...
Expand | ||
---|---|---|
| ||
7.6(a) is the infraction, Minor is the duration |
...
Rule Models
Extracting the nested infractions of the rulebook into separate tables for simpler relations and querying.
Bit of a challenge coming up for the names of each part. Infractions
have a Duration
and belong to Rules
which belong to Categories
. Infractions are grouped as Options
to require Major+GM or Double Minors to be selected together.
InfractionDuration
Minor, Major, Match, Misconduct, Game Misconduct
...
Property
...
Type
...
Description
...
id
...
uuid
...
officeId
...
id
...
Hockey Canada
...
name
...
string
...
Minor
...
description
...
string
...
abbreviation
...
string
...
length
...
number
...
Minutes
...
legacyName
...
string
...
Used to set duration
on GamePenalty
for limited backwards compatibility
InfractionCategory
Infractions are categorized in the rulebook as rules. A rule (7.6 Head Contact) belongs to a section (7 Physical Fouls), has many infractions (7.6 (a) Head Contact - Minor) and has many options to apply those infractions (e.g., minor or double minor).
Options define how infractions are used by each office and what the scorekeeper can select. The part that combines double minors or majors and game misconducts as one and results in a time offset.
Purple requires i18n., gray are for backwards compatibility.
RuleSection
07 Physical Fouls
Property | Type | Description |
---|---|---|
id | uuid | |
seasonId | id | 2024-25 |
officeId | id | Hockey Canada |
name | string | Physical Fouls |
code | text | 7 |
...
order | number | Display sort order |
Rule
7.6 Head Contact
Property | Type | Description |
---|---|---|
id | uuid | |
seasonId | id | 2024-25 |
officeId | id | Hockey Canada |
name | string | Head Contact |
code | string | 7.6 |
categoryIdsectionId | id | Physical Fouls |
Infraction
7.6(b) - Head Contact - Minor
...
Property
...
Type
...
Description
...
id
...
uuid
...
seasonId
...
id
...
2024-25
...
officeId
...
id
...
Hockey Canada
...
ruleId
...
id
...
7.6 Head Contact
...
durationId
...
id
...
Minor
...
code
...
string
...
7.6 (b)
...
parentId
...
id
...
Allows overriding a parent infraction by a lower office
...
externalId
...
uuid
...
For syncing with Spordle ID
...
legacyName
...
string
...
Used to set infraction
on GamePenalty
for limited backwards compatibility
...
Behaviour Options
...
severity
...
enum
...
requiresIncidentReport
...
boolean
...
isTimed
...
boolean
...
isServable
...
boolean
Infraction Option Models
Options define how infractions are used by each office and what the scorekeeper can select.
The part that combines double minors or majors and game misconducts as one and results in a time offset.
This is very important when editing so you can make sure that double minors are deleted together or the GM is deleted together with the Major.
Also fun, HQ doesn’t combine majors and game misconducts, so this definitely needs to be configurable by branch.
InfractionOption
...
order | number | Display sort order |
RuleOption
This is a container that represents the options the scorekeeper can select.
This is very important when editing so you can make sure that double minors are deleted together or the GM is deleted together with the Major.
Also fun, HQ doesn’t combine majors and game misconducts, so this definitely needs to be configurable by branch.
Property | Type | Description |
---|---|---|
id | uuid | |
seasonId | id | 2024-25 |
officeId | id | Hockey Canada |
ruleId | id | 7.6 Head Contact (07 Physical Fouls) |
name | string | Display name |
description | string | Optional text to help describe the scenario this option is used for |
parentId | id | Allows overriding a parent option by a lower office |
order | number | Display sort order |
RuleOptionMember
These are the effective infractions upon selecting the option. Order is significant and allows for sequencing penalties as consecutive (e.g., major = 0, GM = 1) or parallel (same order) for start times
Property | Type | Description |
---|---|---|
id | uuid |
optionId | id |
2024-25
infractionId | id |
ruleId
id
7.6 |
( |
b) |
parentId
id
Allows overriding a parent option by a lower office
InfractionOptionMember
...
No unique constraint to allow for double minors | ||
order | number | Serving order |
Infraction Models
When creating a penalty, you’re presented with a list of rules and then select an option. That option then results in one or many penalties that are linked to an infraction.
InfractionType
Minor, Major, Match, Misconduct, Game Misconduct, Gross Misconduct, Game Ejection
Property | Type | Description |
---|---|---|
id | uuid |
officeId | id |
infractionId
id
7.6 (b)
No unique constraint to allow for double minors
order
number
Infraction Accumulation Models
When creating a penalty, we need to check for accumulation rules to stack an additional infraction.
Typical examples are 3x Stick Infraction → Game Ejection or 2x Misconduct → Game Ejection.
InfractionAccumulation
This acts as a grouping that defines the count of the member infractions necessary and what the resulting infraction is.
...
Property
...
Type
...
Description
...
id
...
uuid
...
seasonId
...
id
...
2023-24
...
officeId
...
id
...
Hockey Canada
...
name
...
string
...
Stick Infractions
...
count
...
number
...
3
...
infractionId
...
id
...
Resulting infraction when accumulation reached
4.8 (b)
InfractionAccumulationMember
These are the list of infractions that are part of the accumulation group. Order is not significant; any member infraction counts towards the accumulation group.
So for stick infractions, receiving 9.1 (a), 9.2 (a) and 9.3 (a) would result in a game ejection upon receiving 9.3 (a).
To account for double minors, penalties with the same infraction, game time and option are counted as one. Therefore a minor head contact (1x 7.6 (a)) by a double minor head contact (2x 7.6 (a)) continues to be counted as 2 despite there being 3x 7.6 (a).
...
Property
...
Type
...
Description
...
id
...
uuid
...
accumulationId
...
id
...
2023-24
...
infractionId
...
id
...
9.1 (a)
Penalty Models
GamePenalty
Instances of an infraction in a game are called penalties. This is a scoresheet artifact.
...
Property
...
Type
...
Description
...
id
...
uuid
...
gameId
...
id
...
teamId
...
id
...
participantId
...
id
...
servedById
...
id
...
isInjured
...
boolean
...
Necessary for suspensions
...
Time
...
gameTime
...
GameTime
...
Time of infraction
...
startTime
...
GameTime
...
Time the penalty started to be served
...
endTime
...
GameTime
...
Time the penalty ceased to be served
...
isEnded
...
boolean
...
Whether or not the penalty was ended
...
Infraction
...
infractionId
...
id
...
durationId
...
id
...
Technically not really necessary since the durationId is part of the infraction above
...
optionId
...
id
...
Link penalties part of the same option group when creating instead of trying to reverse them as we currently do
...
accumulationId
...
id
...
Link penalties that were created by an accumulation rule
...
Legacy infraction options (deprecated)
...
infraction
...
string
...
Infraction “id” which is something like “head-contact” in the rulebook
...
duration
...
string
...
Duration “id” which is something like “minor” in the rulebook
...
code
...
string
...
Infraction “code”
Penalties are consisted linked if they have the same participantId
, gameTime
and optionId
or have an accumulationId
that matches.
Implementation
Scoresheets are effectively versioned by season. This is limited to 2024-25 and beyond seasons; 2023-24 and past seasons would maintain legacy rulebook support. Must maintain the same behaviour for past seasons (2018 - 2023), but new seasons would use the new models.
The /meta API should return all applicable infraction, infraction option and accumulation entities.
...
Hockey Canada | ||
name | string | Minor |
description | string | |
abbreviation | string | |
duration | number | Total time for stats |
servedBy | string | Determines if the penalty has endTime & servedById None | Offender | Player |
isShorthanded | boolean | Determines if the penalty may be cancelled out with coincidental penalties of same type |
isEjection | boolean | Penalty results in player being ejected for remainder of game |
servingOrder | number | When multiple infractions are selected at one start time, helps stagger the times. Order is major/minor/misconduct. Optional. If not specified, will be ordered after any ordered infractions |
Characteristics
Duration indicates that there’s an end time, unless there’s also a removal and not shorthanded.
Can determine if someone else should be serving if any penalty in the option has an ejection
If a major/minor/misconduct are called at the same game time, the start time will be staggered
Type | Characteristics | Minutes | Shorthanded Team is shorthanded | Removed Player is removed from game | Serving Order |
---|---|---|---|---|---|
Hockey | |||||
Minor |
| 2 | Yes | No | 2 |
Bench Minor |
| 2 | Yes | No | 2 |
Major |
| 5 | Yes | No | 1 |
Misconduct |
| 10 | No | No | 3 |
Game Misconduct |
| 10 | No | Yes | |
Game Ejection |
| 10 | No | Yes | |
Gross Misconduct |
| 10 | No | Yes | |
Match |
| 5 | Yes | Yes | |
Penalty Shot |
| 0 | No | No | |
Soccer | |||||
Caution |
| 0 | No | No | |
Expulsion |
| 0 | No | Yes | |
Baseball | |||||
Ejection |
| 0 | No | Yes |
Infraction
7.6(b) - Head Contact - Minor
Property | Type | Description |
---|---|---|
id | uuid | |
seasonId | id | 2024-25 |
officeId | id | Hockey Canada |
ruleId | id | 7.6 Head Contact |
typeId | id | Minor |
code | string | 7.6 (b) |
severity | enum | Low | Medium | High | Severe |
order | number | Display sort order |
parentId | id | Allows overriding a parent infraction by a lower office |
externalId | uuid | For syncing with Spordle ID |
legacyName | string | Used to set |
legacyDuration | string | Used to set |
Behaviour Options |
Accumulation Models
When creating a penalty, we need to check for accumulation rules to stack an additional infraction.
Typical examples are 3x Stick Infraction → Game Ejection or 2x Misconduct → Game Ejection.
InfractionAccumulation
This acts as a grouping that defines the count of the member infractions necessary and what the resulting infraction is.
Property | Type | Description |
---|---|---|
id | uuid | |
seasonId | id | 2023-24 |
officeId | id | Hockey Canada |
name | string | Stick Infractions |
count | number | 3 |
infractionId | id | Resulting infraction when accumulation reached 4.8 (b) |
isReplacement | boolean | Whether the accumulation acts as a replacement infraction or not e.g., 2nd yellow → Yellow/Red Card |
InfractionAccumulationMember
These are the list of infractions that are part of the accumulation group. Order is not significant; any member infraction counts towards the accumulation group.
So for stick infractions, receiving 9.1 (a), 9.2 (a) and 9.3 (a) would result in a game ejection upon receiving 9.3 (a).
To account for double minors, penalties with the same infraction, game time and option are counted as one. Therefore a minor head contact (1x 7.6 (a)) by a double minor head contact (2x 7.6 (a)) continues to be counted as 2 despite there being 3x 7.6 (a).
Property | Type | Description |
---|---|---|
id | uuid | |
accumulationId | id | 2023-24 |
infractionId | id | 9.1 (a) |
Penalty Models
Yellow are new properties, red are deprecated.
GamePenalty
Instances of an infraction in a game are called penalties. This is a scoresheet artifact.
Property | Type | Description |
---|---|---|
id | uuid | |
gameId | id | |
teamId | id | |
participantId | id | |
servedById | id | |
isInjured | boolean | Necessary for suspensions |
Time | ||
gameTime | GameTime | Time of infraction |
startTime | GameTime | Time the penalty started to be served |
endTime | GameTime | Time the penalty ceased to be served |
isEnded | boolean | Whether or not the penalty was ended |
Infraction | ||
infractionId | id | |
optionId | id | Link penalties part of the same option group when creating instead of trying to reverse them as we currently do |
accumulationId | id | Link penalties that were created by an accumulation rule |
Legacy infraction options (deprecated) | ||
infraction | string | Infraction “id” which is something like “head-contact” in the rulebook |
duration | string | Duration “id” which is something like “minor” in the rulebook |
code | string | Infraction “code” |
Penalties are consisted linked if they have the same participantId
, gameTime
and optionId
or have an accumulationId
that matches.
Implementation
Scoresheets are effectively versioned by season. This is limited to 2024-25 and beyond seasons; 2023-24 and past seasons would maintain legacy rulebook support. Must maintain the same behaviour for past seasons (2018 - 2023), but new seasons would use the new models.
The /meta API should return all applicable infraction, infraction option and accumulation entities.
...
Administration
A new Rulebook office tab will be added that will show rules, infractions, options and accumulations as individual cards. Each card would have a filter to show effective offices, but editing is disabled if the office doesn’t match.
Rules, Rule Sections, Infraction Types
These are only configurable by top-level offices.
Meta
Meta is critical for building the effective rulebook for the scorekeeping interface, as the app needs to be able to function offline, so it needs all data up front. Another key bit is we need to resolve all the overridden rules by child organizations.
2023-24 and prior seasons must continue to maintain backwards-compatible support and resolve using the legacy rulebook.
Rules, Rule Sections, Infraction Types
These are not overridable, so all effective entities should be included.
Infractions
These can be overridden, so when a parentId
is present, the parent is excluded from the result.
Options, Accumulations
Similar to infractions, can be overridden.
Payload
This payload basically keeps everything at the top-level unlike the legacy payload so it’s easy to resolve references, and the app can decide to nest infractions into rules into sections as needed. The legacy ejections key is replaced by accumulations.
types
sections
rules
infractions
options
members
accumulations
members
lineupLimits / pitcherLimits
Penalty Management
Legend for the examples given below
A being a match penalty (from the rule option)
B being a game misconduct penalty (from the rule option)
C being a game ejection (from accumulation rule)
Linked Penalties: Bundle of penalties created off of a rule option. This includes accumulation penalties caused by the rule option (from an accumulation rule).
Ex. rule option resulted in A, B, C → A, B, C would get returned)
First Linked Penalty: First penalty in the linked penalties.
Ex. a rule option resulted in A, B, C
passing the penalty A → A would get returned
passing C → A would get returned)
Subsequent Linked Penalties: Penalties after the first one in the linked penalties.
Ex. a rule option resulted in A, B, C
passing penalty A → B, C would get returned
passing penalty C → B, C would get returned
Adding a penalty
Pick a rule option → Results in a bundle of linked penalties (an accumulation infraction might get added if an accumulation rule is fulfilled)
Editing a penalty
First penalty in the linked penalties → Fully editable (can change rule option, participant, start time, off time) and deletable.
Changing the rule option will remove all linked penalties and create the new penalties based off of the new rule option.
Changing the participant / start time / off time will change for all the linked penalties
Deleting the penalty will automatically delete subsequent penalties (this includes the accumulation penalties)
Subsequent penalties in the linked penalties → Partially editable (can change only the start time) and deletable.
Changing the start time will not affect the other penalties
Deleting any of the subsequent penalty that isn’t an accumulation will automatically delete subsequent penalties (this includes the accumulation penalties)
Deleting an accumulation penalty will always only delete the one penalty