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:
@@ -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)]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user