@ttt-productions/q-core 0.1.14 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants/sports.d.ts +1 -0
- package/dist/constants/sports.d.ts.map +1 -1
- package/dist/constants/sports.js +1 -0
- package/dist/constants/sports.js.map +1 -1
- package/dist/types/stats.d.ts +1 -1
- package/dist/types/stats.d.ts.map +1 -1
- package/dist/types/stats.js +3 -0
- package/dist/types/stats.js.map +1 -1
- package/package.json +1 -1
|
@@ -47,6 +47,7 @@ export declare const STATS_MIGRATION_OPERATION_ID = "migration";
|
|
|
47
47
|
export declare const STATS_MIGRATION_CORRECTION_REASON = "The recorded result differs from what its recorded plays add up to; this correction keeps the recorded result.";
|
|
48
48
|
export declare const GAME_REPAIR_REFUSAL_COPY: {
|
|
49
49
|
readonly eventUnreadable: "One of this game's recorded stats can no longer be read. Fix the event in the console, then repair the game.";
|
|
50
|
+
readonly eventSequenceGap: "This game's recorded stats are numbered with a gap or a repeat. Fix the event documents in the console, then restore the game.";
|
|
50
51
|
readonly sourcesDisagree: "This game's record, its stored numbers, and its recorded stats all disagree, so nothing says what was applied. Fix the game in the console first.";
|
|
51
52
|
readonly scoreAmbiguous: "The team's score was edited in two places to different values. Enter the score you want as a correction instead.";
|
|
52
53
|
readonly fieldNotCorrectable: "That number cannot be corrected for this sport. Restore the game from its recorded stats, or reopen it and score it again.";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sports.d.ts","sourceRoot":"","sources":["../../src/constants/sports.ts"],"names":[],"mappings":"AAyBA,eAAO,MAAM,+BAA+B;;;;;;;;CAQgB,CAAC;AAI7D,eAAO,MAAM,gCAAgC;;;;CAIe,CAAC;AAG7D,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAGtC,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAI1C,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAG7C,eAAO,MAAM,iCAAiC,MAAM,CAAC;AAGrD,eAAO,MAAM,+BAA+B,MAAM,CAAC;AAGnD,eAAO,MAAM,kCAAkC,MAAM,CAAC;AAGtD,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAG3C,eAAO,MAAM,6BAA6B;;;;;CAKgB,CAAC;AAI3D,eAAO,MAAM,wBAAwB,2CAA2C,CAAC;AAIjF,eAAO,MAAM,0BAA0B,8CAA8C,CAAC;AAGtF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;CAeqB,CAAC;AAK1D,eAAO,MAAM,4BAA4B,cAAc,CAAC;AACxD,eAAO,MAAM,iCAAiC,mHACoE,CAAC;AAGnH,eAAO,MAAM,wBAAwB
|
|
1
|
+
{"version":3,"file":"sports.d.ts","sourceRoot":"","sources":["../../src/constants/sports.ts"],"names":[],"mappings":"AAyBA,eAAO,MAAM,+BAA+B;;;;;;;;CAQgB,CAAC;AAI7D,eAAO,MAAM,gCAAgC;;;;CAIe,CAAC;AAG7D,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAGtC,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAI1C,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAG7C,eAAO,MAAM,iCAAiC,MAAM,CAAC;AAGrD,eAAO,MAAM,+BAA+B,MAAM,CAAC;AAGnD,eAAO,MAAM,kCAAkC,MAAM,CAAC;AAGtD,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAG3C,eAAO,MAAM,6BAA6B;;;;;CAKgB,CAAC;AAI3D,eAAO,MAAM,wBAAwB,2CAA2C,CAAC;AAIjF,eAAO,MAAM,0BAA0B,8CAA8C,CAAC;AAGtF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;CAeqB,CAAC;AAK1D,eAAO,MAAM,4BAA4B,cAAc,CAAC;AACxD,eAAO,MAAM,iCAAiC,mHACoE,CAAC;AAGnH,eAAO,MAAM,wBAAwB;;;;;;;;;CAaiB,CAAC;AAGvD,eAAO,MAAM,4BAA4B;;;;CAOiB,CAAC;AAG3D,eAAO,MAAM,2BAA2B;;CAEuB,CAAC;AAIhE,eAAO,MAAM,kCAAkC,wBAAyB,CAAC;AACzE,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,kCAAkC,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
package/dist/constants/sports.js
CHANGED
|
@@ -71,6 +71,7 @@ export const STATS_MIGRATION_CORRECTION_REASON = 'The recorded result differs fr
|
|
|
71
71
|
// What an admin reads when Fix stats refuses a game repair.
|
|
72
72
|
export const GAME_REPAIR_REFUSAL_COPY = {
|
|
73
73
|
eventUnreadable: "One of this game's recorded stats can no longer be read. Fix the event in the console, then repair the game.",
|
|
74
|
+
eventSequenceGap: "This game's recorded stats are numbered with a gap or a repeat. Fix the event documents in the console, then restore the game.",
|
|
74
75
|
sourcesDisagree: "This game's record, its stored numbers, and its recorded stats all disagree, so nothing says what was applied. Fix the game in the console first.",
|
|
75
76
|
scoreAmbiguous: "The team's score was edited in two places to different values. Enter the score you want as a correction instead.",
|
|
76
77
|
fieldNotCorrectable: "That number cannot be corrected for this sport. Restore the game from its recorded stats, or reopen it and score it again.",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sports.js","sourceRoot":"","sources":["../../src/constants/sports.ts"],"names":[],"mappings":"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","sourcesContent":["// Sport rule values that are persisted or validated on both sides of the boundary. What a sport\n// DOES with them — applying an event, recomputing a score — belongs to its adapter (SPORT-003).\n\nimport {\n BASKETBALL_ASSIST_EVENT_TYPE,\n BASKETBALL_BULK_EDIT_EVENT_TYPE,\n BASKETBALL_ONE_POINT_EVENT_TYPE,\n BASKETBALL_REBOUND_EVENT_TYPE,\n BASKETBALL_THREE_POINT_EVENT_TYPE,\n BASKETBALL_TIMEOUT_EVENT_TYPE,\n BASKETBALL_TWO_POINT_EVENT_TYPE,\n FOOTBALL_BULK_EDIT_EVENT_TYPE,\n FOOTBALL_ONE_POINT_EVENT_TYPE,\n FOOTBALL_SIX_POINT_EVENT_TYPE,\n FOOTBALL_TWO_POINT_EVENT_TYPE,\n} from '../types/sports.js';\nimport type { BasketballPlayerStatKey, BasketballStatEventType, FootballStatEventType } from '../types/sports.js';\nimport type {\n FinalizationNotReadyReason,\n GameRepairRefusal,\n StatEventRefusalCode,\n StatsIntegrityRefusal,\n} from '../types/stats.js';\n\n// Points a basketball stat event adds to its team's score. BULK_EDIT carries its own `value`.\nexport const BASKETBALL_POINTS_BY_EVENT_TYPE = {\n [BASKETBALL_ONE_POINT_EVENT_TYPE]: 1,\n [BASKETBALL_TWO_POINT_EVENT_TYPE]: 2,\n [BASKETBALL_THREE_POINT_EVENT_TYPE]: 3,\n [BASKETBALL_REBOUND_EVENT_TYPE]: 0,\n [BASKETBALL_ASSIST_EVENT_TYPE]: 0,\n [BASKETBALL_TIMEOUT_EVENT_TYPE]: 0,\n [BASKETBALL_BULK_EDIT_EVENT_TYPE]: 0,\n} as const satisfies Record<BasketballStatEventType, number>;\n\n// Basketball fantasy points (FP): each player counter times its weight. Every weight is a multiple\n// of one half, so FP summed across games equals FP of the summed counters exactly.\nexport const BASKETBALL_FANTASY_POINT_WEIGHTS = {\n points: 1,\n rebounds: 1.5,\n assists: 2,\n} as const satisfies Record<BasketballPlayerStatKey, number>;\n\n// A curling game is this many rounds; `roundScores` has exactly this many slots.\nexport const CURLING_ROUND_COUNT = 14;\n\n// A scored curling round is worth 1..MAX; a blank end is 0.\nexport const MAX_CURLING_ROUND_POINTS = 4;\n\n// The most events one scoring write may carry: each event is a document created in the write's one\n// transaction, and a Firestore transaction commits at most 500 writes.\nexport const MAX_STAT_EVENTS_PER_WRITE = 200;\n\n// The most lines and fields one Correct a game call may set; a game holds far fewer.\nexport const MAX_GAME_STATS_CORRECTION_TARGETS = 200;\n\n// The most destination changes one rebuild call lists in its answer; the audit events record all.\nexport const MAX_STATS_REPAIR_LISTED_CHANGES = 500;\n\n// The most findings one stats check keeps on its report; every finding is still counted by kind.\nexport const MAX_STATS_VALIDATION_DISCREPANCIES = 500;\n\n// The most events one page of a completed game's finalized record holds.\nexport const STAT_HISTORY_PAGE_SIZE = 1000;\n\n// Points a football stat event adds to its team's score. FOOTBALL_BULK_EDIT carries its own `value`.\nexport const FOOTBALL_POINTS_BY_EVENT_TYPE = {\n [FOOTBALL_SIX_POINT_EVENT_TYPE]: 6,\n [FOOTBALL_TWO_POINT_EVENT_TYPE]: 2,\n [FOOTBALL_ONE_POINT_EVENT_TYPE]: 1,\n [FOOTBALL_BULK_EDIT_EVENT_TYPE]: 0,\n} as const satisfies Record<FootballStatEventType, number>;\n\n// A game write's answer — a scoring event, a bulk-entry form, absence, the possession arrow, a ghost\n// added from the game — when the request names a team the game does not hold.\nexport const TEAM_NOT_IN_GAME_MESSAGE = 'That team is not playing in this game.';\n\n// A game write's answer — a bulk-entry row, absence, a memo — when the request names a person the\n// game's roster does not hold.\nexport const NOT_ON_GAME_ROSTER_MESSAGE = \"That player is not on this game's roster.\";\n\n// What the scorekeeper reads beside an event a scoring write refused.\nexport const STAT_EVENT_REFUSAL_COPY = {\n eventTypeNotInSport: \"That stat does not belong to this game's sport.\",\n teamNotInGame: TEAM_NOT_IN_GAME_MESSAGE,\n playerNotRostered: \"That player is not on this game's roster for that team.\",\n assisterNotRostered: \"The assisting player is not on this game's roster for that team.\",\n assistNotAllowed: 'Only a 2- or 3-point basket can be assisted, and never by the player who scored it.',\n playerNotAllowed: \"That stat is the team's; it cannot name a player.\",\n roundNotNext: 'That round is not the next one to record.',\n roundsComplete: 'Every round is already recorded.',\n bulkValueInvalid: 'That entry is not a real result: stats are whole numbers and never go below zero.',\n bulkStale: 'The numbers changed while you were editing. Check the flagged values and save again.',\n eventIdConflict: 'A different stat was already saved under this one. Discard it and enter it again.',\n voidTargetNotSportEvent: 'There is no recorded stat there to undo.',\n correctionNotAccepted: 'Corrections are made from Fix stats, not from the scoring screen.',\n undoBelowZero: 'Undoing that play would leave a stat below zero, because a later entry already lowered it.',\n} as const satisfies Record<StatEventRefusalCode, string>;\n\n// The operation every correction the game copy appends is recorded under, and the reason it carries.\n// The copy carries each recorded result exactly: where a game's recorded lines differ from what its\n// recorded plays replay to, one correction per field closes the difference, and these name it.\nexport const STATS_MIGRATION_OPERATION_ID = 'migration';\nexport const STATS_MIGRATION_CORRECTION_REASON =\n 'The recorded result differs from what its recorded plays add up to; this correction keeps the recorded result.';\n\n// What an admin reads when Fix stats refuses a game repair.\nexport const GAME_REPAIR_REFUSAL_COPY = {\n eventUnreadable: \"One of this game's recorded stats can no longer be read. Fix the event in the console, then repair the game.\",\n sourcesDisagree:\n \"This game's record, its stored numbers, and its recorded stats all disagree, so nothing says what was applied. Fix the game in the console first.\",\n scoreAmbiguous:\n \"The team's score was edited in two places to different values. Enter the score you want as a correction instead.\",\n fieldNotCorrectable:\n \"That number cannot be corrected for this sport. Restore the game from its recorded stats, or reopen it and score it again.\",\n lineNotRostered: \"That player is not on this game's roster.\",\n teamNotInGame: \"That team is not playing in this game.\",\n gameTooLarge: 'This repair is too large to save at once.',\n} as const satisfies Record<GameRepairRefusal, string>;\n\n// What the caller reads when a stats path refuses a game whose numbers changed outside the app.\nexport const STATS_INTEGRITY_REFUSAL_COPY = {\n statsOutOfBand:\n \"This game's stored numbers no longer match the stats recorded for it. An admin must reconcile the game in Fix stats first.\",\n finalRecordMissing:\n \"This finalized game's record of its stats is missing. An admin must repair the game in Fix stats first.\",\n aggregateBelowZero:\n 'A league, career, or hall-of-fame total holds less than this game added to it. An admin must rebuild the totals in Fix stats first.',\n} as const satisfies Record<StatsIntegrityRefusal, string>;\n\n// What the finish control shows while a game may not be finalized, and what finalize refuses with.\nexport const FINALIZATION_NOT_READY_COPY = {\n roundsIncomplete: 'Every round must be recorded before the game can be finalized.',\n} as const satisfies Record<FinalizationNotReadyReason, string>;\n\n// The hall of fame's minimum-games filter: each choice keeps the careers with at least that many\n// games played. None is chosen until the viewer picks one, so the hall of fame opens on everyone.\nexport const HALL_OF_FAME_MINIMUM_GAMES_CHOICES = [25, 50, 100] as const;\nexport type HallOfFameMinimumGames = (typeof HALL_OF_FAME_MINIMUM_GAMES_CHOICES)[number];\n"]}
|
|
1
|
+
{"version":3,"file":"sports.js","sourceRoot":"","sources":["../../src/constants/sports.ts"],"names":[],"mappings":"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","sourcesContent":["// Sport rule values that are persisted or validated on both sides of the boundary. What a sport\n// DOES with them — applying an event, recomputing a score — belongs to its adapter (SPORT-003).\n\nimport {\n BASKETBALL_ASSIST_EVENT_TYPE,\n BASKETBALL_BULK_EDIT_EVENT_TYPE,\n BASKETBALL_ONE_POINT_EVENT_TYPE,\n BASKETBALL_REBOUND_EVENT_TYPE,\n BASKETBALL_THREE_POINT_EVENT_TYPE,\n BASKETBALL_TIMEOUT_EVENT_TYPE,\n BASKETBALL_TWO_POINT_EVENT_TYPE,\n FOOTBALL_BULK_EDIT_EVENT_TYPE,\n FOOTBALL_ONE_POINT_EVENT_TYPE,\n FOOTBALL_SIX_POINT_EVENT_TYPE,\n FOOTBALL_TWO_POINT_EVENT_TYPE,\n} from '../types/sports.js';\nimport type { BasketballPlayerStatKey, BasketballStatEventType, FootballStatEventType } from '../types/sports.js';\nimport type {\n FinalizationNotReadyReason,\n GameRepairRefusal,\n StatEventRefusalCode,\n StatsIntegrityRefusal,\n} from '../types/stats.js';\n\n// Points a basketball stat event adds to its team's score. BULK_EDIT carries its own `value`.\nexport const BASKETBALL_POINTS_BY_EVENT_TYPE = {\n [BASKETBALL_ONE_POINT_EVENT_TYPE]: 1,\n [BASKETBALL_TWO_POINT_EVENT_TYPE]: 2,\n [BASKETBALL_THREE_POINT_EVENT_TYPE]: 3,\n [BASKETBALL_REBOUND_EVENT_TYPE]: 0,\n [BASKETBALL_ASSIST_EVENT_TYPE]: 0,\n [BASKETBALL_TIMEOUT_EVENT_TYPE]: 0,\n [BASKETBALL_BULK_EDIT_EVENT_TYPE]: 0,\n} as const satisfies Record<BasketballStatEventType, number>;\n\n// Basketball fantasy points (FP): each player counter times its weight. Every weight is a multiple\n// of one half, so FP summed across games equals FP of the summed counters exactly.\nexport const BASKETBALL_FANTASY_POINT_WEIGHTS = {\n points: 1,\n rebounds: 1.5,\n assists: 2,\n} as const satisfies Record<BasketballPlayerStatKey, number>;\n\n// A curling game is this many rounds; `roundScores` has exactly this many slots.\nexport const CURLING_ROUND_COUNT = 14;\n\n// A scored curling round is worth 1..MAX; a blank end is 0.\nexport const MAX_CURLING_ROUND_POINTS = 4;\n\n// The most events one scoring write may carry: each event is a document created in the write's one\n// transaction, and a Firestore transaction commits at most 500 writes.\nexport const MAX_STAT_EVENTS_PER_WRITE = 200;\n\n// The most lines and fields one Correct a game call may set; a game holds far fewer.\nexport const MAX_GAME_STATS_CORRECTION_TARGETS = 200;\n\n// The most destination changes one rebuild call lists in its answer; the audit events record all.\nexport const MAX_STATS_REPAIR_LISTED_CHANGES = 500;\n\n// The most findings one stats check keeps on its report; every finding is still counted by kind.\nexport const MAX_STATS_VALIDATION_DISCREPANCIES = 500;\n\n// The most events one page of a completed game's finalized record holds.\nexport const STAT_HISTORY_PAGE_SIZE = 1000;\n\n// Points a football stat event adds to its team's score. FOOTBALL_BULK_EDIT carries its own `value`.\nexport const FOOTBALL_POINTS_BY_EVENT_TYPE = {\n [FOOTBALL_SIX_POINT_EVENT_TYPE]: 6,\n [FOOTBALL_TWO_POINT_EVENT_TYPE]: 2,\n [FOOTBALL_ONE_POINT_EVENT_TYPE]: 1,\n [FOOTBALL_BULK_EDIT_EVENT_TYPE]: 0,\n} as const satisfies Record<FootballStatEventType, number>;\n\n// A game write's answer — a scoring event, a bulk-entry form, absence, the possession arrow, a ghost\n// added from the game — when the request names a team the game does not hold.\nexport const TEAM_NOT_IN_GAME_MESSAGE = 'That team is not playing in this game.';\n\n// A game write's answer — a bulk-entry row, absence, a memo — when the request names a person the\n// game's roster does not hold.\nexport const NOT_ON_GAME_ROSTER_MESSAGE = \"That player is not on this game's roster.\";\n\n// What the scorekeeper reads beside an event a scoring write refused.\nexport const STAT_EVENT_REFUSAL_COPY = {\n eventTypeNotInSport: \"That stat does not belong to this game's sport.\",\n teamNotInGame: TEAM_NOT_IN_GAME_MESSAGE,\n playerNotRostered: \"That player is not on this game's roster for that team.\",\n assisterNotRostered: \"The assisting player is not on this game's roster for that team.\",\n assistNotAllowed: 'Only a 2- or 3-point basket can be assisted, and never by the player who scored it.',\n playerNotAllowed: \"That stat is the team's; it cannot name a player.\",\n roundNotNext: 'That round is not the next one to record.',\n roundsComplete: 'Every round is already recorded.',\n bulkValueInvalid: 'That entry is not a real result: stats are whole numbers and never go below zero.',\n bulkStale: 'The numbers changed while you were editing. Check the flagged values and save again.',\n eventIdConflict: 'A different stat was already saved under this one. Discard it and enter it again.',\n voidTargetNotSportEvent: 'There is no recorded stat there to undo.',\n correctionNotAccepted: 'Corrections are made from Fix stats, not from the scoring screen.',\n undoBelowZero: 'Undoing that play would leave a stat below zero, because a later entry already lowered it.',\n} as const satisfies Record<StatEventRefusalCode, string>;\n\n// The operation every correction the game copy appends is recorded under, and the reason it carries.\n// The copy carries each recorded result exactly: where a game's recorded lines differ from what its\n// recorded plays replay to, one correction per field closes the difference, and these name it.\nexport const STATS_MIGRATION_OPERATION_ID = 'migration';\nexport const STATS_MIGRATION_CORRECTION_REASON =\n 'The recorded result differs from what its recorded plays add up to; this correction keeps the recorded result.';\n\n// What an admin reads when Fix stats refuses a game repair.\nexport const GAME_REPAIR_REFUSAL_COPY = {\n eventUnreadable: \"One of this game's recorded stats can no longer be read. Fix the event in the console, then repair the game.\",\n eventSequenceGap:\n \"This game's recorded stats are numbered with a gap or a repeat. Fix the event documents in the console, then restore the game.\",\n sourcesDisagree:\n \"This game's record, its stored numbers, and its recorded stats all disagree, so nothing says what was applied. Fix the game in the console first.\",\n scoreAmbiguous:\n \"The team's score was edited in two places to different values. Enter the score you want as a correction instead.\",\n fieldNotCorrectable:\n \"That number cannot be corrected for this sport. Restore the game from its recorded stats, or reopen it and score it again.\",\n lineNotRostered: \"That player is not on this game's roster.\",\n teamNotInGame: \"That team is not playing in this game.\",\n gameTooLarge: 'This repair is too large to save at once.',\n} as const satisfies Record<GameRepairRefusal, string>;\n\n// What the caller reads when a stats path refuses a game whose numbers changed outside the app.\nexport const STATS_INTEGRITY_REFUSAL_COPY = {\n statsOutOfBand:\n \"This game's stored numbers no longer match the stats recorded for it. An admin must reconcile the game in Fix stats first.\",\n finalRecordMissing:\n \"This finalized game's record of its stats is missing. An admin must repair the game in Fix stats first.\",\n aggregateBelowZero:\n 'A league, career, or hall-of-fame total holds less than this game added to it. An admin must rebuild the totals in Fix stats first.',\n} as const satisfies Record<StatsIntegrityRefusal, string>;\n\n// What the finish control shows while a game may not be finalized, and what finalize refuses with.\nexport const FINALIZATION_NOT_READY_COPY = {\n roundsIncomplete: 'Every round must be recorded before the game can be finalized.',\n} as const satisfies Record<FinalizationNotReadyReason, string>;\n\n// The hall of fame's minimum-games filter: each choice keeps the careers with at least that many\n// games played. None is chosen until the viewer picks one, so the hall of fame opens on everyone.\nexport const HALL_OF_FAME_MINIMUM_GAMES_CHOICES = [25, 50, 100] as const;\nexport type HallOfFameMinimumGames = (typeof HALL_OF_FAME_MINIMUM_GAMES_CHOICES)[number];\n"]}
|
package/dist/types/stats.d.ts
CHANGED
|
@@ -43,7 +43,7 @@ export declare const STATS_INTEGRITY_REFUSAL_KEYS: readonly ["statsOutOfBand", "
|
|
|
43
43
|
export type StatsIntegrityRefusal = (typeof STATS_INTEGRITY_REFUSAL_KEYS)[number];
|
|
44
44
|
export declare const GAME_STATS_REPAIR_OUTCOME_KEYS: readonly ["reconciled", "unchanged", "alreadyApplied"];
|
|
45
45
|
export type GameStatsRepairOutcome = (typeof GAME_STATS_REPAIR_OUTCOME_KEYS)[number];
|
|
46
|
-
export declare const GAME_REPAIR_REFUSAL_KEYS: readonly ["eventUnreadable", "sourcesDisagree", "scoreAmbiguous", "fieldNotCorrectable", "lineNotRostered", "teamNotInGame", "gameTooLarge"];
|
|
46
|
+
export declare const GAME_REPAIR_REFUSAL_KEYS: readonly ["eventUnreadable", "eventSequenceGap", "sourcesDisagree", "scoreAmbiguous", "fieldNotCorrectable", "lineNotRostered", "teamNotInGame", "gameTooLarge"];
|
|
47
47
|
export type GameRepairRefusal = (typeof GAME_REPAIR_REFUSAL_KEYS)[number];
|
|
48
48
|
export declare const GHOST_LINK_MEMBERSHIP_OUTCOME_KEYS: readonly ["handedOver", "created", "merged", "kept"];
|
|
49
49
|
export type GhostLinkMembershipOutcome = (typeof GHOST_LINK_MEMBERSHIP_OUTCOME_KEYS)[number];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/types/stats.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/types/stats.ts"],"names":[],"mappings":"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"}
|
package/dist/types/stats.js
CHANGED
|
@@ -102,6 +102,8 @@ export const STATS_INTEGRITY_REFUSAL_KEYS = ['statsOutOfBand', 'finalRecordMissi
|
|
|
102
102
|
export const GAME_STATS_REPAIR_OUTCOME_KEYS = ['reconciled', 'unchanged', 'alreadyApplied'];
|
|
103
103
|
// Why a game repair in Fix stats was refused, in the refusal's details, so the form says what to do:
|
|
104
104
|
// eventUnreadable an event document no longer parses or replays — fix it in the console first
|
|
105
|
+
// eventSequenceGap the events do not hold exactly the sequences 1..n — a gap or a repeat — which
|
|
106
|
+
// a repair never renumbers: fix the event documents in the console first
|
|
105
107
|
// sourcesDisagree the record, the stored rollup, and the events all disagree: no one of them
|
|
106
108
|
// says what finalize applied
|
|
107
109
|
// scoreAmbiguous keep-stored: the team line's score and the score mirror were both edited, to
|
|
@@ -113,6 +115,7 @@ export const GAME_STATS_REPAIR_OUTCOME_KEYS = ['reconciled', 'unchanged', 'alrea
|
|
|
113
115
|
// gameTooLarge the repair would not fit in one commit
|
|
114
116
|
export const GAME_REPAIR_REFUSAL_KEYS = [
|
|
115
117
|
'eventUnreadable',
|
|
118
|
+
'eventSequenceGap',
|
|
116
119
|
'sourcesDisagree',
|
|
117
120
|
'scoreAmbiguous',
|
|
118
121
|
'fieldNotCorrectable',
|
package/dist/types/stats.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/types/stats.ts"],"names":[],"mappings":"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","sourcesContent":["// Canonical unions of the stat event store and the stats operations (ARCH-102). What each sport's\n// own events and lines are is ./sports.ts; these are the sport-agnostic halves every sport shares.\n\nimport { CAPTAIN_TEAM_ROLES, SYSTEM_ROLE_KEYS } from './unions.js';\n\n// The two store-level events, members of every sport's event union. A void undoes the one event it\n// targets; a correction adds a signed value to one correctable field of one line.\nexport const STAT_VOID_EVENT_TYPE = 'STAT_VOID';\nexport const STAT_CORRECTION_EVENT_TYPE = 'STAT_CORRECTION';\nexport const STAT_STORE_EVENT_TYPE_KEYS = [STAT_VOID_EVENT_TYPE, STAT_CORRECTION_EVENT_TYPE] as const;\nexport type StatStoreEventType = (typeof STAT_STORE_EVENT_TYPE_KEYS)[number];\n\n// The fields of a stored stat event the writing core derives — its place in the replay, and who\n// recorded it under which authority — so a caller never sends them (ARCH-106).\nexport const STAT_EVENT_RECORDER_FIELD_KEYS = [\n 'sequence',\n 'acceptedAt',\n 'recordedByUserId',\n 'recordedByAuthority',\n 'recordedByTeamId',\n] as const;\nexport type StatEventRecorderField = (typeof STAT_EVENT_RECORDER_FIELD_KEYS)[number];\n\n// The name snapshots only a copied event carries; nothing writes one on a new event (SPORT-104).\nexport const STAT_EVENT_SNAPSHOT_FIELD_KEYS = ['displayNameSnapshot', 'assistedByDisplayNameSnapshot'] as const;\nexport type StatEventSnapshotField = (typeof STAT_EVENT_SNAPSHOT_FIELD_KEYS)[number];\n\n// Who appended a correction: an admin reconciling a game, or the copy that carries a recorded\n// result its events do not explain.\nexport const STAT_CORRECTION_SOURCE_KEYS = ['admin', 'migration'] as const;\nexport type StatCorrectionSource = (typeof STAT_CORRECTION_SOURCE_KEYS)[number];\n\n// The authority the writing core confirmed for an event: a global role, or a team role on one of\n// the game's teams.\nexport const STAT_EVENT_AUTHORITY_KEYS = [...SYSTEM_ROLE_KEYS, ...CAPTAIN_TEAM_ROLES] as const;\nexport type StatEventAuthority = (typeof STAT_EVENT_AUTHORITY_KEYS)[number];\n\n// Every kind of stat line: the four player kinds, then the two team kinds. A sport's line of each\n// kind is declared once, in `SPORT_LINE_SCHEMAS`; a kind a sport has no line for is `never` there.\nexport const PLAYER_STAT_LINE_KIND_KEYS = ['gamePlayer', 'membershipRow', 'lifetime', 'hallOfFame'] as const;\nexport const TEAM_STAT_LINE_KIND_KEYS = ['gameTeam', 'teamSeason'] as const;\nexport const STAT_LINE_KIND_KEYS = [...PLAYER_STAT_LINE_KIND_KEYS, ...TEAM_STAT_LINE_KIND_KEYS] as const;\nexport type StatLineKind = (typeof STAT_LINE_KIND_KEYS)[number];\nexport type PlayerStatLineKind = (typeof PLAYER_STAT_LINE_KIND_KEYS)[number];\n\n// One logical run of a stats action, recorded on its `statsOperations` document.\nexport const STATS_OPERATION_KIND_KEYS = [\n 'leagueStatsRebuild',\n 'lifetimeStatsRebuild',\n 'hallOfFameRebuild',\n 'statsValidation',\n 'gameStatsCorrection',\n 'gameStatsRecalculation',\n 'historicalStatsUpdate',\n 'ghostPlayerStats',\n 'gameDeletion',\n] as const;\nexport type StatsOperationKind = (typeof STATS_OPERATION_KIND_KEYS)[number];\n\n// The rebuilds: each replaces one destination from the finalized games, a unit at a time, and shares\n// one paged run.\nexport const STATS_REBUILD_OPERATION_KIND_KEYS = [\n 'leagueStatsRebuild',\n 'lifetimeStatsRebuild',\n 'hallOfFameRebuild',\n] as const satisfies readonly StatsOperationKind[];\nexport type StatsRebuildOperationKind = (typeof STATS_REBUILD_OPERATION_KIND_KEYS)[number];\n\nexport const STATS_OPERATION_STATUS_KEYS = ['running', 'complete', 'stopped'] as const;\nexport type StatsOperationStatus = (typeof STATS_OPERATION_STATUS_KEYS)[number];\n\n// A validation run checks every game first, then the destinations those games feed.\nexport const STATS_VALIDATION_PHASE_KEYS = ['games', 'destinations'] as const;\nexport type StatsValidationPhase = (typeof STATS_VALIDATION_PHASE_KEYS)[number];\n\n// A ghost has one operation for both of its ways out, so a link and a removal refuse each other.\nexport const GHOST_STATS_OPERATION_ACTION_KEYS = ['link', 'removal'] as const;\nexport type GhostStatsOperationAction = (typeof GHOST_STATS_OPERATION_ACTION_KEYS)[number];\n\n// Why a scoring write refused an event. The first ten are a sport adapter's `validate`; the last\n// four are the store driver's own: an id already stored, or earlier in the batch, with different\n// content; a void whose target is missing, a void, or a correction; a correction sent to a scoring\n// entry, which only the game-reconcile core appends; and a void that would leave a stat below zero,\n// because a later edit already moved its target's field down.\nexport const STAT_EVENT_REFUSAL_KEYS = [\n 'eventTypeNotInSport',\n 'teamNotInGame',\n 'playerNotRostered',\n 'assisterNotRostered',\n 'assistNotAllowed',\n 'playerNotAllowed',\n 'roundNotNext',\n 'roundsComplete',\n 'bulkValueInvalid',\n 'bulkStale',\n 'eventIdConflict',\n 'voidTargetNotSportEvent',\n 'correctionNotAccepted',\n 'undoBelowZero',\n] as const;\nexport type StatEventRefusalCode = (typeof STAT_EVENT_REFUSAL_KEYS)[number];\n\n// Why a game may not be finalized yet — a sport played in rounds with an end still unrecorded.\nexport const FINALIZATION_NOT_READY_KEYS = ['roundsIncomplete'] as const;\nexport type FinalizationNotReadyReason = (typeof FINALIZATION_NOT_READY_KEYS)[number];\n\n// The scoring panel a sport's adapter names; the scoring screen renders one component per kind.\nexport const SCORING_PANEL_KIND_KEYS = ['playerEvents', 'teamPoints', 'rounds'] as const;\nexport type ScoringPanelKind = (typeof SCORING_PANEL_KIND_KEYS)[number];\n\n// The bulk-entry form body a sport's adapter names; the bulk-entry dialog renders one per kind.\nexport const BULK_ENTRY_KIND_KEYS = ['playerLines', 'teamScores', 'rounds'] as const;\nexport type BulkEntryKind = (typeof BULK_ENTRY_KIND_KEYS)[number];\n\n// What a scoring write did with each event it was sent: stored it now, or found it already stored\n// by an earlier send and acknowledged it without applying it again.\nexport const RECORDED_STAT_EVENT_OUTCOME_KEYS = ['recorded', 'alreadyRecorded'] as const;\nexport type RecordedStatEventOutcome = (typeof RECORDED_STAT_EVENT_OUTCOME_KEYS)[number];\n\n// What finalize did: made the game's numbers permanent, or found it already finalized and changed\n// nothing (SPORT-203).\nexport const GAME_FINALIZE_OUTCOME_KEYS = ['finalized', 'alreadyFinalized'] as const;\nexport type GameFinalizeOutcome = (typeof GAME_FINALIZE_OUTCOME_KEYS)[number];\n\n// What reopen did: took a finalized game's numbers back out, or found the game already open and\n// changed nothing.\nexport const GAME_REOPEN_OUTCOME_KEYS = ['reopened', 'alreadyOpen'] as const;\nexport type GameReopenOutcome = (typeof GAME_REOPEN_OUTCOME_KEYS)[number];\n\n// Why a path that makes numbers permanent, or takes them back, refused a game whose stored numbers\n// disagree with what produced them — something changed them outside the app, and an admin\n// reconciles the game in Fix stats first. Finalize, reopen, and a ghost link never adopt or discard\n// an unexplained difference (ENG-009):\n// statsOutOfBand the rollup or score mirror is not the replay of the game's events or record\n// finalRecordMissing a completed game has no finalized record\n// aggregateBelowZero a stored derived line holds less than the game put into it\nexport const STATS_INTEGRITY_REFUSAL_KEYS = ['statsOutOfBand', 'finalRecordMissing', 'aggregateBelowZero'] as const;\nexport type StatsIntegrityRefusal = (typeof STATS_INTEGRITY_REFUSAL_KEYS)[number];\n\n// What a game repair in Fix stats did: changed the game (`reconciled`), found nothing to change\n// (`unchanged`), or found its operation already committed and acknowledged the retry\n// (`alreadyApplied`).\nexport const GAME_STATS_REPAIR_OUTCOME_KEYS = ['reconciled', 'unchanged', 'alreadyApplied'] as const;\nexport type GameStatsRepairOutcome = (typeof GAME_STATS_REPAIR_OUTCOME_KEYS)[number];\n\n// Why a game repair in Fix stats was refused, in the refusal's details, so the form says what to do:\n// eventUnreadable an event document no longer parses or replays — fix it in the console first\n// sourcesDisagree the record, the stored rollup, and the events all disagree: no one of them\n// says what finalize applied\n// scoreAmbiguous keep-stored: the team line's score and the score mirror were both edited, to\n// different values — give the score as a target instead\n// fieldNotCorrectable a field the sport's adapter does not let a correction change — restore from\n// the events instead, or reopen and re-score\n// lineNotRostered a line for someone not on the game's roster\n// teamNotInGame a target names a team the game does not hold\n// gameTooLarge the repair would not fit in one commit\nexport const GAME_REPAIR_REFUSAL_KEYS = [\n 'eventUnreadable',\n 'sourcesDisagree',\n 'scoreAmbiguous',\n 'fieldNotCorrectable',\n 'lineNotRostered',\n 'teamNotInGame',\n 'gameTooLarge',\n] as const;\nexport type GameRepairRefusal = (typeof GAME_REPAIR_REFUSAL_KEYS)[number];\n\n// What a ghost link did with the team's memberships: the ghost's membership became the account's\n// (`handedOver`); the account had none and the ghost none either, so the closed-league link gave the\n// account one (`created`); both held one and one survives with the higher role (`merged`); or only\n// the account held one, and it stands (`kept`).\nexport const GHOST_LINK_MEMBERSHIP_OUTCOME_KEYS = ['handedOver', 'created', 'merged', 'kept'] as const;\nexport type GhostLinkMembershipOutcome = (typeof GHOST_LINK_MEMBERSHIP_OUTCOME_KEYS)[number];\n\n// What the migration's placement of an unplaceable V1 stat line did: `alreadyResolved` when the game\n// already held the entry it would write — nothing was written.\nexport const UNROSTERED_STAT_LINE_RESOLUTION_OUTCOME_KEYS = ['resolved', 'alreadyResolved'] as const;\nexport type UnrosteredStatLineResolutionOutcome = (typeof UNROSTERED_STAT_LINE_RESOLUTION_OUTCOME_KEYS)[number];\n\n// Why a ghost's removal was refused, in the refusal's details, so the client answers each one: the\n// ghost has played (link it instead) or its removal stopped on finding it had; a game the removal\n// needs is held by another operation (try again shortly); the ghost is being, or was, linked; the\n// ghost is the team's captain (change the captain first).\nexport const GHOST_REMOVAL_REFUSAL_KEYS = ['ghostHasPlayed', 'removalStopped', 'gameHeld', 'ghostBeingLinked', 'captainNotRemovable'] as const;\nexport type GhostRemovalRefusal = (typeof GHOST_REMOVAL_REFUSAL_KEYS)[number];\n\n"]}
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/types/stats.ts"],"names":[],"mappings":"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","sourcesContent":["// Canonical unions of the stat event store and the stats operations (ARCH-102). What each sport's\n// own events and lines are is ./sports.ts; these are the sport-agnostic halves every sport shares.\n\nimport { CAPTAIN_TEAM_ROLES, SYSTEM_ROLE_KEYS } from './unions.js';\n\n// The two store-level events, members of every sport's event union. A void undoes the one event it\n// targets; a correction adds a signed value to one correctable field of one line.\nexport const STAT_VOID_EVENT_TYPE = 'STAT_VOID';\nexport const STAT_CORRECTION_EVENT_TYPE = 'STAT_CORRECTION';\nexport const STAT_STORE_EVENT_TYPE_KEYS = [STAT_VOID_EVENT_TYPE, STAT_CORRECTION_EVENT_TYPE] as const;\nexport type StatStoreEventType = (typeof STAT_STORE_EVENT_TYPE_KEYS)[number];\n\n// The fields of a stored stat event the writing core derives — its place in the replay, and who\n// recorded it under which authority — so a caller never sends them (ARCH-106).\nexport const STAT_EVENT_RECORDER_FIELD_KEYS = [\n 'sequence',\n 'acceptedAt',\n 'recordedByUserId',\n 'recordedByAuthority',\n 'recordedByTeamId',\n] as const;\nexport type StatEventRecorderField = (typeof STAT_EVENT_RECORDER_FIELD_KEYS)[number];\n\n// The name snapshots only a copied event carries; nothing writes one on a new event (SPORT-104).\nexport const STAT_EVENT_SNAPSHOT_FIELD_KEYS = ['displayNameSnapshot', 'assistedByDisplayNameSnapshot'] as const;\nexport type StatEventSnapshotField = (typeof STAT_EVENT_SNAPSHOT_FIELD_KEYS)[number];\n\n// Who appended a correction: an admin reconciling a game, or the copy that carries a recorded\n// result its events do not explain.\nexport const STAT_CORRECTION_SOURCE_KEYS = ['admin', 'migration'] as const;\nexport type StatCorrectionSource = (typeof STAT_CORRECTION_SOURCE_KEYS)[number];\n\n// The authority the writing core confirmed for an event: a global role, or a team role on one of\n// the game's teams.\nexport const STAT_EVENT_AUTHORITY_KEYS = [...SYSTEM_ROLE_KEYS, ...CAPTAIN_TEAM_ROLES] as const;\nexport type StatEventAuthority = (typeof STAT_EVENT_AUTHORITY_KEYS)[number];\n\n// Every kind of stat line: the four player kinds, then the two team kinds. A sport's line of each\n// kind is declared once, in `SPORT_LINE_SCHEMAS`; a kind a sport has no line for is `never` there.\nexport const PLAYER_STAT_LINE_KIND_KEYS = ['gamePlayer', 'membershipRow', 'lifetime', 'hallOfFame'] as const;\nexport const TEAM_STAT_LINE_KIND_KEYS = ['gameTeam', 'teamSeason'] as const;\nexport const STAT_LINE_KIND_KEYS = [...PLAYER_STAT_LINE_KIND_KEYS, ...TEAM_STAT_LINE_KIND_KEYS] as const;\nexport type StatLineKind = (typeof STAT_LINE_KIND_KEYS)[number];\nexport type PlayerStatLineKind = (typeof PLAYER_STAT_LINE_KIND_KEYS)[number];\n\n// One logical run of a stats action, recorded on its `statsOperations` document.\nexport const STATS_OPERATION_KIND_KEYS = [\n 'leagueStatsRebuild',\n 'lifetimeStatsRebuild',\n 'hallOfFameRebuild',\n 'statsValidation',\n 'gameStatsCorrection',\n 'gameStatsRecalculation',\n 'historicalStatsUpdate',\n 'ghostPlayerStats',\n 'gameDeletion',\n] as const;\nexport type StatsOperationKind = (typeof STATS_OPERATION_KIND_KEYS)[number];\n\n// The rebuilds: each replaces one destination from the finalized games, a unit at a time, and shares\n// one paged run.\nexport const STATS_REBUILD_OPERATION_KIND_KEYS = [\n 'leagueStatsRebuild',\n 'lifetimeStatsRebuild',\n 'hallOfFameRebuild',\n] as const satisfies readonly StatsOperationKind[];\nexport type StatsRebuildOperationKind = (typeof STATS_REBUILD_OPERATION_KIND_KEYS)[number];\n\nexport const STATS_OPERATION_STATUS_KEYS = ['running', 'complete', 'stopped'] as const;\nexport type StatsOperationStatus = (typeof STATS_OPERATION_STATUS_KEYS)[number];\n\n// A validation run checks every game first, then the destinations those games feed.\nexport const STATS_VALIDATION_PHASE_KEYS = ['games', 'destinations'] as const;\nexport type StatsValidationPhase = (typeof STATS_VALIDATION_PHASE_KEYS)[number];\n\n// A ghost has one operation for both of its ways out, so a link and a removal refuse each other.\nexport const GHOST_STATS_OPERATION_ACTION_KEYS = ['link', 'removal'] as const;\nexport type GhostStatsOperationAction = (typeof GHOST_STATS_OPERATION_ACTION_KEYS)[number];\n\n// Why a scoring write refused an event. The first ten are a sport adapter's `validate`; the last\n// four are the store driver's own: an id already stored, or earlier in the batch, with different\n// content; a void whose target is missing, a void, or a correction; a correction sent to a scoring\n// entry, which only the game-reconcile core appends; and a void that would leave a stat below zero,\n// because a later edit already moved its target's field down.\nexport const STAT_EVENT_REFUSAL_KEYS = [\n 'eventTypeNotInSport',\n 'teamNotInGame',\n 'playerNotRostered',\n 'assisterNotRostered',\n 'assistNotAllowed',\n 'playerNotAllowed',\n 'roundNotNext',\n 'roundsComplete',\n 'bulkValueInvalid',\n 'bulkStale',\n 'eventIdConflict',\n 'voidTargetNotSportEvent',\n 'correctionNotAccepted',\n 'undoBelowZero',\n] as const;\nexport type StatEventRefusalCode = (typeof STAT_EVENT_REFUSAL_KEYS)[number];\n\n// Why a game may not be finalized yet — a sport played in rounds with an end still unrecorded.\nexport const FINALIZATION_NOT_READY_KEYS = ['roundsIncomplete'] as const;\nexport type FinalizationNotReadyReason = (typeof FINALIZATION_NOT_READY_KEYS)[number];\n\n// The scoring panel a sport's adapter names; the scoring screen renders one component per kind.\nexport const SCORING_PANEL_KIND_KEYS = ['playerEvents', 'teamPoints', 'rounds'] as const;\nexport type ScoringPanelKind = (typeof SCORING_PANEL_KIND_KEYS)[number];\n\n// The bulk-entry form body a sport's adapter names; the bulk-entry dialog renders one per kind.\nexport const BULK_ENTRY_KIND_KEYS = ['playerLines', 'teamScores', 'rounds'] as const;\nexport type BulkEntryKind = (typeof BULK_ENTRY_KIND_KEYS)[number];\n\n// What a scoring write did with each event it was sent: stored it now, or found it already stored\n// by an earlier send and acknowledged it without applying it again.\nexport const RECORDED_STAT_EVENT_OUTCOME_KEYS = ['recorded', 'alreadyRecorded'] as const;\nexport type RecordedStatEventOutcome = (typeof RECORDED_STAT_EVENT_OUTCOME_KEYS)[number];\n\n// What finalize did: made the game's numbers permanent, or found it already finalized and changed\n// nothing (SPORT-203).\nexport const GAME_FINALIZE_OUTCOME_KEYS = ['finalized', 'alreadyFinalized'] as const;\nexport type GameFinalizeOutcome = (typeof GAME_FINALIZE_OUTCOME_KEYS)[number];\n\n// What reopen did: took a finalized game's numbers back out, or found the game already open and\n// changed nothing.\nexport const GAME_REOPEN_OUTCOME_KEYS = ['reopened', 'alreadyOpen'] as const;\nexport type GameReopenOutcome = (typeof GAME_REOPEN_OUTCOME_KEYS)[number];\n\n// Why a path that makes numbers permanent, or takes them back, refused a game whose stored numbers\n// disagree with what produced them — something changed them outside the app, and an admin\n// reconciles the game in Fix stats first. Finalize, reopen, and a ghost link never adopt or discard\n// an unexplained difference (ENG-009):\n// statsOutOfBand the rollup or score mirror is not the replay of the game's events or record\n// finalRecordMissing a completed game has no finalized record\n// aggregateBelowZero a stored derived line holds less than the game put into it\nexport const STATS_INTEGRITY_REFUSAL_KEYS = ['statsOutOfBand', 'finalRecordMissing', 'aggregateBelowZero'] as const;\nexport type StatsIntegrityRefusal = (typeof STATS_INTEGRITY_REFUSAL_KEYS)[number];\n\n// What a game repair in Fix stats did: changed the game (`reconciled`), found nothing to change\n// (`unchanged`), or found its operation already committed and acknowledged the retry\n// (`alreadyApplied`).\nexport const GAME_STATS_REPAIR_OUTCOME_KEYS = ['reconciled', 'unchanged', 'alreadyApplied'] as const;\nexport type GameStatsRepairOutcome = (typeof GAME_STATS_REPAIR_OUTCOME_KEYS)[number];\n\n// Why a game repair in Fix stats was refused, in the refusal's details, so the form says what to do:\n// eventUnreadable an event document no longer parses or replays — fix it in the console first\n// eventSequenceGap the events do not hold exactly the sequences 1..n — a gap or a repeat — which\n// a repair never renumbers: fix the event documents in the console first\n// sourcesDisagree the record, the stored rollup, and the events all disagree: no one of them\n// says what finalize applied\n// scoreAmbiguous keep-stored: the team line's score and the score mirror were both edited, to\n// different values — give the score as a target instead\n// fieldNotCorrectable a field the sport's adapter does not let a correction change — restore from\n// the events instead, or reopen and re-score\n// lineNotRostered a line for someone not on the game's roster\n// teamNotInGame a target names a team the game does not hold\n// gameTooLarge the repair would not fit in one commit\nexport const GAME_REPAIR_REFUSAL_KEYS = [\n 'eventUnreadable',\n 'eventSequenceGap',\n 'sourcesDisagree',\n 'scoreAmbiguous',\n 'fieldNotCorrectable',\n 'lineNotRostered',\n 'teamNotInGame',\n 'gameTooLarge',\n] as const;\nexport type GameRepairRefusal = (typeof GAME_REPAIR_REFUSAL_KEYS)[number];\n\n// What a ghost link did with the team's memberships: the ghost's membership became the account's\n// (`handedOver`); the account had none and the ghost none either, so the closed-league link gave the\n// account one (`created`); both held one and one survives with the higher role (`merged`); or only\n// the account held one, and it stands (`kept`).\nexport const GHOST_LINK_MEMBERSHIP_OUTCOME_KEYS = ['handedOver', 'created', 'merged', 'kept'] as const;\nexport type GhostLinkMembershipOutcome = (typeof GHOST_LINK_MEMBERSHIP_OUTCOME_KEYS)[number];\n\n// What the migration's placement of an unplaceable V1 stat line did: `alreadyResolved` when the game\n// already held the entry it would write — nothing was written.\nexport const UNROSTERED_STAT_LINE_RESOLUTION_OUTCOME_KEYS = ['resolved', 'alreadyResolved'] as const;\nexport type UnrosteredStatLineResolutionOutcome = (typeof UNROSTERED_STAT_LINE_RESOLUTION_OUTCOME_KEYS)[number];\n\n// Why a ghost's removal was refused, in the refusal's details, so the client answers each one: the\n// ghost has played (link it instead) or its removal stopped on finding it had; a game the removal\n// needs is held by another operation (try again shortly); the ghost is being, or was, linked; the\n// ghost is the team's captain (change the captain first).\nexport const GHOST_REMOVAL_REFUSAL_KEYS = ['ghostHasPlayed', 'removalStopped', 'gameHeld', 'ghostBeingLinked', 'captainNotRemovable'] as const;\nexport type GhostRemovalRefusal = (typeof GHOST_REMOVAL_REFUSAL_KEYS)[number];\n\n"]}
|