feat(simulations): config par tâche + hook useTimer + 7 tests

This commit is contained in:
Hermann_Kitio 2026-04-21 00:16:38 +03:00
parent 869668a1ba
commit 24968f542d
3 changed files with 199 additions and 0 deletions

View file

@ -0,0 +1,52 @@
/**
* Configuration par tâche de simulation : durée et cibles de mots.
*
* Règle H : logique métier regroupée ici, jamais dans les composants UI.
*
* Les valeurs EE viennent des consignes TCF Canada officielles.
* Les valeurs EO sont symboliques (placeholders) seront ajustées quand
* les flux EO seront implémentés côté frontend.
*/
import type { Tache } from '@/entities/production/types'
export interface SimulationConfig {
/** Durée du minuteur en minutes. */
dureeMinutes: number
/** Seuil minimum de mots pour autoriser la soumission. */
motsMin: number
/** Borne basse de la cible TCF. */
motsCibleMin: number
/** Borne haute de la cible TCF. */
motsCibleMax: number
}
const SIMULATION_CONFIG: Record<Tache, SimulationConfig> = {
EE_T1: { dureeMinutes: 10, motsMin: 30, motsCibleMin: 60, motsCibleMax: 120 },
EE_T2: { dureeMinutes: 20, motsMin: 30, motsCibleMin: 120, motsCibleMax: 150 },
EE_T3: { dureeMinutes: 30, motsMin: 30, motsCibleMin: 120, motsCibleMax: 180 },
EO_T1: { dureeMinutes: 5, motsMin: 30, motsCibleMin: 30, motsCibleMax: 80 },
EO_T3: { dureeMinutes: 10, motsMin: 30, motsCibleMin: 60, motsCibleMax: 150 },
}
export function getSimulationConfig(tache: Tache): SimulationConfig {
return SIMULATION_CONFIG[tache]
}
/**
* Compte les mots d'un texte en découpant sur les espaces / caractères blancs.
* Un "mot" = toute séquence non-blanche. Retourne 0 si le texte est vide.
*/
export function countWords(texte: string): number {
const trimmed = texte.trim()
if (trimmed.length === 0) return 0
return trimmed.split(/\s+/).length
}
/** Formate un nombre de secondes en MM:SS (ex. 125 → "02:05"). */
export function formatTimer(secondes: number): string {
const safe = Math.max(0, Math.floor(secondes))
const mm = Math.floor(safe / 60).toString().padStart(2, '0')
const ss = (safe % 60).toString().padStart(2, '0')
return `${mm}:${ss}`
}