Skip to content

Commit

Permalink
Implement shootout procedure
Browse files Browse the repository at this point in the history
  • Loading branch information
g3force committed Jul 6, 2023
1 parent 512d623 commit dd937d3
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 52 deletions.
19 changes: 19 additions & 0 deletions frontend/src/components/match/MatchTeamTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {useMatchStateStore} from "@/store/matchState";
import formatDuration from "format-duration";
import {teams} from "@/helpers";
import type {Team} from "@/proto/ssl_gc_common";
import {Referee_Stage} from "@/proto/ssl_gc_referee_message";
import {computed} from "vue";
const store = useMatchStateStore()
Expand All @@ -30,6 +32,12 @@ const nextYellowCardDue = (team: Team) => {
}
return 0
}
const isShootout = computed(() => {
return store.matchState.stage === Referee_Stage.PENALTY_SHOOTOUT
})
const penaltyAttempts = (team: Team) => {
return store.matchState.shootoutState?.numberOfAttempts?.[team] || 0
}
</script>

<template>
Expand Down Expand Up @@ -79,6 +87,17 @@ const nextYellowCardDue = (team: Team) => {
</q-item-label>
</q-item-section>
</q-item>

<q-item v-ripple v-if="isShootout">
<q-item-section class="text-center">
<q-item-label>
{{ penaltyAttempts(team) }}
</q-item-label>
<q-item-label caption>
Number of penalty attempts
</q-item-label>
</q-item-section>
</q-item>
</q-list>
</div>
</template>
35 changes: 34 additions & 1 deletion frontend/src/proto/ssl_gc_state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,12 @@ export interface State_TeamStateEntry {

export interface ShootoutState {
nextTeam?: Team;
numberOfAttempts?: { [key: string]: number };
}

export interface ShootoutState_NumberOfAttemptsEntry {
key: string;
value: number;
}

export const YellowCard = {
Expand Down Expand Up @@ -558,12 +564,39 @@ export const State_TeamStateEntry = {

export const ShootoutState = {
fromJSON(object: any): ShootoutState {
return { nextTeam: isSet(object.nextTeam) ? teamFromJSON(object.nextTeam) : Team.UNKNOWN };
return {
nextTeam: isSet(object.nextTeam) ? teamFromJSON(object.nextTeam) : Team.UNKNOWN,
numberOfAttempts: isObject(object.numberOfAttempts)
? Object.entries(object.numberOfAttempts).reduce<{ [key: string]: number }>((acc, [key, value]) => {
acc[key] = Number(value);
return acc;
}, {})
: {},
};
},

toJSON(message: ShootoutState): unknown {
const obj: any = {};
message.nextTeam !== undefined && (obj.nextTeam = teamToJSON(message.nextTeam));
obj.numberOfAttempts = {};
if (message.numberOfAttempts) {
Object.entries(message.numberOfAttempts).forEach(([k, v]) => {
obj.numberOfAttempts[k] = Math.round(v);
});
}
return obj;
},
};

export const ShootoutState_NumberOfAttemptsEntry = {
fromJSON(object: any): ShootoutState_NumberOfAttemptsEntry {
return { key: isSet(object.key) ? String(object.key) : "", value: isSet(object.value) ? Number(object.value) : 0 };
},

toJSON(message: ShootoutState_NumberOfAttemptsEntry): unknown {
const obj: any = {};
message.key !== undefined && (obj.key = message.key);
message.value !== undefined && (obj.value = Math.round(message.value));
return obj;
},
};
Expand Down
11 changes: 11 additions & 0 deletions internal/app/engine/process_continue_next_action.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,17 @@ func (e *Engine) randomTeam() state.Team {
func suggestEndOfMatch(currentState *state.State) bool {
goalsY := int(*currentState.TeamInfo(state.Team_YELLOW).Goals)
goalsB := int(*currentState.TeamInfo(state.Team_BLUE).Goals)

if *currentState.Stage == state.Referee_PENALTY_SHOOTOUT {
attempts := currentState.ShootoutState.NumberOfAttempts[state.Team_BLUE.String()] +
currentState.ShootoutState.NumberOfAttempts[state.Team_YELLOW.String()]

if attempts < 10 || attempts%2 == 1 {
return false
}
return goalsY != goalsB
}

if *currentState.Stage != state.Referee_POST_GAME &&
(goalsY >= 10 || goalsB >= 10) && math.Abs(float64(goalsY-goalsB)) > 1 {
return true
Expand Down
121 changes: 70 additions & 51 deletions internal/app/state/ssl_gc_state.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions internal/app/statemachine/change_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ func (s *StateMachine) processChangeNewCommand(newState *state.State, newCommand
if *newState.Stage == state.Referee_PENALTY_SHOOTOUT &&
newState.ShootoutState != nil {
if *newCommand.Command.Type == state.Command_NORMAL_START {
newState.ShootoutState.NumberOfAttempts[newState.ShootoutState.NextTeam.String()]++
*newState.ShootoutState.NextTeam = newState.ShootoutState.NextTeam.Opposite()
} else if *newState.GameState.Type == state.GameState_STOP {
forTeam := *newState.ShootoutState.NextTeam
Expand Down
4 changes: 4 additions & 0 deletions internal/app/statemachine/change_stage.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ func (s *StateMachine) proceedStage(newState *state.State, newStage state.Refere
if newStage == state.Referee_PENALTY_SHOOTOUT {
newState.ShootoutState = &state.ShootoutState{
NextTeam: newState.FirstKickoffTeam,
NumberOfAttempts: map[string]int32{
state.Team_BLUE.String(): 0,
state.Team_YELLOW.String(): 0,
},
}
}

Expand Down
1 change: 1 addition & 0 deletions proto/ssl_gc_state.proto
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,5 @@ message State {

message ShootoutState {
optional Team next_team = 1;
map<string, int32> number_of_attempts = 2;
}

0 comments on commit dd937d3

Please sign in to comment.