SPR-846 Infractions extraction

https://spordle.atlassian.net/browse/SPR-846

Extract infractions from the rulebook so they can be extended on for suspensions and customizations.

Requirements

  • Scoresheet entry needs to be able to pull a list of infractions applicable to the branch

    • Currently outside of a game page (e.g., play profile) this isn’t exactly a simple as everything else as the rulebook is in the way

  • Suspensions and sanctioning rules need to be able to reference infractions to target accumulation rules

    • Currently penalties are not using infraction ids, so forced to target based on code

  • SQL-based reports need to be able to determine infraction names properly

    • Currently using initcap based on the infraction code to show infraction names and i18n is not possible

  • Branches need to be able to customize infraction options and extend the HC rulebook

    • Currently should be possible, but hasn’t been tested in practice

    • QC requires an automatic Major when a Match is assessed (similar to Major+GM)

  • Branches may need to be able to override how codes are displayed for each infraction (TBD)

    • Currently not supported

  • Specific types of infractions need to be able to trigger other infractions (ejections) based on accumulation

    • Currently possible

    • Ice hockey requires ejection after 3x stick infraction or 3x head contact

    • Ball hockey requires ejection after 3x any penalty

  • Scoresheet needs to be able to understand how infractions are grouped to keep editing accurate

    • When deleting a major penalty, the game misconduct should be deleted with it

    • This isn’t well solved below yet

Existing

Currently infractions exists within the rulebook only, and penalties reference infraction codes instead of ids. This makes it difficult to reference infractions in other contexts, especially providing a list of possible infractions.

{ "id": "head-contact", "name": "Head Contact", "choices": [ { "id": "712a9d97-dc28-4f44-a9bc-f65f464243d2", "durations": [ { "id": "3b660054-13da-4a10-baae-3726b2b1d5b8", "code": "7.6(a)", "durationId": "minor" } ] }, { "id": "45bd6df7-85cd-4ab3-a1f3-dd19ca403772", "durations": [ { "id": "fc33dd8e-25ca-473b-ab0c-a88d30f109b6", "code": "7.6(a)", "durationId": "minor" }, { "id": "41a36d01-a5f1-4041-af78-105b177b9ff5", "code": "7.6(a)", "durationId": "minor" } ] }, { "id": "b81cffef-c35d-4a34-9fab-10f259a922d1", "durations": [ { "id": "f056be20-062c-4495-b36c-71a4290f5de2", "code": "7.6(b)", "durationId": "major" }, { "id": "00db3d81-87aa-4b71-b63c-44d61fb2e2cf", "code": "7.6(e)", "durationId": "game-misconduct" } ] }, { "id": "8f13e831-9718-44f9-b3b1-5d9e4979ef30", "durations": [ { "id": "177df463-3903-42b1-8b69-35970b1bab67", "code": "7.6(c)", "durationId": "match" } ] } ], "category": "07 Physical Fouls" },

 

  • 7.6 Head Contact
    Category: 07 Physical Fouls

    • Option 1

      • 7.6(a) Minor

    • Option 2

      • 7.6(a) Minor

      • 7.6(a) Minor

    • Option 3

      • 7.6(b) Major

      • 7.6(e) Game Misconduct

    • Option 3

      • 7.6(c) Match

7.6(a) is the infraction, Minor is the duration

Rule Models

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

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

Property

Type

Description

id

uuid

 

seasonId

id

2024-25

officeId

id

Hockey Canada

name

string

Head Contact

code

string

7.6

sectionId

id

Physical Fouls

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

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

Property

Type

Description

id

uuid

 

optionId

id

 

infractionId

id

7.6 (b)

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

Property

Type

Description

id

uuid

 

officeId

id

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

Type

 

Characteristics

Minutes

Shorthanded

Team is shorthanded

Removed

Player is removed from game

Serving Order

Hockey

 

Minor

  • 2 minute penalty, timed

  • Player serves on bench, team shorthanded

2

Yes
Offender

No

2

Bench Minor

  • 2 minute penalty, timed

  • Player serves on bench, team shorthanded

  • Not counted towards stats as offender is not identified

2

Yes
Player

No

2

Major

  • 5 minute penalty, timed

  • Immediate removal (from GM)

  • Another player serves on bench, team shorthanded

5

Yes
Player (due to GM)

No

1

Misconduct

  • 10 minutes, non-timed

  • Player serves on bench

  • Immediate substitution

10

No
Offender (duration)

No

3

Game Misconduct

  • 10 minutes, non-timed

  • Immediate removal

  • Immediate substitution

10

No

Yes

 

Game Ejection

  • 10 minutes, non-timed

  • Immediate removal

  • Immediate substitution

10

No

Yes

 

Gross Misconduct

  • 10 minutes, non-timed

  • Immediate removal

  • Immediate substitution

10

No

Yes

 

Match

  • 5 minutes, timed

  • Immediate removal

  • Another player serves on bench, team shorthanded

5

Yes
Player

Yes

 

Penalty Shot

  • 0 minutes, non-timed

  • No removal, not served

0

No

No

 

Soccer

 

Caution

  • Yellow card

0

No

No

 

Expulsion

  • 2nd Yellow Card

  • Red Card

0

No

Yes

 

Baseball

 

Ejection

  • All penalties

0

No

Yes

 

Infraction

7.6(b) - Head Contact - Minor

Property

Type

Description

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 infraction on GamePenalty for limited backwards compatibility

legacyDuration

string

Used to set duration on GamePenalty for limited backwards compatibility

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

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

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

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.

image-20240521-194805.png

 

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