commit d46e69ecbdc761b09c613de4c05d51a762746a7b
parent 001cb7bcdf4ca6f74f99fd27a88906e91a8b3f54
Author: n0tr1v <n0tr1v@protonmail.com>
Date: Wed, 14 Jun 2023 02:14:13 -0700
analyse game endpoint
Diffstat:
3 files changed, 62 insertions(+), 14 deletions(-)
diff --git a/pkg/web/handlers/chess.go b/pkg/web/handlers/chess.go
@@ -112,6 +112,31 @@ func ChessHandler(c echo.Context) error {
return c.Render(http.StatusOK, "chess", data)
}
+func ChessGameAnalyseHandler(c echo.Context) error {
+ key := c.Param("key")
+ db := c.Get("database").(*database.DkfDB)
+ authUser := c.Get("authUser").(*database.User)
+ if !authUser.IsAdmin {
+ return c.Redirect(http.StatusFound, "/")
+ }
+ g, err := interceptors.ChessInstance.GetGame(key)
+ if err != nil {
+ return c.Redirect(http.StatusFound, "/")
+ }
+ game := g.Game
+ if game.Outcome() == chess.NoOutcome {
+ return c.String(http.StatusOK, "no outcome")
+ }
+ res, err := interceptors.AnalyseGame(game.String())
+ if err != nil {
+ return c.String(http.StatusOK, err.Error())
+ }
+ g.DbChessGame.AccuracyWhite = res.WhiteAccuracy
+ g.DbChessGame.AccuracyBlack = res.BlackAccuracy
+ g.DbChessGame.DoSave(db)
+ return c.String(http.StatusOK, "done")
+}
+
func ChessGameFormHandler(c echo.Context) error {
key := c.Param("key")
csrf, _ := c.Get("csrf").(string)
diff --git a/pkg/web/handlers/interceptors/chess.go b/pkg/web/handlers/interceptors/chess.go
@@ -387,7 +387,15 @@ func (g *ChessGame) drawPlayerCard(key string, isBlack, isSpectator, isYourTurn,
{{ if .IsSpectator }}
<tr><td style="padding: 10px 0;" colspan="2"><a href="?{{ if not .IsFlipped }}r=1{{ end }}" style="color: #eee;">Flip board</a></td></tr>
{{ end }}
- <tr style="height: 100%;"><td colspan="2"><div style="color: #eee;">Outcome: <span id="outcome"></span></div></td></tr>
+ <tr style="height: 100%;">
+ <td colspan="2">
+ <div style="color: #eee;">Outcome: <span id="outcome"></span></div>
+ {{ if .IsAnalysed }}
+ <div style="color: #eee;">White accuracy: <span id="white-accuracy">{{ .WhiteAccuracy }}</span></div>
+ <div style="color: #eee;">Black accuracy: <span id="black-accuracy">{{ .BlackAccuracy }}</span></div>
+ {{ end }}
+ </td>
+ </tr>
{{ if .GameOver }}<tr><td colspan="2"><div><textarea>{{ .PGN }}</textarea></div></td></tr>{{ end }}
</table>
@@ -420,6 +428,9 @@ func (g *ChessGame) drawPlayerCard(key string, isBlack, isSpectator, isYourTurn,
"WhiteScore": whiteScore,
"BlackAdvantage": blackAdvantage,
"BlackScore": blackScore,
+ "IsAnalysed": g.DbChessGame.AccuracyWhite != 0 && g.DbChessGame.AccuracyBlack != 0,
+ "WhiteAccuracy": g.DbChessGame.AccuracyWhite,
+ "BlackAccuracy": g.DbChessGame.AccuracyBlack,
}
fns := template.FuncMap{
@@ -742,20 +753,25 @@ func CalcAdvantage(position *chess.Position) (string, string, string, string) {
return whiteAdvantage, whiteScoreLbl, blackAdvantage, blackScoreLbl
}
-func Test() {
+type AnalyseResult struct {
+ WhiteAccuracy float64
+ BlackAccuracy float64
+}
+
+func AnalyseGame(pgn string) (out AnalyseResult, err error) {
// https://github.com/lichess-org/lila/blob/9204a337492c1be4b7b8dabd68941d8934439cbc/modules/analyse/src/main/AccuracyPercent.scala#L71
// sbt 'testOnly lila.analyse.AccuracyPercentTest'
// lichess: 86% 97% (game against stockfish)
// Lila: 26.036024039104852 25.007112871751964
// Ours: 28.07242196565701 25.629909658576725
// 35, -29, 37, -42, 31, -15, 28, -16, 16, -4, 30, -24, 13, -14, 0, -17, 9, 6, -17, 8, -3, -5, -1, 5, -13, 20, -21, 90, -59, 77, -55, 70, -84, 116, -97, 68, -50, 46, -54, 93, -53, 57, -62, 61, -18, 11, -17, 41, -15, 13, -19, 8, 0, 22, -76, 44, -46, 87, -62, 62, -56, 59, -28, 69, -50, 70, -63, 63, -27, 30, -53, 14, -65, 43, -17, 398, -430, 565, -597, 793, -802, 837, -821, 908, -915, 957, -984, 1073, -981, 1285
- pgn := "1. d4 Nf6 2. Nf3 e6 3. Bf4 { A46 Indian Defense: London System } c5 4. e3 d5 5. c3 Bd6 6. Bg3 O-O " +
- "7. Bd3 Qc7 8. Bxd6 Qxd6 9. O-O Nbd7 10. Nbd2 e5 11. dxe5 Nxe5 12. Nxe5 Qxe5 13. Nf3 Qe7 14. b3 Rd8 " +
- "15. Rc1 Bg4 16. Be2 Bf5 17. Bd3 Ne4 18. Qc2 Rd6 19. Rfd1 Re8 20. Bb5 Rc8 21. Bd3 Rcd8 22. Nd2 h6 " +
- "23. Nxe4 dxe4 24. Bc4 b6 25. Rxd6 Qxd6 26. h3 a5 27. Qe2 Qd2 28. Qxd2 Rxd2 29. a4 Be6 30. Bxe6 fxe6 " +
- "31. Rb1 Kf7 32. Kf1 Rc2 33. c4 h5 34. g4 hxg4 35. hxg4 Kf6 36. Kg2 Ke5 37. Kg3 Rd2 38. f3 Re2 39. f4+ Kf6 " +
- "40. g5+ Kf5 41. Rh1 Rxe3+ 42. Kh4 Rxb3 43. g6 Kxf4 44. Kh5 Ra3 45. Rf1+ Rf3 46. Rxf3+ exf3 47. Kh4 f2 " +
- "48. Kh3 Kf3 49. Kh2 f1=R 50. Kh3" // Rh1# { Black wins by checkmate. } 0-1"
+ //pgn := "1. d4 Nf6 2. Nf3 e6 3. Bf4 { A46 Indian Defense: London System } c5 4. e3 d5 5. c3 Bd6 6. Bg3 O-O " +
+ // "7. Bd3 Qc7 8. Bxd6 Qxd6 9. O-O Nbd7 10. Nbd2 e5 11. dxe5 Nxe5 12. Nxe5 Qxe5 13. Nf3 Qe7 14. b3 Rd8 " +
+ // "15. Rc1 Bg4 16. Be2 Bf5 17. Bd3 Ne4 18. Qc2 Rd6 19. Rfd1 Re8 20. Bb5 Rc8 21. Bd3 Rcd8 22. Nd2 h6 " +
+ // "23. Nxe4 dxe4 24. Bc4 b6 25. Rxd6 Qxd6 26. h3 a5 27. Qe2 Qd2 28. Qxd2 Rxd2 29. a4 Be6 30. Bxe6 fxe6 " +
+ // "31. Rb1 Kf7 32. Kf1 Rc2 33. c4 h5 34. g4 hxg4 35. hxg4 Kf6 36. Kg2 Ke5 37. Kg3 Rd2 38. f3 Re2 39. f4+ Kf6 " +
+ // "40. g5+ Kf5 41. Rh1 Rxe3+ 42. Kh4 Rxb3 43. g6 Kxf4 44. Kh5 Ra3 45. Rf1+ Rf3 46. Rxf3+ exf3 47. Kh4 f2 " +
+ // "48. Kh3 Kf3 49. Kh2 f1=R 50. Kh3" // Rh1# { Black wins by checkmate. } 0-1"
pgnOpt, _ := chess.PGN(strings.NewReader(pgn))
g := chess.NewGame(pgnOpt)
positions := g.Positions()
@@ -763,11 +779,11 @@ func Test() {
eng, err := uci.New("stockfish")
if err != nil {
logrus.Error(err)
- return
+ return out, err
}
if err := eng.Run(uci.CmdUCI, uci.CmdIsReady, uci.CmdUCINewGame); err != nil {
logrus.Error(err)
- return
+ return out, err
}
defer eng.Close()
@@ -789,15 +805,21 @@ func Test() {
cp *= -1
}
cps = append(cps, cp)
- fmt.Printf("%d: %d/%d %d %d\n", idx/2, idx, len(positions), idx%2, cp)
+ //fmt.Printf("%d: %d/%d %d %d\n", idx/2, idx, len(positions), idx%2, cp)
}
s := make([]string, 0)
for _, c := range cps {
s = append(s, strconv.Itoa(c))
}
- fmt.Println(strings.Join(s, ", "))
- fmt.Println(gameAccuracy(cps))
+
+ //fmt.Println(strings.Join(s, ", "))
+
+ wa, ba := gameAccuracy(cps)
+ return AnalyseResult{
+ WhiteAccuracy: wa,
+ BlackAccuracy: ba,
+ }, nil
}
func standardDeviation(num []WinPercent) float64 {
diff --git a/pkg/web/web.go b/pkg/web/web.go
@@ -100,6 +100,7 @@ func getMainServer(db *database.DkfDB, i18nBundle *i18n.Bundle, renderer *tmp.Te
authGroup.POST("/chess", handlers.ChessHandler)
authGroup.GET("/chess/:key", handlers.ChessGameHandler)
authGroup.POST("/chess/:key", handlers.ChessGameHandler)
+ authGroup.GET("/chess/:key/analyse", handlers.ChessGameAnalyseHandler)
authGroup.GET("/chess/:key/form", handlers.ChessGameFormHandler)
authGroup.POST("/chess/:key/form", handlers.ChessGameFormHandler)
authGroup.GET("/settings/chat", handlers.SettingsChatHandler)