En resumen la explicación es la siguiente:
El algoritmo hace una primera ronda (con exclusión), es decir, al procesar cada día (D), un grupo que ya tenga un turno de predicación el día D−1 o D+1 queda excluido de los candidatos de ese día. Esto cuenta tanto los turnos preexistentes (asignados manualmente) como los que la propia ejecución va asignando en días anteriores, porque cada asignación se persiste y la elegibilidad se recalcula por día.
El efecto práctico: los turnos de cada grupo quedan espaciados (día 1, día 3, día 5… en vez de día 1 y día 2). Luego, en una segunda ronda (repesca): al terminar todos los días, se repite la pasada completa sin la restricción de días consecutivos, para rellenar la capacidad que haya quedado libre con grupos que aún no han alcanzado su máximo de turnos (maxPreachingShiftsPerGroup). Así se cumple el "evitar si es posible": nadie se queda sin turnos que podría tener solo por culpa de la restricción.