From fccdcc176eb60a43542f9830b9f83d9ad763668f Mon Sep 17 00:00:00 2001 From: schreifuchs Date: Wed, 19 Feb 2025 14:03:57 +0100 Subject: [PATCH] added matches --- .vscode/launch.json | 15 +++++ .vscode/tasks.json | 23 +++++++ app.go | 70 ++++++++++++++++---- frontend/src/routes/Home.svelte | 5 +- frontend/src/routes/Matches.svelte | 86 +++++++++++++++++++++++-- frontend/src/routes/TourCreator.svelte | 11 ++-- frontend/wailsjs/go/main/App.d.ts | 4 ++ frontend/wailsjs/go/main/App.js | 8 +++ frontend/wailsjs/go/models.ts | 16 ++--- model/model.go | 36 +++++------ tournament.db | Bin 49152 -> 57344 bytes 11 files changed, 224 insertions(+), 50 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..827cc07 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Wails: Debug myproject", + "type": "go", + "request": "launch", + "mode": "exec", + "program": "${workspaceFolder}/build/bin/vscode", + "preLaunchTask": "build", + "cwd": "${workspaceFolder}", + "env": {} + } + ] + } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..3360ab3 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,23 @@ +{ + "version": "2.0.0", + "tasks": [ + + { + "label": "build", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "go", + "args": [ + "build", + "-tags", + "dev", + "-gcflags", + "all=-N -l", + "-o", + "build/bin/vscode" + ], + } + ] + } \ No newline at end of file diff --git a/app.go b/app.go index 2452682..9460bc4 100644 --- a/app.go +++ b/app.go @@ -37,7 +37,7 @@ func (a *App) GetGames() (gs []model.Game, err error) { } func (a *App) GetTournaments() (ts []model.Tournament, err error) { - err = a.db.Preload("Game").Find(&ts).Error + err = a.db.Preload("Game").Preload("WinnerParticipant").Find(&ts).Error return } @@ -117,15 +117,63 @@ func (a *App) RemoveParticipantFromTournament(p model.Participant, t model.Tourn } func (a *App) GetMatches(tID uint) [][]model.Match { - matches := make([][]model.Match, 0) - for { - ms := make([]model.Match, 0) - if err := a.db.Where("tournament_id = ? AND stage = ?", tID, len(matches)).Find(&ms).Error; err != nil || len(ms) == 0 { - fmt.Println(ms) - fmt.Println(err) - return matches - } - slices.SortFunc(ms, func(a, b model.Match) int { return a.Order - b.Order }) - matches = append(matches, ms) + rawMatches := make([]model.Match, 0) + a.db.Preload("Participant1").Preload("Participant2").Preload("WinnerParticipant").Where("tournament_id = ?", tID).Find(&rawMatches) + slices.SortFunc(rawMatches, func(a model.Match, b model.Match) int { return a.Stage - b.Stage }) + + if len(rawMatches) < 1 { + return [][]model.Match{} } + + matches := make([][]model.Match, rawMatches[len(rawMatches)-1].Stage) + for _, match := range rawMatches { + matches[match.Stage-1] = append(matches[match.Stage-1], match) + } + return matches +} + +func (a *App) CreateStage(tID uint) { + oldMatches := a.GetMatches(tID) + + if len(oldMatches) < 1 { + return + } + + participants := make([]model.Participant, 0, len(oldMatches[len(oldMatches)-1])) + + for _, m := range oldMatches[len(oldMatches)-1] { + participants = append(participants, m.WinnerParticipant) + } + + if len(participants) == 0 { + return + } + + stage := oldMatches[len(oldMatches)-1][len(oldMatches[len(oldMatches)-1])-1].Stage + 1 + + matches := make([]model.Match, 0, len(participants)/2) + for i := range len(participants) / 2 { + matches = append(matches, model.Match{ + TournamentID: tID, + Order: i, + Stage: stage, + Participant1ID: participants[i].ID, + Participant2ID: participants[i+len(participants)/2].ID, + }) + } + if len(participants)%2 != 0 { + matches = append(matches, model.Match{ + TournamentID: tID, + Order: len(participants)/2 + 1, + Stage: stage, + Participant1ID: participants[len(participants)-1].ID, + Participant2ID: participants[len(participants)-1].ID, + WinnerParticipantID: participants[len(participants)-1].ID, + }) + } + a.db.Save(matches) +} + +func (a *App) SaveMatch(m *model.Match) { + a.db.Save(m) } diff --git a/frontend/src/routes/Home.svelte b/frontend/src/routes/Home.svelte index 5286e49..ebcdd31 100644 --- a/frontend/src/routes/Home.svelte +++ b/frontend/src/routes/Home.svelte @@ -43,9 +43,7 @@ {t.Game.Name} - - {t.WinnierParticipant.Name} - + {t.WinnerParticipant.Name}
-
diff --git a/frontend/src/routes/Matches.svelte b/frontend/src/routes/Matches.svelte index 18ebe8b..4ba14d2 100644 --- a/frontend/src/routes/Matches.svelte +++ b/frontend/src/routes/Matches.svelte @@ -1,24 +1,49 @@
-
+
-
- e +
- +
+ +
diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index 03aa673..3fc226e 100755 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -2,6 +2,8 @@ // This file is automatically generated. DO NOT EDIT import {model} from '../models'; +export function CreateStage(arg1:number):Promise; + export function DeleteParticipat(arg1:model.Participant):Promise; export function ExportTournament(arg1:model.Tournament):Promise; @@ -20,6 +22,8 @@ export function GetTournaments():Promise>; export function RemoveParticipantFromTournament(arg1:model.Participant,arg2:model.Tournament):Promise; +export function SaveMatch(arg1:model.Match):Promise; + export function SaveParticipant(arg1:model.Participant):Promise; export function SaveTournament(arg1:model.Tournament):Promise; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js index dba73c9..20f31b0 100755 --- a/frontend/wailsjs/go/main/App.js +++ b/frontend/wailsjs/go/main/App.js @@ -2,6 +2,10 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT +export function CreateStage(arg1) { + return window['go']['main']['App']['CreateStage'](arg1); +} + export function DeleteParticipat(arg1) { return window['go']['main']['App']['DeleteParticipat'](arg1); } @@ -38,6 +42,10 @@ export function RemoveParticipantFromTournament(arg1, arg2) { return window['go']['main']['App']['RemoveParticipantFromTournament'](arg1, arg2); } +export function SaveMatch(arg1) { + return window['go']['main']['App']['SaveMatch'](arg1); +} + export function SaveParticipant(arg1) { return window['go']['main']['App']['SaveParticipant'](arg1); } diff --git a/frontend/wailsjs/go/models.ts b/frontend/wailsjs/go/models.ts index 6fb34b3..6c011d9 100755 --- a/frontend/wailsjs/go/models.ts +++ b/frontend/wailsjs/go/models.ts @@ -54,8 +54,8 @@ export namespace model { Game: Game; Size: number; TournamentState: number; - WinnierParticipantID: number; - WinnierParticipant: Participant; + WinnerParticipantID: number; + WinnerParticipant: Participant; Participants: Participant[]; Matches: Match[]; @@ -74,8 +74,8 @@ export namespace model { this.Game = this.convertValues(source["Game"], Game); this.Size = source["Size"]; this.TournamentState = source["TournamentState"]; - this.WinnierParticipantID = source["WinnierParticipantID"]; - this.WinnierParticipant = this.convertValues(source["WinnierParticipant"], Participant); + this.WinnerParticipantID = source["WinnerParticipantID"]; + this.WinnerParticipant = this.convertValues(source["WinnerParticipant"], Participant); this.Participants = this.convertValues(source["Participants"], Participant); this.Matches = this.convertValues(source["Matches"], Match); } @@ -160,8 +160,8 @@ export namespace model { Participant1: Participant; Participant2ID: number; Participant2: Participant; - WinnierParticipantID: number; - WinnierParticipant: Participant; + WinnerParticipantID: number; + WinnerParticipant: Participant; static createFrom(source: any = {}) { return new Match(source); @@ -180,8 +180,8 @@ export namespace model { this.Participant1 = this.convertValues(source["Participant1"], Participant); this.Participant2ID = source["Participant2ID"]; this.Participant2 = this.convertValues(source["Participant2"], Participant); - this.WinnierParticipantID = source["WinnierParticipantID"]; - this.WinnierParticipant = this.convertValues(source["WinnierParticipant"], Participant); + this.WinnerParticipantID = source["WinnerParticipantID"]; + this.WinnerParticipant = this.convertValues(source["WinnerParticipant"], Participant); } convertValues(a: any, classs: any, asMap: boolean = false): any { diff --git a/model/model.go b/model/model.go index 1a5eaff..2e18935 100644 --- a/model/model.go +++ b/model/model.go @@ -19,26 +19,26 @@ type Participant struct { type Tournament struct { gorm.Model - Title string - GameID int - Game Game `gorm:"foreignKey:GameID"` - Size int // number of prarticipants - TournamentState int - WinnierParticipantID int - WinnierParticipant Participant `gorm:"foreignKey:WinnierParticipantID"` - Participants []*Participant `gorm:"many2many:partcipant_tournaments;"` - Matches []Match + Title string + GameID int + Game Game `gorm:"foreignKey:GameID"` + Size int // number of prarticipants + TournamentState int + WinnerParticipantID int + WinnerParticipant Participant `gorm:"foreignKey:WinnerParticipantID"` + Participants []*Participant `gorm:"many2many:partcipant_tournaments;"` + Matches []Match } type Match struct { gorm.Model - TournamentID uint - Stage int - Order int - Participant1ID uint - Participant1 Participant `gorm:"foreignKey:Participant1ID"` - Participant2ID uint - Participant2 Participant `gorm:"foreignKey:Participant2ID"` - WinnierParticipantID uint - WinnierParticipant Participant `gorm:"foreignKey:WinnierParticipantID"` + TournamentID uint + Stage int + Order int + Participant1ID uint + Participant1 Participant `gorm:"foreignKey:Participant1ID"` + Participant2ID uint + Participant2 Participant `gorm:"foreignKey:Participant2ID"` + WinnerParticipantID uint + WinnerParticipant Participant `gorm:"foreignKey:WinnerParticipantID"` } diff --git a/tournament.db b/tournament.db index b917d5ae9403f35a7181c44d92e372237db057cb..75dc330af94cfba0b494b8cb564280dd9441482e 100644 GIT binary patch literal 57344 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