From 9171a2d932dfb07fca916bfecb0ab8720221f0ac Mon Sep 17 00:00:00 2001 From: Wanja Krah Date: Fri, 30 Oct 2026 11:46:06 +0100 Subject: [PATCH] refinement of spec S9 and updated S2 as implemented --- specs/S10_allow-group-exclusion-for-show | 0 ...S11_add-season-context-go-groups-and-shows | 0 .../S12_support-async-feedback-for-scheduling | 0 ...runner-to-allow-scheduling-on-different-pc | 0 .../S2_implement-eslint-for-fe | 2 +- .../S9_spread-dancegroups-via-ortools-setup | 153 ++++++++++++++++++ 6 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 specs/S10_allow-group-exclusion-for-show create mode 100644 specs/S11_add-season-context-go-groups-and-shows create mode 100644 specs/S12_support-async-feedback-for-scheduling create mode 100644 specs/S13_create-runner-to-allow-scheduling-on-different-pc rename specs/{in_review => implemented}/S2_implement-eslint-for-fe (99%) create mode 100644 specs/refined/S9_spread-dancegroups-via-ortools-setup diff --git a/specs/S10_allow-group-exclusion-for-show b/specs/S10_allow-group-exclusion-for-show new file mode 100644 index 0000000..e69de29 diff --git a/specs/S11_add-season-context-go-groups-and-shows b/specs/S11_add-season-context-go-groups-and-shows new file mode 100644 index 0000000..e69de29 diff --git a/specs/S12_support-async-feedback-for-scheduling b/specs/S12_support-async-feedback-for-scheduling new file mode 100644 index 0000000..e69de29 diff --git a/specs/S13_create-runner-to-allow-scheduling-on-different-pc b/specs/S13_create-runner-to-allow-scheduling-on-different-pc new file mode 100644 index 0000000..e69de29 diff --git a/specs/in_review/S2_implement-eslint-for-fe b/specs/implemented/S2_implement-eslint-for-fe similarity index 99% rename from specs/in_review/S2_implement-eslint-for-fe rename to specs/implemented/S2_implement-eslint-for-fe index b37bf46..75e3d01 100644 --- a/specs/in_review/S2_implement-eslint-for-fe +++ b/specs/implemented/S2_implement-eslint-for-fe @@ -1,6 +1,6 @@ # S2 — ESLint for the frontend -Status: IN_REVIEW +Status: IMPLEMENTED Agreed after the grill-me review; shared understanding confirmed. diff --git a/specs/refined/S9_spread-dancegroups-via-ortools-setup b/specs/refined/S9_spread-dancegroups-via-ortools-setup new file mode 100644 index 0000000..d3ffaab --- /dev/null +++ b/specs/refined/S9_spread-dancegroups-via-ortools-setup @@ -0,0 +1,153 @@ +# S9 — Schedule dance groups across show dayparts with OR-Tools + +Status: REFINED + +Agreed after the grill-me review; shared understanding confirmed. + +## User story + +As a dance-school maintainer, I want to assign my school's dance groups to a +show's dated dayparts, using configurable appearance counts per group type, +so that appearances are spread evenly across the show. + +## Show configuration + +- A show can have one to six dayparts across multiple dates. Each daypart has a + date and a type: MORNING, AFTERNOON or EVENING. A date/type combination must be + unique within a show. For example, Friday afternoon, Saturday afternoon and + Saturday evening are three distinct dayparts. +- An unscheduled show may have no dayparts while being configured. +- Daypart dates are the source of truth. Remove the separate editable show date. + Display the range from the earliest to the latest daypart date, or + "No dates configured" when there are none. +- Each show stores an editable appearance count for every dance-group type, + including types with no current groups. Remove the backend + `DanceGroupType.dayPartsRequired` property. +- Initialize counts when creating the show using the following defaults, where + N is the configured number of dayparts: + + | Type | Default appearances | + | --- | --- | + | PRE_SCHOOLER | 1 | + | SHOW_CASE | N | + | PRE_EDUCATION | N | + | All remaining types | min(2, N) | + +- PRE_SCHOOLER's count is editable; one is a default, not a fixed exception. +- Both frontend and backend enforce integer counts greater than zero and no + greater than N for a configured show. With one daypart, all fields display one + and are disabled in the frontend. +- A show without dayparts remains unscheduled; usable counts must be initialized + when its initial daypart configuration becomes available. +- Subsequent daypart edits preserve the saved counts rather than reapplying + defaults. Block saving if a count exceeds the new number of dayparts until + the user corrects it. Adding a daypart does not automatically increase counts. + +## Scheduling rules and objective + +- Use Google OR-Tools in the backend. +- Include every current dance group belonging to the show's school. +- Each group must appear in exactly the number of distinct dayparts configured + for its type. A group cannot appear twice within one daypart. +- Among assignments satisfying those requirements, minimize the difference + between the largest and smallest number of group appearances per daypart. + Count every configured daypart, including an empty one. +- Assign groups to dayparts only. Do not calculate performance order or timing. +- Require at least one school group and one configured daypart. Disable the + scheduling action with an explanation when either is missing, and enforce + the same requirements in the backend. + +## Scheduling action and result handling + +- Provide an explicit "Schedule groups" action clearly indicating that it + replaces the current assignments. A separate preview/accept workflow is + outside this specification. +- Run scheduling synchronously, with a solver time limit of 30 minutes. + For S9, the frontend may remain blocked until the request returns; configure + the request path to accommodate the agreed duration. +- If a valid result is found, save it as a complete replacement of the existing + assignments. This includes a valid result whose optimality has not been proven + when the time limit is reached. +- Distinguish "optimal balance" from "valid result; optimal balance not proven" + in the result presented to the user. +- If validation fails, the problem is infeasible, the solver fails, or the limit + is reached without a valid result, explain the outcome and preserve existing + assignments. Never silently reduce required appearances. +- Disable the scheduling action while a run is pending. The backend must reject + another concurrent run for the same show. +- Before saving, verify that scheduling inputs have not changed during the run. + If they changed, reject the stale result, preserve existing assignments and + explain that the user must run scheduling again. + +## Changes affecting existing schedules + +- Before accepting a potentially invalidating edit, warn that an existing show + schedule may become invalid, name the affected shows and allow cancellation. +- Cover adding/deleting school groups, changing a group's type, changing show + dayparts and changing appearance counts when affected shows have assignments. + Name-only edits do not require this warning. +- After accepting the edit, do not automatically reschedule. Identify schedules + whose assignments no longer meet the appearance requirements and offer the + explicit scheduling action again. +- Newly added groups use their type's saved count on the next scheduling run. + +## JSON import/export + +- Preserve dated dayparts, group assignments and every per-type appearance + setting through JSON export/import. +- Update the format version and validation for the new structure, including + allowing the same daypart type on different dates. +- No legacy export compatibility or migration is required: the application is + still greenfield and no exports have been made. + +## Optional repeatability + +Identical inputs producing identical assignments is a nice-to-have for +testability, not a mandatory scheduling requirement. Spend at most three +minutes investigating how to achieve it. Implement it only if it requires at +most ten additional code statements; otherwise omit it. Changed inputs may +produce different assignments regardless. + +## Out of scope and follow-up specifications + +- Group exclusions: S10_allow-group-exclusion-for-show. +- Season context: S11_add-season-context-go-groups-and-shows. +- Asynchronous scheduling feedback: S12_support-async-feedback-for-scheduling. +- Scheduling on another PC: S13_create-runner-to-allow-scheduling-on-different-pc. +- Availability restrictions, pinned assignments, capacity limits, shared-dancer + constraints, duration/audience balancing and performance ordering. + +S10–S13 are intentionally empty placeholders and are to be refined separately. + +## Acceptance criteria + +- [ ] Configure up to six dated dayparts, reject duplicate date/type combinations + and derive the displayed show date range from them. +- [ ] Persist editable per-type counts with the agreed defaults, remove the + backend type-level property and validate counts in frontend and backend. +- [ ] With one daypart, every count is one and frontend fields are disabled. +- [ ] Daypart edits preserve configured counts and require correction of counts + that exceed the new number of dayparts. +- [ ] OR-Tools assigns every school group to exactly its type's required number + of distinct dayparts and minimizes the busiest/quietest appearance gap. +- [ ] Scheduling requires groups and dayparts and replaces assignments only after + a successful, current result. +- [ ] The synchronous request supports a 30-minute solver limit, accepts valid + unproven results and communicates whether optimality was proven. +- [ ] Failed, infeasible, stale and no-result runs preserve existing assignments + and explain why no replacement was saved. +- [ ] Duplicate concurrent runs for a show are prevented in frontend and backend. +- [ ] Potentially invalidating edits warn beforehand, identify affected shows, + permit cancellation and expose invalid schedules afterward without + automatically rescheduling. +- [ ] New-format JSON round-trips dates, assignments and all type settings; + legacy import support is not required. +- [ ] Any repeatability work respects both the three-minute investigation limit + and the ten-additional-statement implementation limit. + +## Implementation handoff + +This specification records agreed behavior; it does not implement scheduling. +The current application uses in-memory storage with JSON import/export for +transfer. S9 adds the scheduling model, frontend controls, backend operation and +JSON changes within that existing persistence approach.