Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 07c0c8adc3 | |||
| 6e37a7d209 |
@@ -1378,3 +1378,65 @@
|
|||||||
### Reverts
|
### Reverts
|
||||||
|
|
||||||
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
||||||
|
## (2026-06-30)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* **analytics:** add Spark batch analytics module ([#70](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/70)) ([39f1657](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/39f1657e1db6e84889af338c43be8cb5c03c3ec3))
|
||||||
|
* **bot:** add Lazy SMP parallel search for the NNUE bot ([3437dab](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3437dab49b2cc3f7b7e726febb07ad759e878079))
|
||||||
|
* **bot:** clock-aware time management and stream-driven tournament play ([45b5719](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/45b5719d630c9480398f51510cc598d2d6ce39db))
|
||||||
|
* **bot:** implement bot-vs-bot harness for NNUE evaluation ([b2683a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b2683a7f5ab6f3e41883736ac5eeaaee2e1ea5c1))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* **docker:** add .dockerignore and .gitignore files for build exclusions ([c987d8e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c987d8e258c0e6c4cfbdaa8381c64c410d7a2b83))
|
||||||
|
* **docker:** add Dockerfiles for building Quarkus application in native and JVM modes ([3f2d2bb](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f2d2bb4c97fa8cddba66e1da4427c54236dfeed))
|
||||||
|
* **docker:** add Dockerfiles for Quarkus application in JVM and native modes ([34b9933](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/34b993304670cf2aa62cd2f6460cee7b9864b08e))
|
||||||
|
* **events:** migrate game-creation and bot flows to Redis Streams NCS-89 ([#62](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/62)) ([a24924c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a24924c23057db3d700a75dbc4333557789cd991))
|
||||||
|
* **ncs-110:** feed NNUE root-move scores into search move ordering ([#83](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/83)) ([e4fee85](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/e4fee8513430093d46957970618935e99591519f))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#46](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/46)) ([649566e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/649566eb3fcf38f91c8896a739f74ea318af312d))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#47](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/47)) ([87dfc6c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/87dfc6c2bcce7f7d58fc641bd8d468a2e584c108))
|
||||||
|
* NCS-82 add Swiss-system tournament module ([#55](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/55)) ([c5661de](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c5661de4a0ebf4b33211f5a391840dcf744656b7))
|
||||||
|
* **official-bots:** activate opening book in expert bot (native-safe) ([260db25](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/260db25803ec55ce99e55782791eabdc190dfed4))
|
||||||
|
* **official-bots:** add Google Colab notebook for NNUE training (NCS-111) ([#81](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/81)) ([fa10852](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fa10852bc98451d4068ec6fb9e7a486b5e53ef5c))
|
||||||
|
* **official-bots:** consume GameOver stream for bot cleanup ([#67](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/67)) ([db9d153](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/db9d1533912f4b41c4d1ca80ccffdde5d23d6ff6))
|
||||||
|
* **official-bots:** implement king-relative (HalfKP) encoding in NNUE (NCS-109) ([#80](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/80)) ([44f376f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/44f376f03221f086b898741436e13c93fd314dd1))
|
||||||
|
* **official-bots:** make HybridBot veto actionable and use it for expert ([1df29cf](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1df29cf3a6e21af3f396b2b7a6da67d978f941ae))
|
||||||
|
* **official-bots:** park expert bot on tournament server at startup ([#75](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/75)) ([30295a4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/30295a4bb95855ee8261c92278bb9ebc80ee12ee))
|
||||||
|
* **official-bots:** resolve tournament bot token from Redis and account service ([386ddc5](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/386ddc5c19f8f893b16c6422aa5393b54c872e45))
|
||||||
|
* **official-bots:** standalone self-play + one-shot dataset builder for NNUE training ([1c80abd](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1c80abdb8a45814d642d43c633cde81ce7374c4f))
|
||||||
|
* **tournament:** auto-join external tournaments and publish created ones ([#77](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/77)) ([9978b7e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/9978b7ea78eb658a225a461b9cd339386c0c14f3))
|
||||||
|
* **tournament:** federate tournaments across clusters with DB replication ([5b000a6](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5b000a6e5f04ea6770d1c7ab6bfdaded77a99172))
|
||||||
|
* **tournament:** seed external server registry from env var on startup ([845dc9c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/845dc9c2935c8bc1be42541dfaf31c9a861d3272))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bot:** drop game-stream play, poll with low delay ([6e37a7d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6e37a7d20992b7d27c5ffebb12184916ed9d3120))
|
||||||
|
* **bot:** include quiet promotions in quiescence search ([4938560](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/49385600147021cd29f00a8eecc6be7ba8470717))
|
||||||
|
* **bot:** seed search with game history, add contempt and NNUE mop-up ([faf7eb3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/faf7eb38ea7a0d3bc41ae4c2ef9a5195822f390c))
|
||||||
|
* enable official bots to connect to external tournament server ([#71](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/71)) ([688d30e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/688d30e2b10026923372be5fca3c63eaaee2de2a))
|
||||||
|
* modified training pipeline ([9f9140c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/9f9140cb585345cd244a1dfee1a06e51a5f7f7a8))
|
||||||
|
* **official-bots:** configure JWT verification ([#72](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/72)) ([98c64fc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/98c64fc0d56dc542beb31c75f4b9056d91de03cd))
|
||||||
|
* **official-bots:** correct parkOn path from /api/bots to /api/account/bots ([1be9949](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1be9949c0b5c6a1db535696620d77735050d6c93))
|
||||||
|
* **official-bots:** derive tournament game color from game endpoint ([#79](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/79)) ([bfc4672](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/bfc46723e615bb9b65f7f9bba5f53877c4f079a7))
|
||||||
|
* **official-bots:** discover tournament games by polling, not just the stream ([10113fd](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/10113fd0579b614d15870798d933bc9c495d2049))
|
||||||
|
* **official-bots:** make botToken optional, fall back to env, fix 502 status ([f43d193](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f43d1930d80670d810c57b54eaa3789854fa082c))
|
||||||
|
* **official-bots:** NCS-70-auto-register official bots with account service ([#59](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/59)) ([7117a93](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/7117a93376272094d0b1a6abf2121254ce396684))
|
||||||
|
* **official-bots:** park on external tournament servers using correct endpoint and token ([3188241](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/31882417377468b41bbe3ff94506aa4928024450))
|
||||||
|
* **official-bots:** play games by polling state instead of NDJSON stream ([bfb15c7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/bfb15c7299bd471d5e064a577ed10af98e2ea90a))
|
||||||
|
* **official-bots:** play only own tournament games with correct color ([4651bb7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/4651bb796f07a21bd013d9521b2dfe2e1078cebb))
|
||||||
|
* **official-bots:** prevent Colab OOM in NNUE training ([e2b4342](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/e2b4342f602215b5e8de6fccafc4105525a1ddd1))
|
||||||
|
* **official-bots:** prioritize Redis token over stale env var in joinTournament ([83dd2d4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/83dd2d4335ca48eb3e5aa234a75367574276ba63))
|
||||||
|
* **official-bots:** register with tournament server directly to get correct token ([64b5d55](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/64b5d5567f110c2fe152558c7de275a1e0b30e21))
|
||||||
|
* **official-bots:** resolve per-difficulty bot token on tournament join ([fdf4c94](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fdf4c94811d086996447bb4657fac1d9bd6e5a93))
|
||||||
|
* **official-bots:** resume tournaments already joined after restart ([285b73e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/285b73efbd6dd98cec410ade9eead9881d693a8f))
|
||||||
|
* **official-bots:** stream NNUE features as sparse indices to stop host OOM ([9d65662](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/9d656624d85889f55746faa5704578e248f9b088))
|
||||||
|
* **official-bots:** sync bots before token fetch on first startup after DB wipe ([b0ddb27](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b0ddb274d23bca8b1b3f691ce0d643f33e0b54cd))
|
||||||
|
* **official-bots:** use ThreadLocalRandom in PolyglotBook for native image ([1b30c3b](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1b30c3be393d25712c8743d3d9057207f8bbb67c))
|
||||||
|
|
||||||
|
### Reverts
|
||||||
|
|
||||||
|
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
||||||
|
|||||||
+2
-49
@@ -20,7 +20,6 @@ import scala.jdk.CollectionConverters.*
|
|||||||
import scala.util.{Failure, Success, Try}
|
import scala.util.{Failure, Success, Try}
|
||||||
import java.io.{BufferedReader, InputStream, InputStreamReader}
|
import java.io.{BufferedReader, InputStream, InputStreamReader}
|
||||||
import java.util.concurrent.{ConcurrentHashMap, ExecutorService, Executors}
|
import java.util.concurrent.{ConcurrentHashMap, ExecutorService, Executors}
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
|
||||||
|
|
||||||
@Startup
|
@Startup
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
@@ -44,7 +43,7 @@ class TournamentBotGamePlayer:
|
|||||||
private val hardestDifficulty = "expert"
|
private val hardestDifficulty = "expert"
|
||||||
private val autoJoinIntervalMs = 15000L
|
private val autoJoinIntervalMs = 15000L
|
||||||
// Detect the opponent's move fast: every poll spent waiting runs our clock without us thinking.
|
// Detect the opponent's move fast: every poll spent waiting runs our clock without us thinking.
|
||||||
private val pollIntervalMs = 250L
|
private val pollIntervalMs = 150L
|
||||||
|
|
||||||
private val gameTerminalStatuses =
|
private val gameTerminalStatuses =
|
||||||
Set("checkmate", "stalemate", "draw", "resigned", "timeout", "aborted", "finished")
|
Set("checkmate", "stalemate", "draw", "resigned", "timeout", "aborted", "finished")
|
||||||
@@ -396,58 +395,12 @@ class TournamentBotGamePlayer:
|
|||||||
private def playGame(cfg: TournamentBotConfig, gameId: String, color: String): Unit =
|
private def playGame(cfg: TournamentBotConfig, gameId: String, color: String): Unit =
|
||||||
Try {
|
Try {
|
||||||
log.infof("Playing game %s as %s", gameId, color)
|
log.infof("Playing game %s as %s", gameId, color)
|
||||||
if !streamGameLoop(cfg, gameId, color) then
|
pollGameLoop(cfg, gameId, color)
|
||||||
log.infof("Stream unavailable for game %s — falling back to polling", gameId)
|
|
||||||
pollGameLoop(cfg, gameId, color)
|
|
||||||
activeGames.remove(gameId)
|
activeGames.remove(gameId)
|
||||||
} match
|
} match
|
||||||
case Failure(ex) => log.errorf(ex, "Game %s crashed", gameId); activeGames.remove(gameId)
|
case Failure(ex) => log.errorf(ex, "Game %s crashed", gameId); activeGames.remove(gameId)
|
||||||
case Success(_) => ()
|
case Success(_) => ()
|
||||||
|
|
||||||
// Push-based play: the game stream delivers the opponent's move the instant it lands, so our clock
|
|
||||||
// is not burned waiting between polls. Heartbeats (every 10s) keep the NDJSON connection flushing.
|
|
||||||
// Returns true if the game was driven to completion via the stream; false to fall back to polling.
|
|
||||||
private def streamGameLoop(cfg: TournamentBotConfig, gameId: String, color: String): Boolean =
|
|
||||||
val myColor = resolveColor(cfg, gameId).getOrElse(color)
|
|
||||||
val lastFen = AtomicReference("")
|
|
||||||
Try {
|
|
||||||
val response = authed(cfg, target(cfg).path("game").path(gameId).path("stream"))
|
|
||||||
.header("Accept", "application/x-ndjson")
|
|
||||||
.get()
|
|
||||||
try
|
|
||||||
if response.getStatus != 200 then
|
|
||||||
log.warnf("Game stream %s returned status %d", gameId, response.getStatus)
|
|
||||||
false
|
|
||||||
else
|
|
||||||
log.infof("Streaming game %s as %s", gameId, myColor)
|
|
||||||
forEachLine(response.readEntity(classOf[InputStream])): line =>
|
|
||||||
parse(line).foreach(node => handleStreamEvent(cfg, gameId, myColor, node, lastFen))
|
|
||||||
true
|
|
||||||
finally response.close()
|
|
||||||
} match
|
|
||||||
case Success(completed) => completed
|
|
||||||
case Failure(ex) => log.warnf(ex, "Game stream %s failed", gameId); false
|
|
||||||
|
|
||||||
private def handleStreamEvent(
|
|
||||||
cfg: TournamentBotConfig,
|
|
||||||
gameId: String,
|
|
||||||
myColor: String,
|
|
||||||
node: JsonNode,
|
|
||||||
lastFen: AtomicReference[String],
|
|
||||||
): Unit =
|
|
||||||
val eventType = node.path("type").asText()
|
|
||||||
if eventType == "move" || eventType == "gameState" then
|
|
||||||
val status = node.path("status").asText("ongoing")
|
|
||||||
val turn = node.path("turn").asText()
|
|
||||||
val fen = node.path("fen").asText()
|
|
||||||
if !gameTerminalStatuses.contains(status) && turn == myColor && fen.nonEmpty && fen != lastFen.get then
|
|
||||||
lastFen.set(fen)
|
|
||||||
val time = readTimeControl(node, myColor)
|
|
||||||
log.infof("Our turn (stream) in game %s — computing move (fen=%s, budget=%dms)", gameId, fen, time.budgetMs)
|
|
||||||
computeUci(cfg, fen, time) match
|
|
||||||
case None => log.warnf("No move found for game %s (fen=%s)", gameId, fen)
|
|
||||||
case Some(uci) => submitMove(cfg, gameId, uci)
|
|
||||||
|
|
||||||
// The native JAX-RS client buffers streaming responses, so reading the NDJSON game stream blocks
|
// The native JAX-RS client buffers streaming responses, so reading the NDJSON game stream blocks
|
||||||
// forever. Poll the game state with plain GETs (which work) and move when it is our turn.
|
// forever. Poll the game state with plain GETs (which work) and move when it is our turn.
|
||||||
private def pollGameLoop(cfg: TournamentBotConfig, gameId: String, color: String): Unit =
|
private def pollGameLoop(cfg: TournamentBotConfig, gameId: String, color: String): Unit =
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=43
|
MINOR=44
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
Reference in New Issue
Block a user