package main import ( "database/sql" "sync" "time" ) var preliminaryRoundStages = []string{"prelim_r1", "prelim_r2", "prelim_r3"} var finalRoundStages = []string{"final_r1", "final_r2"} var tieBreakStages = []string{"prelim_tiebreak", "final_tiebreak"} var scoreStages = append(append(append([]string{}, preliminaryRoundStages...), finalRoundStages...), tieBreakStages...) type App struct { db *sql.DB cfg Config sessions *SessionStore events *EventHub } type SessionStore struct { mu sync.RWMutex tokens map[string]time.Time duration time.Duration } type EventHub struct { mu sync.RWMutex nextID int subscribers map[int]chan struct{} } type CompetitionMeta struct { TitleAr string `json:"titleAr"` TitleEn string `json:"titleEn"` } type Player struct { ID int `json:"id"` NameAr string `json:"nameAr"` NameEn string `json:"nameEn"` GroupCode string `json:"groupCode"` ImageData string `json:"imageData"` } type RankingRow struct { PlayerID int `json:"playerId"` NameAr string `json:"nameAr"` NameEn string `json:"nameEn"` GroupCode string `json:"groupCode"` ImageData string `json:"imageData"` Score int `json:"score"` TieBreak int `json:"tieBreak"` Rank int `json:"rank"` Seed int `json:"seed"` FinalGroup int `json:"finalGroup"` } type TieBreakInfo struct { Required bool `json:"required"` Resolved bool `json:"resolved"` Slots int `json:"slots"` PlayerIDs []int `json:"playerIds"` } type DerivedState struct { PreliminaryRanking RankingBundle `json:"preliminaryRanking"` Finalists []RankingRow `json:"finalists"` FinalGroups FinalGroups `json:"finalGroups"` FinalRanking RankingBundle `json:"finalRanking"` Podium []RankingRow `json:"podium"` } type RankingBundle struct { Rows []RankingRow `json:"rows"` TieBreak TieBreakInfo `json:"tieBreak"` Unresolved bool `json:"unresolved"` } type FinalGroups struct { Group1 []RankingRow `json:"group1"` Group2 []RankingRow `json:"group2"` } type StateResponse struct { Competition CompetitionMeta `json:"competition"` Players []Player `json:"players"` Scores map[string]map[string]int `json:"scores"` ScoreProofs map[string]map[string]string `json:"scoreProofs,omitempty"` Settings AppSettings `json:"settings"` Derived DerivedState `json:"derived"` ServerTime string `json:"serverTime"` } type AppSettings struct { ViewProofInView bool `json:"viewProofInView"` LiveMode LiveModeSettings `json:"liveMode"` } type LiveModeSettings struct { ActiveView string `json:"activeView"` ShowGroupLive bool `json:"showGroupLive"` GroupDisplayMode string `json:"groupDisplayMode"` GroupFixedCode string `json:"groupFixedCode"` ShowPrelimTie bool `json:"showPrelimTie"` ShowPrelimOverall bool `json:"showPrelimOverall"` ShowFinalGroups bool `json:"showFinalGroups"` FinalDisplayMode string `json:"finalDisplayMode"` FinalFixedGroup int `json:"finalFixedGroup"` ShowFinalTie bool `json:"showFinalTie"` ShowPodium bool `json:"showPodium"` RotationIntervalSec int `json:"rotationIntervalSec"` RotationPlayerCount int `json:"rotationPlayerCount"` } type AdminLoginRequest struct { Username string `json:"username"` Password string `json:"password"` } type PlayerCreateRequest struct { NameAr string `json:"nameAr"` NameEn string `json:"nameEn"` GroupCode string `json:"groupCode"` } type PlayerUpdateRequest struct { NameAr *string `json:"nameAr"` NameEn *string `json:"nameEn"` GroupCode *string `json:"groupCode"` ImageData *string `json:"imageData"` ClearImage bool `json:"clearImage"` } type ScoreUpdateRequest struct { Score int `json:"score"` } type ScoreProofUpdateRequest struct { ImageData string `json:"imageData"` } type AdminSettingsUpdateRequest struct { ViewProofInView *bool `json:"viewProofInView"` LiveMode *LiveModeSettingsUpdateRequest `json:"liveMode"` } type LiveModeSettingsUpdateRequest struct { ActiveView *string `json:"activeView"` ShowGroupLive *bool `json:"showGroupLive"` GroupDisplayMode *string `json:"groupDisplayMode"` GroupFixedCode *string `json:"groupFixedCode"` ShowPrelimTie *bool `json:"showPrelimTie"` ShowPrelimOverall *bool `json:"showPrelimOverall"` ShowFinalGroups *bool `json:"showFinalGroups"` FinalDisplayMode *string `json:"finalDisplayMode"` FinalFixedGroup *int `json:"finalFixedGroup"` ShowFinalTie *bool `json:"showFinalTie"` ShowPodium *bool `json:"showPodium"` RotationIntervalSec *int `json:"rotationIntervalSec"` RotationPlayerCount *int `json:"rotationPlayerCount"` } type ResetStageRequest struct { ResetProofs bool `json:"resetProofs"` } type AutoGroupPlayersRequest struct { Groups []string `json:"groups"` } type ScoreAdviceResponse struct { Stage string `json:"stage"` PlayerID int `json:"playerId"` AdvisedScore int `json:"advisedScore"` Reason string `json:"reason"` GeneratedAt string `json:"generatedAt"` }