Pseudocódigo
Definir inicioEvento, fimEvento, toleranciaSegundos
Para cada participante em participantes:
- Ajustar cada intervalo: s = max(intervalo.inicio, inicioEvento); e = min(intervalo.fim, fimEvento)
- Manter intervalos onde e > s
- Ordenar intervalos por s
- Mesclar intervalos: se próximo.s - atual.fim <= toleranciaSegundos então atual.fim = max(atual.fim, próximo.fim) senão adicionar atual ao mesclados e atual = próximo
- Adicionar último atual a mesclados
- Se mesclados não vazio e mesclados[0].inicio <= inicioEvento e mesclados[-1].fim >= fimEvento então enviarEmailAgradecimento(participante.email, participante.id)
Código em Java:
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Main {
static class Intervalo {
Instant inicio;
Instant fim;
Intervalo(Instant inicio, Instant fim) { this.inicio = inicio; this.fim = fim; }
}
static class Participante {
String id;
String email;
List<Intervalo> intervalos = new ArrayList<>();
Participante(String id, String email) { this.id = id; this.email = email; }
}
static List<Intervalo> mesclarIntervalos(List<Intervalo> lista, long toleranciaMillis) {
List<Intervalo> resultado = new ArrayList<>();
if (lista.isEmpty()) return resultado;
List<Intervalo> ordenada = new ArrayList<>(lista);
Collections.sort(ordenada, Comparator.comparing(i -> i.inicio));
Intervalo atual = ordenada.get(0);
for (int i = 1; i < ordenada.size(); i++) {
Intervalo proximo = ordenada.get(i);
long lacunaMillis = proximo.inicio.toEpochMilli() - atual.fim.toEpochMilli();
if (lacunaMillis <= toleranciaMillis) {
atual.fim = atual.fim.isAfter(proximo.fim) ? atual.fim : proximo.fim;
} else {
resultado.add(atual);
atual = proximo;
}
}
resultado.add(atual);
return resultado;
}
static boolean cobreTodoEvento(List<Intervalo> mesclados, Instant inicioEvento, Instant fimEvento, long toleranciaSegundos) {
if (mesclados.isEmpty()) return false;
Intervalo primeiro = mesclados.get(0);
Intervalo ultimo = mesclados.get(mesclados.size() - 1);
return !primeiro.inicio.isAfter(inicioEvento) && !ultimo.fim.isBefore(fimEvento);
}
public static void main(String[] args) {
Instant inicioEvento = Instant.parse("2025-10-03T18:00:00Z");
Instant fimEvento = Instant.parse("2025-10-03T19:30:00Z");
long toleranciaSegundos = 5;
Participante p1 = new Participante("usuario1", "u1@exemplo.com");
p1.intervalos.add(new Intervalo(Instant.parse("2025-10-03T18:00:00Z"), Instant.parse("2025-10-03T19:30:00Z")));
Participante p2 = new Participante("usuario2", "u2@exemplo.com");
p2.intervalos.add(new Intervalo(Instant.parse("2025-10-03T18:00:10Z"), Instant.parse("2025-10-03T18:45:00Z")));
p2.intervalos.add(new Intervalo(Instant.parse("2025-10-03T18:46:00Z"), Instant.parse("2025-10-03T19:30:00Z")));
Participante p3 = new Participante("usuario3", "u3@exemplo.com");
p3.intervalos.add(new Intervalo(Instant.parse("2025-10-03T18:10:00Z"), Instant.parse("2025-10-03T19:20:00Z")));
List<Participante> participantes = List.of(p1, p2, p3);
long toleranciaMillis = Duration.ofSeconds(toleranciaSegundos).toMillis();
for (Participante participante : participantes) {
List<Intervalo> validos = new ArrayList<>();
for (Intervalo it : participante.intervalos) {
Instant s = it.inicio.isBefore(inicioEvento) ? inicioEvento : it.inicio;
Instant e = it.fim.isAfter(fimEvento) ? fimEvento : it.fim;
if (e.isAfter(s)) validos.add(new Intervalo(s, e));
}
List<Intervalo> mesclados = mesclarIntervalos(validos, toleranciaMillis);
boolean elegivel = cobreTodoEvento(mesclados, inicioEvento, fimEvento, toleranciaSegundos);
if (elegivel) {
System.out.println("Email de agradecimento enviado para: " + participante.id);
} else {
System.out.println("Não elegível: " + participante.id);
}
}
}
}