diff --git a/CHANGELOG.md b/CHANGELOG.md index 0202ded..2e3222a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## Upcoming release +- Demo: period labels now group the per-day-of-week entries of a hint and + condense consecutive weekdays into a range, e.g. « Vacances scolaires + (lun-sam) : du lundi au samedi + samedis » instead of one « … — lundis » + entry per weekday. Applies to the period cards and the calendar legend. + - Demo: new « Sous le capot » section under the results with two collapsible, syntax-highlighted (Prism) snippets: the exact `findCalendarPeriods` call of the current analysis — real hints and options included — as a runnable diff --git a/website/src/components/ResultsView.tsx b/website/src/components/ResultsView.tsx index 29b82a3..edab6ae 100644 --- a/website/src/components/ResultsView.tsx +++ b/website/src/components/ResultsView.tsx @@ -1,6 +1,6 @@ import { useMemo } from 'react' import type { CalendarHintsResult, HintResult, Period } from '../../../src/calendar-hints' -import { buildDayTypes, dayTypeBackground, frLabel, type DayTypeStyle } from '../day-types' +import { buildDayTypes, dayTypeBackground, frLabel, periodLabel, type DayTypeStyle } from '../day-types' import { eachDay, type GeneratedHints } from '../hints' import CalendarGrid from './CalendarGrid' @@ -50,7 +50,7 @@ function PeriodCard({ period, style }: { period: Period; style: DayTypeStyle })
- {period.labels.map(frLabel).join(' + ')} + {periodLabel(period.labels)}
{period.days.length} jours ({period.days[0]} → {period.days[period.days.length - 1]}) —{' '} diff --git a/website/src/day-types.ts b/website/src/day-types.ts index 0bac026..93aecaf 100644 --- a/website/src/day-types.ts +++ b/website/src/day-types.ts @@ -23,6 +23,61 @@ export function frLabel(label: string): string { return LABEL_FR.reduce((s, [en, fr]) => s.replaceAll(en, fr), label) } +// Libellé d'une période : les labels « Hint — Mondays + Hint — Tuesdays + … » +// issus de la politique per-day-of-week sont regroupés par hint, et les jours +// consécutifs condensés en « du lundi au samedi ». Semaine à la française, +// lundi en tête. +const WEEKDAYS_EN = ['Mondays', 'Tuesdays', 'Wednesdays', 'Thursdays', 'Fridays', 'Saturdays', 'Sundays'] +const WEEKDAYS_FR = ['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche'] + +function frWeekdays(indices: number[]): string { + const sorted = [...new Set(indices)].sort((a, b) => a - b) + const runs: number[][] = [] + for (const i of sorted) { + const run = runs[runs.length - 1] + if (run && i === run[run.length - 1] + 1) run.push(i) + else runs.push([i]) + } + return runs + .map(run => { + if (run.length === 7) return 'tous les jours' + if (run.length >= 3) return `du ${WEEKDAYS_FR[run[0]]} au ${WEEKDAYS_FR[run[run.length - 1]]}` + return run.map(i => `${WEEKDAYS_FR[i]}s`).join(' + ') + }) + .join(' + ') +} + +export function periodLabel(labels: string[]): string { + // Groupes dans l'ordre de première apparition ; ceux issus d'un même hint + // per-day-of-week (même préfixe avant « — jour ») fusionnent leurs jours. + const groups: { prefix: string | null; weekdays: number[] }[] = [] + const byPrefix = new Map() + for (const label of labels) { + const sep = label.lastIndexOf(' — ') + const weekday = sep >= 0 ? WEEKDAYS_EN.indexOf(label.slice(sep + 3)) : -1 + if (weekday < 0) { + groups.push({ prefix: frLabel(label), weekdays: [] }) + continue + } + // « Remaining days — lundis » s'affiche sans préfixe, comme frLabel + const prefix = label.slice(0, sep) === 'Remaining days' ? null : frLabel(label.slice(0, sep)) + let group = byPrefix.get(prefix ?? '') + if (!group) { + group = { prefix, weekdays: [] } + byPrefix.set(prefix ?? '', group) + groups.push(group) + } + group.weekdays.push(weekday) + } + return groups + .map(g => { + if (g.weekdays.length === 0) return g.prefix + const days = frWeekdays(g.weekdays) + return g.prefix === null ? days : `${g.prefix} : ${days}` + }) + .join(' + ') +} + // Palette stable ; quand elle boucle, le motif change — 12 × 4 = 48 styles // distincts avant répétition, largement au-delà du nombre de signatures d'un // feed réel. @@ -110,7 +165,7 @@ export function buildDayTypes(result: CalendarHintsResult, orderedPeriods: Perio return { signature, style: styleOf(i), - label: period ? period.labels.map(frLabel).join(' + ') : 'non classé', + label: period ? periodLabel(period.labels) : 'non classé', dayCount: dayCounts.get(signature) ?? 0, unclassifiedCount: group?.days.length ?? 0, tripCount: period?.tripCount ?? group?.tripCount ?? 0,