Implementado (3 features)

**Agrupamento de faltantes contíguos** (`detector_sequencia.rs`)
- Nova função pública `agrupar_contiguos(&[u64]) -> Vec<(u64, u64)>` com
  4 testes
- Na tela de resultado, faltantes agora aparecem como `• 100–104 (5
  notas)` em vez de 5 linhas separadas

**Estatísticas de completude** (`resultado.rs`)
- Cada série exibe: `Série 001 — 10 faltante(s) — 990/1000 notas (99.0%
  completo):`

**Copiar para clipboard** (`resultado.rs`)
- Botão `📋 Copiar` ao lado de cada série nos faltantes — copia todos os
  números (não só a página atual)
- Botão `📋 Copiar` nas duplicatas — copia no formato `1234 (3x), 5678
  (2x)`

Total: **42 → 46 testes**, todos passando.
This commit is contained in:
FelipeCN
2026-03-03 16:41:32 -03:00
parent 2c96e99ccc
commit b9052e073f
21 changed files with 558 additions and 778 deletions
+50 -1
View File
@@ -67,6 +67,32 @@ pub fn detectar_faltantes(notas: &[&Nota]) -> Vec<u64> {
faltantes
}
/// Agrupa uma lista **ordenada** de faltantes em intervalos contíguos.
///
/// Retorna pares `(inicio, fim)`. Números isolados têm `inicio == fim`.
///
/// # Exemplo
/// `[1, 2, 3, 5, 8, 9]` → `[(1, 3), (5, 5), (8, 9)]`
pub fn agrupar_contiguos(faltantes: &[u64]) -> Vec<(u64, u64)> {
if faltantes.is_empty() {
return Vec::new();
}
let mut grupos = Vec::new();
let mut inicio = faltantes[0];
let mut anterior = faltantes[0];
for &num in &faltantes[1..] {
if num != anterior + 1 {
grupos.push((inicio, anterior));
inicio = num;
}
anterior = num;
}
grupos.push((inicio, anterior));
grupos
}
#[cfg(test)]
mod tests {
use super::*;
@@ -74,7 +100,7 @@ mod tests {
use rust_decimal::Decimal;
fn nota(numero: u64) -> Nota {
Nota::new(numero, "001".to_string(), None, None)
Nota::new(numero, "001".to_string(), None, None, None)
}
#[test]
@@ -136,4 +162,27 @@ mod tests {
let refs: Vec<&Nota> = notas.iter().collect();
assert_eq!(detectar_faltantes(&refs), Vec::<u64>::new());
}
#[test]
fn agrupar_vazio() {
assert_eq!(agrupar_contiguos(&[]), Vec::<(u64, u64)>::new());
}
#[test]
fn agrupar_isolados() {
assert_eq!(agrupar_contiguos(&[1, 3, 5]), vec![(1, 1), (3, 3), (5, 5)]);
}
#[test]
fn agrupar_um_intervalo() {
assert_eq!(agrupar_contiguos(&[1, 2, 3]), vec![(1, 3)]);
}
#[test]
fn agrupar_misto() {
assert_eq!(
agrupar_contiguos(&[1, 2, 3, 5, 8, 9]),
vec![(1, 3), (5, 5), (8, 9)]
);
}
}