S18 Added OR Tools rules for scheduling show
All checks were successful
Build, test and publish / verify (push) Successful in 6m12s
All checks were successful
Build, test and publish / verify (push) Successful in 6m12s
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# School JSON format, version 1
|
||||
# School JSON format, version 3
|
||||
|
||||
Export: `GET /api/dance-schools/{id}/export` downloads readable JSON.
|
||||
Preview: `POST /api/dance-schools/import/preview` accepts the file itself as
|
||||
@@ -11,19 +11,19 @@ There is no merge endpoint.
|
||||
|
||||
```json
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"formatVersion": 3,
|
||||
"key": "1b8fe22c-5ac3-4ab9-a2c8-d1d28d2becee",
|
||||
"name": "Studio",
|
||||
"dancers": [{ "id": "d1", "name": "Sam", "birthDate": "2010-05-12" }],
|
||||
"coaches": [{ "id": "c1", "name": "Alex" }],
|
||||
"coaches": [{ "id": "c1", "name": "Alex", "dancerId": "d1" }],
|
||||
"groups": [{
|
||||
"id": "g1", "category": "Hiphop", "type": "REGULAR",
|
||||
"startAge": 12, "endAge": 18, "styles": ["HIPHOP"],
|
||||
"dancerIds": ["d1"], "coachId": "c1"
|
||||
}],
|
||||
"shows": [{
|
||||
"id": "s1", "name": "Summer show", "date": "2027-06-12",
|
||||
"dayParts": [{ "type": "MORNING", "groupIds": ["g1"] }]
|
||||
"id": "s1", "name": "Summer show", "preferredDayParts": 1, "finalized": false,
|
||||
"dayParts": [{ "date": "2027-06-12", "type": "MORNING", "groupIds": ["g1"] }]
|
||||
}]
|
||||
}
|
||||
```
|
||||
@@ -32,14 +32,20 @@ There is no merge endpoint.
|
||||
inside each collection are nonblank strings, unique within that collection, and
|
||||
local to this file. They can change on export. References must resolve within the
|
||||
file. A dancer or coach can be referenced by multiple groups. A group can appear
|
||||
in multiple day parts. A day-part type can occur once per show.
|
||||
in multiple day parts. A date/type combination can occur once per show, with at most six dayparts.
|
||||
|
||||
All fields are required except `coachId`, which may be absent or null. Collections
|
||||
The optional `coachId` and coach `dancerId` references may be absent or null.
|
||||
`preferredDayParts` defaults to two (one for a single daypart); `finalized`
|
||||
defaults to false. Legacy version 2 files remain supported; version 1 is rejected.
|
||||
Legacy `appearances` counts may be present but do not govern S18 scheduling.
|
||||
Every imported schedule becomes a draft, even when exported as final.
|
||||
`preferredDayParts` must be an integer from one to six; a retained value exceeding
|
||||
the daypart count must be corrected before scheduling or finalization. Collections
|
||||
may be empty. Names/category must be nonblank. Dates use ISO `yyyy-MM-dd`;
|
||||
birth dates cannot be in the future. Ages are nonnegative integers with
|
||||
`startAge <= endAge`. Enum values use the same uppercase names as the management
|
||||
API. Day-part types are `MORNING`, `AFTERNOON`, `EVENING`.
|
||||
Unknown fields, duplicate JSON properties, duplicate IDs or references, invalid
|
||||
Unknown fields, duplicate JSON properties, duplicate IDs or membership references, invalid
|
||||
values and unsupported versions are rejected. Validation is repeated on commit.
|
||||
The entire school is prepared before publishing it under the shared service lock.
|
||||
Replacing retains the numeric school ID for existing browser links; imported
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
# S18 — Scheduling dance groups across a show
|
||||
|
||||
Status: IN_REVIEW
|
||||
|
||||
As a dance school manager,
|
||||
I want OR-Tools to schedule groups and order performances using participation,
|
||||
changing-time and variety rules,
|
||||
so that the complete show is manageable for dancers and enjoyable for audiences.
|
||||
|
||||
Refinement confirmed by the maintainer on 2026-11-03. This specification records
|
||||
the agreed design. Implementation and validation are complete and ready for review.
|
||||
See [validation evidence](../../docs/s18-validation.md) and
|
||||
[the applied scheduling rules](../../show-scheduling-rules.md).
|
||||
|
||||
## Show scope and configuration
|
||||
|
||||
- A show consists of dayparts and can span multiple dates, typically two days.
|
||||
All counts below apply across the entire show, not separately per date.
|
||||
- Each show has one configurable integer `x`, between 1 and the number of
|
||||
dayparts inclusive. Its default is 2, or 1 for a one-daypart show.
|
||||
- This replaces the existing configurable appearance counts per group type.
|
||||
- A show without dayparts can be stored but cannot be scheduled.
|
||||
- If reducing the number of dayparts makes `x` invalid, require the user to
|
||||
correct it before scheduling again; do not silently change it.
|
||||
- Groups without dancers are excluded from scheduling and from all performance
|
||||
counts and showcase-position requirements.
|
||||
|
||||
## Required group appearances
|
||||
|
||||
- Each nonempty REGULAR, SELECTION and PRE_EDUCATION group performs in exactly
|
||||
`x` distinct dayparts, once within each selected daypart.
|
||||
- Each nonempty PRE_SCHOOLER group performs exactly once in the complete show,
|
||||
regardless of `x`. At most two such groups are expected. They can be assigned
|
||||
freely to dayparts; no additional placement restriction applies.
|
||||
- Each nonempty SHOW_CASE group performs exactly once in every daypart.
|
||||
- With at least two showcase groups, each daypart starts with one showcase and
|
||||
ends with another. Additional showcases can appear anywhere between them.
|
||||
Opening and closing groups may differ between dayparts.
|
||||
- With exactly one showcase group, it appears either first or last in each
|
||||
daypart; the planner chooses. It does not perform twice in that daypart.
|
||||
- With no showcase groups, there is no showcase-position requirement.
|
||||
|
||||
## Dancer participation and coaches
|
||||
|
||||
- A dancer without a showcase membership performs in at most `x` distinct
|
||||
dayparts across the complete show. This is a hard constraint.
|
||||
- A showcase participant necessarily performs in all dayparts. Their other
|
||||
group performances may span more than `x` dayparts, but this is undesirable.
|
||||
- For each non-coach showcase participant, count the distinct dayparts in which
|
||||
they perform outside showcases. Their excess is `max(0, count - x)`.
|
||||
Minimize the sum of these excesses as the first optimization priority.
|
||||
- A person dancing in several groups must use the same dancer registration in
|
||||
every group, including when accompanying preschoolers. Up to five group
|
||||
memberships per dancer are expected.
|
||||
- Explicitly link a coach registration to the corresponding dancer registration;
|
||||
never infer identity from matching names. Support maintaining this link.
|
||||
- Coaches are available in all dayparts and are excluded from both the hard
|
||||
dancer limit and the excess penalty, including coaches in showcases.
|
||||
- Being assigned as a group's coach does not automatically mean performing in
|
||||
that group. Actual performances are determined by dancer membership only.
|
||||
Coach availability never increases a group's required appearances.
|
||||
- Dancing coaches remain subject to changing-time rules and contribute to the
|
||||
group's average age just like other dancing members.
|
||||
|
||||
## Changing time and feasibility
|
||||
|
||||
- Between any two performances involving the same dancer within a daypart,
|
||||
there must be at least two intervening performances not involving that dancer.
|
||||
- This is mandatory for everyone, including coaches and showcase participants.
|
||||
- The rule restarts at each daypart boundary. Assume enough changing time
|
||||
between dayparts, including on the same date.
|
||||
- All hard constraints apply together, even for unusual membership combinations
|
||||
such as a person dancing in both preschool and ordinary groups. Do not relax
|
||||
a rule to obtain a result.
|
||||
|
||||
## Balance and optimization priorities
|
||||
|
||||
- Count all scheduled performances, including preschool and showcase groups.
|
||||
- The difference between the largest and smallest daypart performance counts
|
||||
must not exceed two. This is a hard constraint.
|
||||
- Prefer a difference of zero. Preschool groups are an expected cause of
|
||||
differences but have no special exemption or exclusive right to cause them.
|
||||
- Optimize valid schedules in this strict priority order:
|
||||
1. Minimize the total excess for non-coach showcase participants defined above.
|
||||
2. Minimize the difference between largest and smallest daypart counts.
|
||||
3. Improve style and age variety between consecutive performances within
|
||||
each daypart.
|
||||
- A lower priority must not worsen a higher priority. Showcases participate in
|
||||
variety scoring as well.
|
||||
|
||||
## Variety scoring
|
||||
|
||||
- For adjacent groups, the style penalty is the number of shared styles divided
|
||||
by the number of distinct styles in their combined style sets. No shared
|
||||
styles gives zero penalty; two empty style sets also give zero penalty.
|
||||
- Compute dancer ages on the first date of the show. All dancers in a group,
|
||||
including dancing coaches, contribute equally to its average age.
|
||||
- The age penalty decreases linearly from 1 for equal average ages to 0 for a
|
||||
difference of five years; differences greater than five years also score 0.
|
||||
Equivalently: `max(0, 1 - abs(meanAgeA - meanAgeB) / 5)`.
|
||||
- Style and age penalties have equal weight. Minimize their combined penalties
|
||||
over adjacent performances. Empty groups have already been excluded.
|
||||
|
||||
## Solver execution and failure
|
||||
|
||||
- Retain a maximum solver runtime of thirty minutes.
|
||||
- Accept a feasible result without proof of optimality, provided every hard
|
||||
constraint holds. Distinguish feasibility from proven optimality.
|
||||
- If no valid result is found, preserve the existing assignments and order.
|
||||
- Explain whether infeasibility was proven or the time limit expired without
|
||||
a valid result; do not report a timeout as proof of infeasibility.
|
||||
- Retain existing protections against concurrent scheduling and applying stale
|
||||
results after relevant data changes.
|
||||
|
||||
## Manual editing and schedule lifecycle
|
||||
|
||||
- Add UI and API support for moving performances between dayparts and changing
|
||||
their order. Partial or temporarily invalid assignments can be saved as drafts.
|
||||
- Distinguish draft and final schedules explicitly. Display concrete violations
|
||||
for invalid drafts; do not present them as valid final schedules.
|
||||
- Add an explicit finalization action that checks all hard rules and permits
|
||||
finalization only when they all pass. Optimization preferences do not block it.
|
||||
- Automatically generated valid schedules also start as drafts for manager review.
|
||||
- Manual changes to a final schedule return it to draft. Changes to relevant
|
||||
dancer memberships, coach identity links or show settings likewise invalidate
|
||||
final status when they affect scheduling rules.
|
||||
- Treat existing schedules as drafts when introducing this lifecycle.
|
||||
- JSON import preserves assignments and order but makes imported schedules
|
||||
drafts and validates them against the new rules.
|
||||
- JSON export remains available for drafts and finals and preserves status.
|
||||
Import still produces a draft even when the exported status was final.
|
||||
- Include the new configuration and coach identity information in persistence
|
||||
and school JSON round trips so scheduling semantics survive saving and import.
|
||||
|
||||
## Documentation and validation
|
||||
|
||||
- Provide `show-scheduling-rules.md` describing the rules applied by OR-Tools in
|
||||
plain English, including hard constraints, exceptions, optimization priorities,
|
||||
scoring, cross-date scope and failure behavior.
|
||||
- Validate automatic results and finalization using the same agreed rules.
|
||||
- Verification must cover ordinary, preschool and showcase appearances; coach
|
||||
identity and exemptions; overlapping memberships; changing gaps; balance;
|
||||
optimization priority and scoring; multi-date shows; empty groups; invalid
|
||||
configuration; infeasible and timed-out runs; manual drafts/finalization; and
|
||||
persistence/import/export of the new information.
|
||||
Reference in New Issue
Block a user