Skip to content

Commit

Permalink
Combine game event proposals with accepted game events
Browse files Browse the repository at this point in the history
  • Loading branch information
g3force committed Aug 6, 2023
1 parent c13f596 commit f272195
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 90 deletions.
11 changes: 9 additions & 2 deletions frontend/src/components/match/GameEventItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import {gameEventNames} from "@/helpers/texts";
import type {GameEvent} from "@/proto/ssl_gc_game_event";
import {gameEventForTeam, originIcon} from "@/helpers";
import GameEventDetailsTree from "@/components/match/GameEventDetailsTree.vue";
import dayjs from "dayjs";
const props = defineProps<{
gameEvent: GameEvent,
caption?: string,
}>()
const label = computed(() => {
Expand All @@ -22,6 +22,13 @@ const team = computed(() => {
const origins = computed(() => {
return props.gameEvent.origin
})
const time = computed(() => {
if (props.gameEvent.createdTimestamp) {
return dayjs(props.gameEvent.createdTimestamp / 1e3).format("MMM, DD YYYY HH:mm:ss,SSS")
}
return undefined
})
</script>

<template>
Expand All @@ -32,7 +39,7 @@ const origins = computed(() => {
<TeamBadge :team="team"/>
{{ label }}
</q-item-label>
<q-item-label caption v-if="caption">{{ caption }}</q-item-label>
<q-item-label caption v-if="time">{{ time }}</q-item-label>
</q-item-section>
<q-item-section side>
<div class="row">
Expand Down
20 changes: 0 additions & 20 deletions frontend/src/components/match/GameEventList.vue

This file was deleted.

41 changes: 37 additions & 4 deletions frontend/src/components/match/GameEventProposalGroupItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ import {gameEventNames} from "@/helpers/texts";
import type {ControlApi} from "@/providers/controlApi/ControlApi";
import type {ProposalGroup} from "@/proto/ssl_gc_state";
import type {GameEvent} from "@/proto/ssl_gc_game_event";
import TeamBadge from "@/components/common/TeamBadge.vue";
import {gameEventForTeam, originIcon} from "@/helpers";
import GameEventItem from "@/components/match/GameEventItem.vue";
const props = defineProps<{
proposalGroup: ProposalGroup,
groupId: string,
acceptedGameEvent?: GameEvent,
}>()
const control = inject<ControlApi>('control-api')
Expand All @@ -22,9 +26,26 @@ const gameEventLabel = (gameEvent: GameEvent) => {
}
const label = computed(() => {
if (props.acceptedGameEvent) {
return gameEventLabel(props.acceptedGameEvent)
}
return Array.from(new Set(proposals.value?.map(p => gameEventLabel(p.gameEvent!))).values()).join(" / ")
})
const teams = computed(() => {
if (props.acceptedGameEvent) {
return Array.of(gameEventForTeam(props.acceptedGameEvent))
}
return Array.from(new Set(proposals.value?.map(p => gameEventForTeam(p.gameEvent!))).values())
})
const origins = computed(() => {
if (props.acceptedGameEvent) {
return props.acceptedGameEvent.origin
}
return Array.from(new Set(proposals.value?.flatMap(p => p.gameEvent?.origin || []).values()))
})
const pending = computed(() => {
return !props.proposalGroup.accepted
})
Expand All @@ -48,17 +69,29 @@ const acceptGroup = () => {
:default-opened="pending"
>
<template v-slot:header>
<q-item-section side>
<q-item-section side v-if="pending">
<q-icon :name="groupIcon"/>
</q-item-section>
<q-item-section>
<q-item-label>{{ label }}</q-item-label>
<q-item-label>
<TeamBadge v-for="team in teams" :team="team" :key="team"/>
{{ label }}
</q-item-label>
</q-item-section>
<q-item-section side v-if="pending">
<q-btn flat dense round icon="done" @click="acceptGroup"/>
<q-item-section side>
<div class="row">
<q-icon class="q-mx-xs" :name="originIcon(origin)" color="primary" :alt="origin"
v-for="(origin, key) in origins" :key="key">
<q-tooltip>
{{ origin }}
</q-tooltip>
</q-icon>
</div>
<q-btn flat dense round icon="done" @click="acceptGroup" v-if="pending"/>
</q-item-section>
</template>
<q-list>
<GameEventItem :game-event="acceptedGameEvent" v-if="acceptedGameEvent"/>
<GameEventProposalItem :proposal="proposal" v-for="(proposal, key) in proposals" :key="key"/>
</q-list>
</q-expansion-item>
Expand Down
25 changes: 0 additions & 25 deletions frontend/src/components/match/GameEventProposalGroupItemList.vue

This file was deleted.

7 changes: 1 addition & 6 deletions frontend/src/components/match/GameEventProposalItem.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
<script setup lang="ts">
import {computed} from "vue";
import GameEventItem from "@/components/match/GameEventItem.vue";
import dayjs from 'dayjs'
import type {Proposal} from "@/proto/ssl_gc_state";
const props = defineProps<{
proposal: Proposal,
}>()
const time = computed(() => {
return dayjs(props.proposal.timestamp).format("MMM, DD YYYY HH:mm:ss,SSS")
})
const gameEvent = computed(() => {
return props.proposal.gameEvent!
})
</script>

<template>
<GameEventItem :game-event="gameEvent" :caption="time"/>
<GameEventItem :game-event="gameEvent"/>
</template>
69 changes: 69 additions & 0 deletions frontend/src/components/match/GameEvents.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<script setup lang="ts">
import {computed} from "vue";
import GameEventItem from "@/components/match/GameEventItem.vue";
import GameEventProposalGroupItem from "@/components/match/GameEventProposalGroupItem.vue";
import {useMatchStateStore} from "@/store/matchState";
import type {ProposalGroup} from "@/proto/ssl_gc_state";
import type {GameEvent} from "@/proto/ssl_gc_game_event";
const store = useMatchStateStore()
type GameEventWrappedItem = {
id: string
timestamp: number
proposalGroup?: ProposalGroup
gameEvent?: GameEvent
}
const gameEventItems = computed(() => {
const gameEvents = store.matchState.gameEvents!
const proposalGroups = store.matchState.proposalGroups!
const items: GameEventWrappedItem[] = []
for (const proposalGroup of proposalGroups) {
const item: GameEventWrappedItem = {
id: proposalGroup.id!,
timestamp: proposalGroup.proposals![0].timestamp!.getTime(),
proposalGroup: proposalGroup,
}
items.push(item)
}
for (const gameEvent of gameEvents) {
let gameEventItem = items.find(item => item.id === gameEvent.id);
if (gameEventItem) {
gameEventItem.gameEvent = gameEvent
} else {
const item: GameEventWrappedItem = {
id: gameEvent.id!,
timestamp: gameEvent.createdTimestamp! / 1000,
gameEvent: gameEvent,
}
items.push(item)
}
}
items.sort((a, b) => a.timestamp - b.timestamp)
return items
})
</script>

<template>
<q-list bordered class="rounded-borders" v-if="gameEventItems.length > 0">
<template v-for="(item) in gameEventItems">
<GameEventProposalGroupItem
v-if="item.proposalGroup"
:proposal-group="item.proposalGroup"
:group-id="item.id"
:accepted-game-event="item.gameEvent"
:key="item.id"
/>
<GameEventItem
v-else-if="item.gameEvent"
:game-event="item.gameEvent"
:key="item.id"
/>
</template>
</q-list>
<div v-else>
No recent game event proposals
</div>
</template>
6 changes: 2 additions & 4 deletions frontend/src/views/MatchView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
import {computed, inject, onMounted, onUnmounted} from "vue";
import ContinueActionButtonList from "@/components/match/ContinueActionButtonList.vue";
import AutoContinueInput from "@/components/match/AutoContinueInput.vue";
import GameEventProposalGroupItemList from "@/components/match/GameEventProposalGroupItemList.vue";
import GameEventList from "@/components/match/GameEventList.vue";
import MatchTeamTable from "@/components/match/MatchTeamTable.vue";
import type {ControlApi} from "@/providers/controlApi/ControlApi";
import {useGcStateStore} from "@/store/gcState";
Expand All @@ -13,6 +11,7 @@ import {useMatchStateStore} from "@/store/matchState";
import {Referee_Stage} from "@/proto/ssl_gc_referee_message";
import SwitchSidesButton from "@/components/start/SwitchSidesButton.vue";
import HaltButton from "@/components/control/HaltButton.vue";
import GameEvents from "@/components/match/GameEvents.vue";
const store = useMatchStateStore()
const gcStore = useGcStateStore()
Expand Down Expand Up @@ -113,8 +112,7 @@ onUnmounted(() => {
<ContinueActionButtonList/>
</div>
<div class="col q-gutter-md q-mr-md" style="min-width: 300px">
<GameEventProposalGroupItemList/>
<GameEventList/>
<GameEvents/>
</div>
</div>
</template>
56 changes: 27 additions & 29 deletions internal/app/engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,27 +82,6 @@ func NewEngine(gameConfig config.Game, engineConfig config.Engine) (e *Engine) {

// Enqueue adds the change to the change queue
func (e *Engine) Enqueue(change *statemachine.Change) {
if change.GetAddGameEventChange() != nil {
change.GetAddGameEventChange().GameEvent = e.processGameEvent(change.GetAddGameEventChange().GameEvent)
change = e.handleGameEventBehavior(change)
if change == nil {
return
}
} else if change.GetAddPassiveGameEventChange() != nil {
change.GetAddPassiveGameEventChange().GameEvent = e.processGameEvent(change.GetAddPassiveGameEventChange().GameEvent)
} else if change.GetAddProposalChange() != nil {
log.Println("Ignoring unexpected proposal change: ", change.GetAddProposalChange())
return
}

if change.Revertible == nil {
change.Revertible = new(bool)
// Assume that changes from outside are by default revertible, except if the flag is already set
*change.Revertible = true
}
if change.Origin == nil {
change.Origin = proto.String("Unknown")
}
e.changeQueue <- change
}

Expand Down Expand Up @@ -146,18 +125,16 @@ func isNonMajorityOrigin(origins []string) bool {

func (e *Engine) processGameEvent(gameEvent *state.GameEvent) *state.GameEvent {
// Set creation timestamp
if gameEvent.CreatedTimestamp != nil {
log.Printf("Ignore existing created_timestamp in enqueued game event: %v", gameEvent)
if gameEvent.CreatedTimestamp == nil {
gameEvent.CreatedTimestamp = new(uint64)
*gameEvent.CreatedTimestamp = uint64(e.timeProvider().UnixMicro())
}
gameEvent.CreatedTimestamp = new(uint64)
*gameEvent.CreatedTimestamp = uint64(e.timeProvider().UnixMicro())

// Set unique id
if gameEvent.Id != nil {
log.Printf("Ignore existing id in enqueued game event: %v", gameEvent)
if gameEvent.Id == nil {
gameEvent.Id = new(string)
*gameEvent.Id = uuid.NewString()
}
gameEvent.Id = new(string)
*gameEvent.Id = uuid.NewString()

// convert aimless kick if necessary
if e.currentState.Division.Div() == config.DivA && *gameEvent.Type == state.GameEvent_AIMLESS_KICK {
Expand Down Expand Up @@ -382,6 +359,27 @@ func (e *Engine) processChange(change *statemachine.Change) (newChanges []*state
e.mutex.Lock()
defer e.mutex.Unlock()

if change.GetAddGameEventChange() != nil {
change.GetAddGameEventChange().GameEvent = e.processGameEvent(change.GetAddGameEventChange().GameEvent)
change = e.handleGameEventBehavior(change)
if change == nil {
return
}
} else if change.GetAddPassiveGameEventChange() != nil {
change.GetAddPassiveGameEventChange().GameEvent = e.processGameEvent(change.GetAddPassiveGameEventChange().GameEvent)
} else if change.GetAddProposalChange() != nil {
change.GetAddProposalChange().Proposal.GameEvent = e.processGameEvent(change.GetAddProposalChange().Proposal.GameEvent)
}

if change.Revertible == nil {
change.Revertible = new(bool)
// Assume that changes from outside are by default revertible, except if the flag is already set
*change.Revertible = true
}
if change.Origin == nil {
change.Origin = proto.String("Unknown")
}

var entry = e.stateStore.CreateEntry(change, e.timeProvider(), e.currentState)
log.Printf("Process change %d: %+v", *entry.Id, change.StringJson())

Expand Down
3 changes: 3 additions & 0 deletions internal/app/engine/process_proposals.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ func (e *Engine) uniqueAcceptingOrigins(group *state.ProposalGroup) int {
origins := map[string]bool{}
for _, p := range group.Proposals {
for _, o := range p.GameEvent.Origin {
if _, ok := e.config.AutoRefConfigs[o]; !ok {
continue
}
if e.config.AutoRefConfigs[o].GameEventBehavior[p.GameEvent.Type.String()] == AutoRefConfig_BEHAVIOR_ACCEPT {
origins[o] = true
}
Expand Down

0 comments on commit f272195

Please sign in to comment.