From dbcf5decb89832c3f1a764588a15cb07327cbfd7 Mon Sep 17 00:00:00 2001 From: zuma Date: Tue, 10 Jun 2025 22:43:49 +0200 Subject: [PATCH] Feat: Update ELO when a change is made --- backend/README.md | 3 +- backend/hooks.go | 180 ++++++++++++++++++++++++---------------------- 2 files changed, 97 insertions(+), 86 deletions(-) diff --git a/backend/README.md b/backend/README.md index 731cdb3..0bcfd4b 100644 --- a/backend/README.md +++ b/backend/README.md @@ -3,7 +3,8 @@ Le backend du site Brawlset est codé en [GO](https://go.dev/) et utilise [Pocke # TODO - [x] Feat : Créer le système d'ELO -- [ ] Feat : Update les ELO quand il y a un changement ou une suppression de match +- [x] Feat : Update les ELO quand il y a un changement +- [ ] Feat : Update les ELO quand il y a une suppression de match - [x] Fix : Changer le recto / verso des cartes - [ ] Feat : Système d'évènements à ajouter sur la page principale - [ ] Fix : Refuse to create deck when cards are not found diff --git a/backend/hooks.go b/backend/hooks.go index d76192e..a62c18e 100644 --- a/backend/hooks.go +++ b/backend/hooks.go @@ -18,85 +18,54 @@ type DuelResult struct { } func (app *application) SetupHooks() { + default_ELO_value := 100.0 // Set default values after creation app.pb.OnRecordAfterCreateSuccess("elo_player").BindFunc(func (e *core.RecordEvent) error { - e.Record.Set("elo_casual", 100) - e.Record.Set("elo_tournament", 100) + e.Record.Set("elo_casual", default_ELO_value) + e.Record.Set("elo_tournament", default_ELO_value) e.App.Save(e.Record) log.Println("record created") return e.Next() }) + app.pb.OnRecordUpdate("elo").BindFunc(func (e *core.RecordEvent) error { + // Check if any of these fields has been changed : Player1, Player2, Commandant1, Commandant2, Score1, Score2, Date, Official + if(e.Record.GetString("player_1") != e.Record.Original().GetString("player_1") || e.Record.GetString("player_2") != e.Record.Original().GetString("player_2") || e.Record.GetString("commandant_1") != e.Record.Original().GetString("commandant_1") || e.Record.GetString("commandant_2") != e.Record.Original().GetString("commandant_2") || e.Record.GetString("score_1") != e.Record.Original().GetString("score_1") || e.Record.GetString("score_2") != e.Record.Original().GetString("score_2") || e.Record.GetString("date") != e.Record.Original().GetString("date") || e.Record.GetString("official") != e.Record.Original().GetString("official")) { + UpdateRecordELO(e, default_ELO_value) + UpdateLastELO(e, e.Record.GetFloat("elo_player_1"), e.Record.GetFloat("elo_player_2"), e.Record.GetFloat("elo_commandant_1"), e.Record.GetFloat("elo_commandant_2")) + updateNextMatchs(e, DuelResult{ + Player1_NewELO: e.Record.GetFloat("elo_player_1"), + Player2_NewELO: e.Record.GetFloat("elo_player_2"), + Commander1_NewELO: e.Record.GetFloat("elo_commandant_1"), + Commander2_NewELO: e.Record.GetFloat("elo_commandant_2"), + }) + + } + + return e.Next() + }) + // When a ELO entry has been added app.pb.OnRecordCreate("elo").BindFunc(func (e *core.RecordEvent) error { - date := e.Record.GetString("date") - official := e.Record.GetBool("official") - player1Id := e.Record.GetString("player_1") - player2Id := e.Record.GetString("player_2") - commander1Id := e.Record.GetString("commandant_1") - commander2Id := e.Record.GetString("commandant_2") - score1 := e.Record.GetInt("score_1") - score2 := e.Record.GetInt("score_2") + UpdateRecordELO(e, default_ELO_value) - // Base data in case it's the first match - player1_ELO := 100.0 - player2_ELO := 100.0 - commander1_ELO := 100.0 - commander2_ELO := 100.0 + UpdateLastELO(e, e.Record.GetFloat("elo_player_1"), e.Record.GetFloat("elo_player_2"), e.Record.GetFloat("elo_commandant_1"), e.Record.GetFloat("elo_commandant_2")) - // Update ELO With last match ELO (Tournament or Casual) - updateEloPlayerWithLastMatch(e, player1Id, date, &player1_ELO, official) - updateEloPlayerWithLastMatch(e, player2Id, date, &player2_ELO, official) - - // Update ELO With last match ELO (Tournament or Casual) - updateEloCommanderWithLastMatch(e, commander1Id, date, &commander1_ELO, official) - updateEloCommanderWithLastMatch(e, commander2Id, date, &commander2_ELO, official) - - newData := CalculateELO(player1_ELO, player2_ELO, commander1_ELO, commander2_ELO, score1, score2) - - e.Record.Set("last_elo_player_1", player1_ELO) - e.Record.Set("elo_player_1", newData.Player1_NewELO) - e.Record.Set("last_elo_player_2", player2_ELO) - e.Record.Set("elo_player_2", newData.Player2_NewELO) - e.Record.Set("last_elo_commandant_1", commander1_ELO) - e.Record.Set("elo_commandant_1", newData.Commander1_NewELO) - e.Record.Set("last_elo_commandant_2", commander2_ELO) - e.Record.Set("elo_commandant_2", newData.Commander2_NewELO) - - recordPlayer1, _ := e.App.FindRecordById("elo_player", player1Id) - recordPlayer2, _ := e.App.FindRecordById("elo_player", player2Id) - if official { - recordPlayer1.Set("elo_tournament", newData.Player1_NewELO) - recordPlayer2.Set("elo_tournament", newData.Player2_NewELO) - } else { - recordPlayer1.Set("elo_casual", newData.Player1_NewELO) - recordPlayer2.Set("elo_casual", newData.Player2_NewELO) - } - - recordCommander1, _ := e.App.FindRecordById("carte", commander1Id) - recordCommander2, _ := e.App.FindRecordById("carte", commander2Id) - if official { - recordCommander1.Set("elo_tournament", newData.Commander1_NewELO) - recordCommander2.Set("elo_tournament", newData.Commander2_NewELO) - } else { - recordCommander1.Set("elo_casual", newData.Commander1_NewELO) - recordCommander2.Set("elo_casual", newData.Commander2_NewELO) - } - - e.App.Save(recordPlayer1) - e.App.Save(recordPlayer2) - e.App.Save(recordCommander1) - e.App.Save(recordCommander2) - - updateNextMatchs(e, newData, official) + updateNextMatchs(e, DuelResult{ + Player1_NewELO: e.Record.GetFloat("elo_player_1"), + Player2_NewELO: e.Record.GetFloat("elo_player_2"), + Commander1_NewELO: e.Record.GetFloat("elo_commandant_1"), + Commander2_NewELO: e.Record.GetFloat("elo_commandant_2"), + }) return e.Next() }) } -func updateNextMatchs(e *core.RecordEvent, newData DuelResult, official bool) { +func updateNextMatchs(e *core.RecordEvent, newData DuelResult) { + official := e.Record.GetBool("official") needToRecalculateElo := false nextMatchsCount, _ := e.App.CountRecords("elo", dbx.And(dbx.And(dbx.NewExp("date > {:date}", dbx.Params{"date": e.Record.GetString("date")}), dbx.NewExp("official = {:official}", dbx.Params{"official": official})),dbx.Or(dbx.NewExp("player_1 = {:id}", dbx.Params{"id": e.Record.GetString("player_1")}), dbx.NewExp("player_2 = {:id}", dbx.Params{"id": e.Record.GetString("player_1")})))) @@ -193,33 +162,74 @@ func updateNextMatchs(e *core.RecordEvent, newData DuelResult, official bool) { } } - recordPlayer1, _ := e.App.FindRecordById("elo_player", e.Record.GetString("player_1")) - recordPlayer2, _ := e.App.FindRecordById("elo_player", e.Record.GetString("player_2")) - if official { - recordPlayer1.Set("elo_tournament", newPlayerData[e.Record.GetString("player_1")]) - recordPlayer2.Set("elo_tournament", newPlayerData[e.Record.GetString("player_2")]) - } else { - recordPlayer1.Set("elo_casual", newPlayerData[e.Record.GetString("player_1")]) - recordPlayer2.Set("elo_casual", newPlayerData[e.Record.GetString("player_2")]) - } - - recordCommander1, _ := e.App.FindRecordById("carte", e.Record.GetString("commandant_1")) - recordCommander2, _ := e.App.FindRecordById("carte", e.Record.GetString("commandant_2")) - if official { - recordCommander1.Set("elo_tournament", newCommanderData[e.Record.GetString("commandant_1")]) - recordCommander2.Set("elo_tournament", newCommanderData[e.Record.GetString("commandant_2")]) - } else { - recordCommander1.Set("elo_casual", newCommanderData[e.Record.GetString("commandant_1")]) - recordCommander2.Set("elo_casual", newCommanderData[e.Record.GetString("commandant_2")]) - } - - e.App.Save(recordPlayer1) - e.App.Save(recordPlayer2) - e.App.Save(recordCommander1) - e.App.Save(recordCommander2) + UpdateLastELO(e, newPlayerData[e.Record.GetString("player_1")], newPlayerData[e.Record.GetString("player_2")], newCommanderData[e.Record.GetString("commandant_1")], newCommanderData[e.Record.GetString("commandant_2")]) } } +func UpdateLastELO(e *core.RecordEvent, player1_ELO float64, player2_ELO float64, commander1_ELO float64, commander2_ELO float64) { + recordPlayer1, _ := e.App.FindRecordById("elo_player", e.Record.GetString("player_1")) + recordPlayer2, _ := e.App.FindRecordById("elo_player", e.Record.GetString("player_2")) + if e.Record.GetBool("official") { + recordPlayer1.Set("elo_tournament", player1_ELO) + recordPlayer2.Set("elo_tournament", player2_ELO) + } else { + recordPlayer1.Set("elo_casual", player1_ELO) + recordPlayer2.Set("elo_casual", player2_ELO) + } + + recordCommander1, _ := e.App.FindRecordById("carte", e.Record.GetString("commandant_1")) + recordCommander2, _ := e.App.FindRecordById("carte", e.Record.GetString("commandant_2")) + if e.Record.GetBool("official") { + recordCommander1.Set("elo_tournament", commander1_ELO) + recordCommander2.Set("elo_tournament", commander2_ELO) + } else { + recordCommander1.Set("elo_casual", commander1_ELO) + recordCommander2.Set("elo_casual", commander2_ELO) + } + + e.App.Save(recordPlayer1) + e.App.Save(recordPlayer2) + e.App.Save(recordCommander1) + e.App.Save(recordCommander2) + +} + +func UpdateRecordELO(e *core.RecordEvent, default_ELO_value float64) { + date := e.Record.GetString("date") + official := e.Record.GetBool("official") + player1Id := e.Record.GetString("player_1") + player2Id := e.Record.GetString("player_2") + commander1Id := e.Record.GetString("commandant_1") + commander2Id := e.Record.GetString("commandant_2") + score1 := e.Record.GetInt("score_1") + score2 := e.Record.GetInt("score_2") + + // Base data in case it's the first match + player1_ELO := default_ELO_value + player2_ELO := default_ELO_value + commander1_ELO := default_ELO_value + commander2_ELO := default_ELO_value + + // Update ELO With last match ELO (Tournament or Casual) + updateEloPlayerWithLastMatch(e, player1Id, date, &player1_ELO, official) + updateEloPlayerWithLastMatch(e, player2Id, date, &player2_ELO, official) + + // Update ELO With last match ELO (Tournament or Casual) + updateEloCommanderWithLastMatch(e, commander1Id, date, &commander1_ELO, official) + updateEloCommanderWithLastMatch(e, commander2Id, date, &commander2_ELO, official) + + newData := CalculateELO(player1_ELO, player2_ELO, commander1_ELO, commander2_ELO, score1, score2) + + e.Record.Set("last_elo_player_1", player1_ELO) + e.Record.Set("elo_player_1", newData.Player1_NewELO) + e.Record.Set("last_elo_player_2", player2_ELO) + e.Record.Set("elo_player_2", newData.Player2_NewELO) + e.Record.Set("last_elo_commandant_1", commander1_ELO) + e.Record.Set("elo_commandant_1", newData.Commander1_NewELO) + e.Record.Set("last_elo_commandant_2", commander2_ELO) + e.Record.Set("elo_commandant_2", newData.Commander2_NewELO) +} + func updateEloPlayerWithLastMatch(e *core.RecordEvent, playerId string, date string, elo *float64, official bool) { lastMatch := Elo{} err := e.App.RecordQuery("elo").