Files
vac-optimizer/docs/statistics.md
T

18 KiB

Plan Statistics Popup

Local development draft for issue #3 and issue #29, within milestone V1 stats. The behavior below consolidates the decisions confirmed during grill-with-docs; proposals and remaining presentation choices are identified separately.

Problem Statement

The person planning leave can already see newly placed leave, non-working-day gain, and the longest work sequence in the calendar summary. They cannot assess average working stretches, the average and longest full breaks, or how much leave their rules earn in one view. They also need to spot undesirable full weeks in which they must work only one day and see exactly when those workdays occur.

The statistics page requested by #3 and the popup requested by #29 describe the same need. Their shared scope needs precise metric definitions so calendar dates, leave consumption, earned entitlements, and days remaining to work are not confused.

Solution

Provide one statistics popup opened from the calendar. It summarizes the most recent calculated valid plan, including a valid plan retained by a cancelled or interrupted calculation, using that calculation's submitted inputs and Europe/Paris calendar date.

The popup presents nine metrics, a breakdown of earned leave by generating rule, and dated warnings for weeks with one workday. Its figures describe the calculated result and become available with the valid outcome, independently of calculation-trace delivery. Input edits and trace or counterfactual exploration leave those figures attached to the producing calculation until a new outcome arrives.

User Stories

  1. As a person planning leave, I want one statistics popup from the calendar, so that I can assess the calculated plan in context. This single feature fulfils both #3 and #29.
  2. As a person planning leave, I want the following nine metrics with their units and meanings, so that I can distinguish leave consumption from calendar time off and days remaining to work.
Metric Agreed definition
Newly placed leave days Number of leave placement dates in the calculated plan. Declared non-working days are excluded from this consumption count.
Non-working-day gain Distinct weekend and public-holiday dates in planned time-off periods, including adjacent dates outside the horizon. A date contributes once even if it is both a weekend and a public holiday.
Average work-sequence length Arithmetic mean working-day length of all non-empty work sequences inside the horizon, including both horizon edges. Weekends and public holidays neither count nor split a sequence.
Longest work-sequence length Greatest working-day length of any work sequence inside the horizon, including both horizon edges. This retains the metric already requested by #28.
Average time-off period length Arithmetic mean calendar-day duration of all planned time-off periods, using their full spans, including adjacent non-working dates outside the horizon.
Longest time-off period length Greatest calendar-day duration among the same planned time-off periods.
Earned leave Gross quantity of earned leave entitlements generated by all applicable rules for this plan and becoming available strictly after its calculation date. Includes entitlements becoming available after the horizon and days subsequently consumed.
Public holidays connected to a weekend Number of distinct Monday-to-Friday public-holiday dates in planned time-off periods containing at least one Saturday or Sunday. Includes connections through placed or declared leave and adjacent holiday dates outside the horizon.
Weeks with one workday Number of Monday-to-Sunday weeks with exactly one working day remaining after leave placements and declared non-working days. All five Monday-to-Friday dates must lie inside the horizon.
  1. As a person planning leave, I want declared non-working days to contribute to time-off periods, interrupt work sequences, and remove days remaining to work, so that existing bookings are reflected without consuming a remaining balance again. This includes plans with declarations and no new placements.
  2. As a person planning leave, I want averages to reflect actual sequences and complete breaks, so that artificial zero-length gaps and leave-only counts do not distort them. Work sequences of 10, 5, and 15 working days average 10; Friday and Monday off in a holiday-free interval form one 4-calendar-day time-off period.
  3. As a person planning leave, I want earned leave grouped by its generating rule, using that calculation's rule names, so that I can see contributions from Samedi Malin and every other rule that earns leave. Repeated eligible occurrences contribute their generated quantities; the breakdown sums to the total.
  4. As a person planning leave, I want earned leave counted before consumption, so that a plan earning 3 days and using 2 still reports 3 earned days. Fully consumed earned entitlements must remain represented in the total and breakdown.
  5. As a person planning leave, I want the earned-leave cutoff fixed to the calculation's Europe/Paris date, so that historical earnings already included in reported balances are excluded. Availability on or before that date is excluded; availability afterward is included, even beyond the horizon. Pending input edits or a later calendar date do not reinterpret the existing result.
  6. As a person planning leave, I want weekday holidays connected through leave to count as well as directly adjacent holidays, so that a Tuesday public holiday joined to a weekend by Monday off is included. Saturday and Sunday public holidays are excluded from this metric. Naturally long weekends with no leave placement or declared non-working day are excluded; a qualifying planned time-off period must contain at least one such day.
  7. As a person planning leave, I want adjacent holidays beyond the horizon included when they belong to a qualifying time-off period, so that a Friday placement before a weekend and a Monday holiday outside the horizon still reports that holiday.
  8. As a person planning leave, I want weeks with one workday highlighted as undesirable patterns, so that I can find when they happen. When the count is positive, show the matching weeks and the exact date of each lone workday. Weeks with zero or two remaining workdays do not qualify, even if a week with two workdays contains separate one-day work sequences.
  9. As a person planning leave, I want partial workweeks at the horizon edges excluded from these warnings, so that clipped dates cannot create false one-workday weeks. A week whose Monday-to-Friday dates are all inside the horizon qualifies even if its weekend lies outside it.
  10. As a person planning leave, I want statistics for a valid retained partial plan to carry a prominent "Partial plan" label, so that I do not mistake unfinished optimization for a complete result. Invalid input, a planning conflict, and an incomplete calculation without a valid retained plan expose no plan statistics.
  11. As a person planning leave, I want the figures and rule names to remain attached to the calculated plan while I edit inputs or inspect historical trace steps or hypothetical alternatives, so that I see one coherent result. A new planning outcome replaces or clears the statistics; late replies from older calculations cannot overwrite them.
  12. As a person planning leave, I want statistics available when the valid plan is displayed even if its trace is pending or fails, so that optional diagnostic delivery does not block the summary.
  13. As a keyboard or mobile user, I want a readable popup with labelled controls, visible focus, keyboard dismissal, and focus restored on close, so that I can use it with the application's existing interaction and language settings.

Implementation Decisions

  • Agreed: Extend calendar-result presentation with one popup. Its nine metrics describe the latest calculated valid plan or retained valid partial plan. Opening it does not run another optimization or mutate placements, balances, declarations, or rules.
  • Agreed: Use the producing calculation's outcome and immutable submitted horizon, balances, rules, declarations, and calculation date. Capture the Europe/Paris calculation date once and retain it with the calculation. Rule attribution uses generating rule identity and that run's rule names, including after a rule is renamed or deleted from pending inputs.
  • Agreed: Preserve the half-open planning horizon and inclusive selected last planning date. Work sequences and qualifying workweeks are measured within that horizon; time-off periods retain their full adjacent non-working spans. Support past and multi-year horizons under the existing calendar contract.
  • Agreed: Statistics are derived from the final or retained valid state of the producing calculation. Candidate evaluations, rejected branches, provisional earnings, and hypothetical alternative plans do not contribute. Trace or explanation readiness and failure are independent of statistics availability.
  • Agreed: Reuse the planner's working-day, French public-holiday, period, and entitlement definitions. Public holidays connected to weekends are a date count, distinct from the weighted public-holiday week value used in optimization. Weeks with one workday are full-workweek diagnostics, distinct from short work sequences.
  • Integration proposal: Keep metric derivation calculation-owned and presentation thin. Reuse existing outcome facts where sufficient; extend the public planning result or calculation metadata only for missing facts, notably the fixed calculation date and reliable gross earned quantities with generating-rule attribution, including fully consumed entitlements. Carry those facts with complete outcomes and retained partial plans through worker delivery and cancellation checkpoints. Do not reconstruct them from trace history or infer their identity by parsing balance IDs.
  • Presentation proposal: Reuse the existing Angular Material dialog, translation service, date formatting, and styling patterns. No new dialog, chart, or date dependency is needed. The exact derived-statistics record shape and division between planner-owned facts and presentation calculations remain implementation choices; no extra public interface is required solely for testing.

Testing Decisions

Use behavior-level tests that assert returned planning facts and user-visible figures, dates, labels, and lifecycle behavior. Avoid tests coupled to aggregation loops, candidate ordering, private helpers, or dialog component structure.

  • Extend the existing public planner and calculation-context tests for reliable earned metadata and metric derivation where exposed. Use fixed date-only horizons, controlled Europe/Paris calculation dates, and complete requests; do not depend on the real clock. Existing cases for merged periods, shared rules, earned-entitlement chains, immutable snapshots, and boundary dates provide prior art.
  • Cover work and time-off metrics with fractional averages, both horizon-edge work sequences, consecutive leave dates without an intervening work sequence, weekends and holidays that do not split work sequences, and declared-day-only periods. Verify work lengths in working days and break lengths in calendar days. Saved declarations outside the horizon must not inflate in-horizon work counts or weekly warnings.
  • Cover earned leave with 3 days earned and 2 consumed, a fully consumed entitlement absent from remaining balances, multiple generating rules, repeated occurrences, and distinct rules sharing placements. Verify acquisition before, on, and after the fixed calculation date, acquisition after the horizon, and the finalized availability date after the complete generating period. Use current rule names changed after submission to prove that the original attribution remains stable.
  • Cover the holiday count with direct Monday/Friday connections, a Tuesday holiday joined by Monday off, a weekday-only break that reaches no weekend, Saturday/Sunday holidays, a naturally long weekend without placed or declared leave, duplicate calendar-date contributions, and an adjacent holiday outside the horizon.
  • Cover one-workday warnings with four weekdays off and one remaining workday, zero-workday and two-workday weeks, separate one-day work sequences inside a two-workday week, partial horizon-edge weeks, a horizon including all weekdays but excluding the weekend, and weeks spanning month or year boundaries. Assert both the count and the displayed week and lone-workday dates.
  • Extend CalendarYear's existing planning-outcome tests for popup access, the nine rendered metrics, rule breakdown, warning rows, and the partial-plan label. Existing summary assertions, adjacent-year context dates, immutable submitted inputs, stale-outcome rejection, accessible comparison dialogs, and delayed or failed trace delivery provide prior art. Include replacement by an outcome without a valid plan so previous statistics cannot remain visible as current.
  • Extend existing worker transport and real cancellation tests for any new result facts: complete and retained partial outcomes must preserve those facts, and trace delay or failure must not remove them. Verify metadata matches the actual retained plan, rather than the latest evaluated candidate or an abandoned branch.
  • Check keyboard opening, dismissal, restored focus, meaningful labels and units, localized dates, and readable mobile layout using the existing UI testing patterns. Exercise a valid plan with no periods or no work sequences; keep its data state distinct from an outcome without a valid plan, and verify the chosen empty-value display once that presentation convention is adopted.
  • Run the repository's existing tests, lint, formatting, type checks, and production build when implementing the feature. No new test framework or speculative benchmark suite is required.

Out of Scope

  • A separate statistics page, saved plan history, or comparisons between separate planning results.
  • Changing the planning objective order or automatically moving leave to eliminate weeks with one workday. This feature makes those weeks visible.
  • Reconstructing historical earned leave already represented in reported balances, or treating weekend public holidays as additional weekday holiday gain.
  • New rule families, working calendars, accounts, backend synchronization, or employer integration.

Further Notes

  • Scope references: #3 and #29 describe the shared popup; #7 supplies the average work-sequence requirement; #8 supplies earned leave; #9 supplies public holidays connected to weekends; #28's longest work-sequence metric already exists. The discussion adds average and longest time-off period lengths and dated one-workday-week warnings. Existing planner and calculation-performance work in the milestone remains the baseline.
  • Domain definitions are maintained in CONTEXT.md. Relevant architectural constraints are the personal client-side planner, separate calculation outcome and trace, selected horizons and cancellation, and declared days and reported balances.
  • Current integration gaps: The inspected outcome exposes placements, periods, remaining balances, and several quality metrics, but no dedicated gross earned-leave summary or fixed calculation date. Remaining balances omit fully consumed entitlements. Declared-day support is in progress in the working tree: declarations are carried with outcomes, while the inspected period and work-sequence calculations still use placements alone. Coordinate with #13's finalized semantics before relying on those values; avoid a second conflicting calendar model in the popup.
  • Proposed empty-value convention, not explicitly confirmed: Counts show 0 when there are no qualifying items. An average with no samples, or longest time-off period length when no periods exist, shows "—". The existing longest work-sequence length remains 0 when there are no work sequences. Empty samples should remain distinguishable from a measured zero in the underlying data.
  • Remaining presentation choices: Exact decimal precision for averages, metric layout, and whether eligible rules with zero earnings receive breakdown rows were not decided. These do not change the agreed counting or date rules. Use existing presentation conventions and keep any selected defaults explicit during implementation.