feat(grpc): implement gRPC services for game context management and move handling

This commit is contained in:
2026-04-25 10:21:58 +02:00
parent 9a39cd6916
commit b6be0cd249
28 changed files with 1687 additions and 145 deletions
+275 -54
View File
@@ -2,8 +2,8 @@
> **Stack:** raw-http | none | unknown | scala > **Stack:** raw-http | none | unknown | scala
> 0 routes | 0 models | 0 components | 107 lib files | 1 env vars | 1 middleware > 0 routes | 0 models | 0 components | 159 lib files | 1 env vars | 1 middleware
> **Token savings:** this file is ~7,200 tokens. Without it, AI exploration would cost ~37,300 tokens. **Saves ~30,100 tokens per conversation.** > **Token savings:** this file is ~0 tokens. Without it, AI exploration would cost ~0 tokens. **Saves ~0 tokens per conversation.**
--- ---
@@ -25,11 +25,13 @@
- function main: () -> None - function main: () -> None
- class TestCase - class TestCase
- _...2 more_ - _...2 more_
- `modules/account/src/main/scala/de/nowchess/account/client/CoreGameClient.scala` — class CoreGameClient, function createGame
- `modules/account/src/main/scala/de/nowchess/account/config/JacksonConfig.scala` — class JacksonConfig, function customize - `modules/account/src/main/scala/de/nowchess/account/config/JacksonConfig.scala` — class JacksonConfig, function customize
- `modules/account/src/main/scala/de/nowchess/account/config/NativeReflectionConfig.scala` — class NativeReflectionConfig - `modules/account/src/main/scala/de/nowchess/account/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
- `modules/account/src/main/scala/de/nowchess/account/domain/Account.scala` — class Account - `modules/account/src/main/scala/de/nowchess/account/domain/Account.scala` — class Account
- `modules/account/src/main/scala/de/nowchess/account/domain/Challenge.scala` - `modules/account/src/main/scala/de/nowchess/account/domain/Challenge.scala`
- class Challenge - class Challenge
- function gameIdOpt
- function declineReasonOpt - function declineReasonOpt
- function timeControlLimitOpt - function timeControlLimitOpt
- function timeControlIncrementOpt - function timeControlIncrementOpt
@@ -81,6 +83,48 @@
- function cancel - function cancel
- function listForUser - function listForUser
- _...1 more_ - _...1 more_
- `modules/api/bin/scoverage/de/nowchess/api/board/Board.scala`
- class Board
- function apply
- function pieceAt
- function updated
- function removed
- function withMove
- _...2 more_
- `modules/api/bin/scoverage/de/nowchess/api/board/CastlingRights.scala`
- function hasAnyRights
- function hasRights
- function revokeColor
- function revokeKingSide
- function revokeQueenSide
- class CastlingRights
- `modules/api/bin/scoverage/de/nowchess/api/board/Color.scala` — function opposite, function label
- `modules/api/bin/scoverage/de/nowchess/api/board/Piece.scala` — class Piece
- `modules/api/bin/scoverage/de/nowchess/api/board/PieceType.scala` — function label
- `modules/api/bin/scoverage/de/nowchess/api/board/Square.scala`
- class Square
- function fromAlgebraic
- function offset
- `modules/api/bin/scoverage/de/nowchess/api/bot/Bot.scala`
- class Bot
- function name
- function nextMove
- `modules/api/bin/scoverage/de/nowchess/api/dto/ErrorEventDto.scala` — class ErrorEventDto, function apply
- `modules/api/bin/scoverage/de/nowchess/api/dto/GameFullEventDto.scala` — class GameFullEventDto, function apply
- `modules/api/bin/scoverage/de/nowchess/api/dto/GameStateEventDto.scala` — class GameStateEventDto, function apply
- `modules/api/bin/scoverage/de/nowchess/api/game/GameContext.scala`
- function kingSquare
- function withBoard
- function withTurn
- function withCastlingRights
- function withEnPassantSquare
- function withHalfMoveClock
- _...4 more_
- `modules/api/bin/scoverage/de/nowchess/api/player/PlayerInfo.scala` — class PlayerId, function apply
- `modules/api/bin/scoverage/de/nowchess/api/response/ApiResponse.scala`
- class ApiResponse
- function error
- function totalPages
- `modules/api/src/main/scala/de/nowchess/api/board/Board.scala` - `modules/api/src/main/scala/de/nowchess/api/board/Board.scala`
- class Board - class Board
- function apply - function apply
@@ -142,6 +186,75 @@
- function isCheck - function isCheck
- function isCheckmate - function isCheckmate
- _...5 more_ - _...5 more_
- `modules/bot/bin/scoverage/de/nowchess/bot/BotController.scala`
- class BotController
- function getBot
- function listBots
- `modules/bot/bin/scoverage/de/nowchess/bot/BotMoveRepetition.scala`
- class BotMoveRepetition
- function blockedMoves
- function repeatedMove
- function filterAllowed
- `modules/bot/bin/scoverage/de/nowchess/bot/Config.scala` — class Config
- `modules/bot/bin/scoverage/de/nowchess/bot/ai/Evaluation.scala`
- class Evaluation
- class CHECKMATE_SCORE
- class DRAW_SCORE
- function evaluate
- function initAccumulator
- function copyAccumulator
- _...2 more_
- `modules/bot/bin/scoverage/de/nowchess/bot/bots/classic/EvaluationClassic.scala`
- class EvaluationClassic
- function evaluate
- function countRay
- `modules/bot/bin/scoverage/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala` — class EvaluationNNUE, function evaluate
- `modules/bot/bin/scoverage/de/nowchess/bot/bots/nnue/NNUE.scala`
- class NNUE
- function initAccumulator
- function pushAccumulator
- function copyAccumulator
- function recomputeAccumulator
- function validateAccumulator
- _...4 more_
- `modules/bot/bin/scoverage/de/nowchess/bot/bots/nnue/NbaiLoader.scala`
- class NbaiLoader
- function load
- function loadDefault
- `modules/bot/bin/scoverage/de/nowchess/bot/bots/nnue/NbaiMigrator.scala` — class NbaiMigrator, function migrateFromBin
- `modules/bot/bin/scoverage/de/nowchess/bot/bots/nnue/NbaiModel.scala`
- function toJson
- class NbaiMetadata
- function fromJson
- function str
- function num
- `modules/bot/bin/scoverage/de/nowchess/bot/bots/nnue/NbaiWriter.scala` — class NbaiWriter, function write
- `modules/bot/bin/scoverage/de/nowchess/bot/logic/AlphaBetaSearch.scala`
- function bestMove
- function bestMove
- function bestMoveWithTime
- function bestMoveWithTime
- function loop
- function loop
- `modules/bot/bin/scoverage/de/nowchess/bot/logic/MoveOrdering.scala`
- class MoveOrdering
- class OrderingContext
- function addKillerMove
- function getKillerMoves
- function addHistory
- function getHistory
- _...3 more_
- `modules/bot/bin/scoverage/de/nowchess/bot/logic/TranspositionTable.scala`
- function advance
- function probe
- function store
- function clear
- `modules/bot/bin/scoverage/de/nowchess/bot/util/PolyglotBook.scala` — function probe, function select
- `modules/bot/bin/scoverage/de/nowchess/bot/util/PolyglotHash.scala` — class PolyglotHash, function hash
- `modules/bot/bin/scoverage/de/nowchess/bot/util/ZobristHash.scala`
- class ZobristHash
- function hash
- function nextHash
- `modules/bot/python/nnue.py` - `modules/bot/python/nnue.py`
- function get_weights_dir: () - function get_weights_dir: ()
- function get_data_dir: () - function get_data_dir: ()
@@ -246,6 +359,63 @@
- class ZobristHash - class ZobristHash
- function hash - function hash
- function nextHash - function nextHash
- `modules/core/bin/scoverage/de/nowchess/chess/command/Command.scala`
- class Command
- function execute
- function undo
- function description
- class MoveResult
- `modules/core/bin/scoverage/de/nowchess/chess/command/CommandInvoker.scala`
- class CommandInvoker
- function execute
- function undo
- function redo
- function history
- function getCurrentIndex
- _...3 more_
- `modules/core/bin/scoverage/de/nowchess/chess/config/JacksonConfig.scala` — class JacksonConfig, function customize
- `modules/core/bin/scoverage/de/nowchess/chess/controller/Parser.scala` — class Parser, function parseMove
- `modules/core/bin/scoverage/de/nowchess/chess/engine/GameEngine.scala`
- class GameEngine
- function board
- function turn
- function context
- function pendingDrawOfferBy
- function canUndo
- _...17 more_
- `modules/core/bin/scoverage/de/nowchess/chess/exception/ApiException.scala`
- class ApiException
- class GameNotFoundException
- class BadRequestException
- `modules/core/bin/scoverage/de/nowchess/chess/exception/ApiExceptionMapper.scala` — class ApiExceptionMapper, function toResponse
- `modules/core/bin/scoverage/de/nowchess/chess/observer/Observer.scala`
- function context
- class Observer
- function onGameEvent
- class Observable
- function subscribe
- function unsubscribe
- _...1 more_
- `modules/core/bin/scoverage/de/nowchess/chess/registry/GameRegistry.scala`
- class GameRegistry
- function store
- function get
- function update
- function generateId
- `modules/core/bin/scoverage/de/nowchess/chess/registry/GameRegistryImpl.scala`
- class GameRegistryImpl
- function store
- function get
- function update
- function generateId
- `modules/core/bin/scoverage/de/nowchess/chess/resource/GameResource.scala`
- class GameResource
- function onGameEvent
- function createGame
- function getGame
- function streamGame
- function onGameEvent
- _...10 more_
- `modules/core/src/main/scala/de/nowchess/chess/adapter/RuleSetRestAdapter.scala` - `modules/core/src/main/scala/de/nowchess/chess/adapter/RuleSetRestAdapter.scala`
- class RuleSetRestAdapter - class RuleSetRestAdapter
- function candidateMoves - function candidateMoves
@@ -284,8 +454,6 @@
- _...3 more_ - _...3 more_
- `modules/core/src/main/scala/de/nowchess/chess/config/JacksonConfig.scala` — class JacksonConfig, function customize - `modules/core/src/main/scala/de/nowchess/chess/config/JacksonConfig.scala` — class JacksonConfig, function customize
- `modules/core/src/main/scala/de/nowchess/chess/config/NativeReflectionConfig.scala` — class NativeReflectionConfig - `modules/core/src/main/scala/de/nowchess/chess/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
- `modules/core/src/main/scala/de/nowchess/chess/config/SquareKeyDeserializer.scala` — class SquareKeyDeserializer
- `modules/core/src/main/scala/de/nowchess/chess/config/SquareKeySerializer.scala` — class SquareKeySerializer
- `modules/core/src/main/scala/de/nowchess/chess/controller/Parser.scala` — class Parser, function parseMove - `modules/core/src/main/scala/de/nowchess/chess/controller/Parser.scala` — class Parser, function parseMove
- `modules/core/src/main/scala/de/nowchess/chess/engine/GameEngine.scala` - `modules/core/src/main/scala/de/nowchess/chess/engine/GameEngine.scala`
- class GameEngine - class GameEngine
@@ -300,10 +468,6 @@
- class GameNotFoundException - class GameNotFoundException
- class BadRequestException - class BadRequestException
- `modules/core/src/main/scala/de/nowchess/chess/exception/ApiExceptionMapper.scala` — class ApiExceptionMapper, function toResponse - `modules/core/src/main/scala/de/nowchess/chess/exception/ApiExceptionMapper.scala` — class ApiExceptionMapper, function toResponse
- `modules/core/src/main/scala/de/nowchess/chess/json/MoveTypeDeserializer.scala` — class MoveTypeDeserializer
- `modules/core/src/main/scala/de/nowchess/chess/json/MoveTypeSerializer.scala` — class MoveTypeSerializer
- `modules/core/src/main/scala/de/nowchess/chess/json/SquareDeserializer.scala` — class SquareDeserializer
- `modules/core/src/main/scala/de/nowchess/chess/json/SquareSerializer.scala` — class SquareSerializer
- `modules/core/src/main/scala/de/nowchess/chess/observer/Observer.scala` - `modules/core/src/main/scala/de/nowchess/chess/observer/Observer.scala`
- function context - function context
- class Observer - class Observer
@@ -329,9 +493,56 @@
- function onGameEvent - function onGameEvent
- function createGame - function createGame
- function getGame - function getGame
- function streamGame - function resignGame
- function makeMove
- _...8 more_
- `modules/core/src/main/scala/de/nowchess/chess/resource/GameWebSocketResource.scala`
- class GameWebSocketResource
- function onOpen
- function onGameEvent - function onGameEvent
- _...10 more_ - function onClose
- `modules/io/bin/scoverage/de/nowchess/io/GameContextExport.scala` — class GameContextExport, function exportGameContext
- `modules/io/bin/scoverage/de/nowchess/io/GameContextImport.scala` — class GameContextImport, function importGameContext
- `modules/io/bin/scoverage/de/nowchess/io/GameFileService.scala`
- class GameFileService
- function saveGameToFile
- function loadGameFromFile
- class FileSystemGameService
- function saveGameToFile
- function loadGameFromFile
- `modules/io/bin/scoverage/de/nowchess/io/fen/FenExporter.scala`
- class FenExporter
- function boardToFen
- function gameContextToFen
- function exportGameContext
- `modules/io/bin/scoverage/de/nowchess/io/fen/FenParser.scala`
- class FenParser
- function parseFen
- function importGameContext
- function parseBoard
- `modules/io/bin/scoverage/de/nowchess/io/fen/FenParserCombinators.scala`
- class FenParserCombinators
- function parseFen
- function parseBoard
- function importGameContext
- `modules/io/bin/scoverage/de/nowchess/io/fen/FenParserFastParse.scala`
- class FenParserFastParse
- function parseFen
- function parseBoard
- function importGameContext
- `modules/io/bin/scoverage/de/nowchess/io/fen/FenParserSupport.scala` — function buildSquares
- `modules/io/bin/scoverage/de/nowchess/io/json/JsonExporter.scala` — class JsonExporter, function exportGameContext
- `modules/io/bin/scoverage/de/nowchess/io/json/JsonParser.scala` — class JsonParser, function importGameContext
- `modules/io/bin/scoverage/de/nowchess/io/pgn/PgnExporter.scala`
- class PgnExporter
- function exportGameContext
- function exportGame
- `modules/io/bin/scoverage/de/nowchess/io/pgn/PgnParser.scala`
- class PgnParser
- function validatePgn
- function importGameContext
- function parsePgn
- function parseAlgebraicMove
- `modules/io/src/main/scala/de/nowchess/io/GameFileService.scala` - `modules/io/src/main/scala/de/nowchess/io/GameFileService.scala`
- class GameFileService - class GameFileService
- function saveGameToFile - function saveGameToFile
@@ -362,8 +573,6 @@
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParserSupport.scala` — function buildSquares - `modules/io/src/main/scala/de/nowchess/io/fen/FenParserSupport.scala` — function buildSquares
- `modules/io/src/main/scala/de/nowchess/io/json/JsonExporter.scala` — class JsonExporter, function exportGameContext - `modules/io/src/main/scala/de/nowchess/io/json/JsonExporter.scala` — class JsonExporter, function exportGameContext
- `modules/io/src/main/scala/de/nowchess/io/json/JsonParser.scala` — class JsonParser, function importGameContext - `modules/io/src/main/scala/de/nowchess/io/json/JsonParser.scala` — class JsonParser, function importGameContext
- `modules/io/src/main/scala/de/nowchess/io/json/SquareKeyDeserializer.scala` — class SquareKeyDeserializer
- `modules/io/src/main/scala/de/nowchess/io/json/SquareKeySerializer.scala` — class SquareKeySerializer
- `modules/io/src/main/scala/de/nowchess/io/pgn/PgnExporter.scala` - `modules/io/src/main/scala/de/nowchess/io/pgn/PgnExporter.scala`
- class PgnExporter - class PgnExporter
- function exportGameContext - function exportGameContext
@@ -382,14 +591,31 @@
- function importPgn - function importPgn
- function exportFen - function exportFen
- function exportPgn - function exportPgn
- `modules/json/src/main/scala/de/nowchess/json/ChessJacksonModule.scala` — class ChessJacksonModule
- `modules/json/src/main/scala/de/nowchess/json/GameResultDeserializer.scala` — class GameResultDeserializer
- `modules/json/src/main/scala/de/nowchess/json/GameResultSerializer.scala` — class GameResultSerializer
- `modules/json/src/main/scala/de/nowchess/json/MoveTypeDeserializer.scala` — class MoveTypeDeserializer
- `modules/json/src/main/scala/de/nowchess/json/MoveTypeSerializer.scala` — class MoveTypeSerializer
- `modules/json/src/main/scala/de/nowchess/json/SquareDeserializer.scala` — class SquareDeserializer
- `modules/json/src/main/scala/de/nowchess/json/SquareKeyDeserializer.scala` — class SquareKeyDeserializer
- `modules/json/src/main/scala/de/nowchess/json/SquareKeySerializer.scala` — class SquareKeySerializer
- `modules/json/src/main/scala/de/nowchess/json/SquareSerializer.scala` — class SquareSerializer
- `modules/rule/bin/scoverage/de/nowchess/rules/RuleSet.scala`
- class RuleSet
- function candidateMoves
- function legalMoves
- function allLegalMoves
- function isCheck
- function isCheckmate
- _...5 more_
- `modules/rule/bin/scoverage/de/nowchess/rules/sets/DefaultRules.scala`
- class DefaultRules
- function positionOf
- function loop
- function toMoves
- function loop
- `modules/rule/src/main/scala/de/nowchess/rules/config/JacksonConfig.scala` — class JacksonConfig, function customize - `modules/rule/src/main/scala/de/nowchess/rules/config/JacksonConfig.scala` — class JacksonConfig, function customize
- `modules/rule/src/main/scala/de/nowchess/rules/config/NativeReflectionConfig.scala` — class NativeReflectionConfig - `modules/rule/src/main/scala/de/nowchess/rules/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
- `modules/rule/src/main/scala/de/nowchess/rules/json/MoveTypeDeserializer.scala` — class MoveTypeDeserializer
- `modules/rule/src/main/scala/de/nowchess/rules/json/MoveTypeSerializer.scala` — class MoveTypeSerializer
- `modules/rule/src/main/scala/de/nowchess/rules/json/SquareDeserializer.scala` — class SquareDeserializer
- `modules/rule/src/main/scala/de/nowchess/rules/json/SquareKeyDeserializer.scala` — class SquareKeyDeserializer
- `modules/rule/src/main/scala/de/nowchess/rules/json/SquareKeySerializer.scala` — class SquareKeySerializer
- `modules/rule/src/main/scala/de/nowchess/rules/json/SquareSerializer.scala` — class SquareSerializer
- `modules/rule/src/main/scala/de/nowchess/rules/resource/RuleSetResource.scala` - `modules/rule/src/main/scala/de/nowchess/rules/resource/RuleSetResource.scala`
- class RuleSetResource - class RuleSetResource
- function candidateMoves - function candidateMoves
@@ -398,12 +624,7 @@
- function isCheck - function isCheck
- function isCheckmate - function isCheckmate
- _...5 more_ - _...5 more_
- `modules/rule/src/main/scala/de/nowchess/rules/sets/DefaultRules.scala` - `modules/rule/src/main/scala/de/nowchess/rules/sets/DefaultRules.scala` — class DefaultRules, function positionOf
- class DefaultRules
- function positionOf
- function loop
- function toMoves
- function loop
--- ---
@@ -426,39 +647,39 @@
## Most Imported Files (change these carefully) ## Most Imported Files (change these carefully)
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala` — imported by **74** files - `modules/api/bin/scoverage/de/nowchess/api/game/GameContext.scala` — imported by **138** files
- `modules/api/src/main/scala/de/nowchess/api/board/Square.scala` — imported by **66** files - `modules/api/bin/scoverage/de/nowchess/api/board/Square.scala` — imported by **99** files
- `modules/api/src/main/scala/de/nowchess/api/move/Move.scala` — imported by **52** files - `modules/api/bin/scoverage/de/nowchess/api/move/Move.scala` — imported by **97** files
- `modules/api/src/main/scala/de/nowchess/api/board/Color.scala` — imported by **42** files - `modules/api/bin/scoverage/de/nowchess/api/board/Color.scala` — imported by **81** files
- `modules/rule/src/main/scala/de/nowchess/rules/sets/DefaultRules.scala` — imported by **27** files - `modules/rule/bin/scoverage/de/nowchess/rules/sets/DefaultRules.scala` — imported by **44** files
- `modules/api/src/main/scala/de/nowchess/api/board/Piece.scala` — imported by **21** files - `modules/api/bin/scoverage/de/nowchess/api/board/Board.scala` — imported by **39** files
- `modules/api/src/main/scala/de/nowchess/api/board/Board.scala` — imported by **20** files - `modules/api/bin/scoverage/de/nowchess/api/board/Piece.scala` — imported by **39** files
- `modules/api/src/main/scala/de/nowchess/api/board/PieceType.scala` — imported by **20** files - `modules/api/bin/scoverage/de/nowchess/api/board/PieceType.scala` — imported by **37** files
- `modules/api/src/main/scala/de/nowchess/api/board/CastlingRights.scala` — imported by **13** files - `modules/api/bin/scoverage/de/nowchess/api/game/DrawReason.scala` — imported by **23** files
- `modules/api/src/main/scala/de/nowchess/api/game/DrawReason.scala` — imported by **12** files - `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala` — imported by **23** files
- `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala` — imported by **12** files - `modules/api/bin/scoverage/de/nowchess/api/board/CastlingRights.scala` — imported by **22** files
- `modules/api/src/main/scala/de/nowchess/api/game/GameResult.scala` — imported by **10** files - `modules/api/bin/scoverage/de/nowchess/api/game/GameResult.scala` — imported by **21** files
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParser.scala` — imported by **10** files - `modules/io/bin/scoverage/de/nowchess/io/fen/FenParser.scala` — imported by **20** files
- `modules/api/src/main/scala/de/nowchess/api/error/GameError.scala` — imported by **9** files - `modules/api/src/main/scala/de/nowchess/api/io/GameContextImport.scala` — imported by **15** files
- `modules/api/src/main/scala/de/nowchess/api/io/GameContextImport.scala` — imported by **8** files - `modules/api/bin/scoverage/de/nowchess/api/player/PlayerInfo.scala` — imported by **14** files
- `modules/api/src/main/scala/de/nowchess/api/player/PlayerInfo.scala` — imported by **7** files - `modules/core/bin/scoverage/de/nowchess/chess/observer/Observer.scala` — imported by **13** files
- `modules/core/src/main/scala/de/nowchess/chess/observer/Observer.scala` — imported by **7** files - `modules/api/bin/scoverage/de/nowchess/api/bot/Bot.scala` — imported by **12** files
- `modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala` — imported by **6** files - `modules/bot/bin/scoverage/de/nowchess/bot/ai/Evaluation.scala` — imported by **12** files
- `modules/bot/src/main/scala/de/nowchess/bot/ai/Evaluation.scala` — imported by **6** files - `modules/bot/bin/scoverage/de/nowchess/bot/util/PolyglotBook.scala` — imported by **10** files
- `modules/api/src/main/scala/de/nowchess/api/io/GameContextExport.scala` — imported by **6** files - `modules/api/src/main/scala/de/nowchess/api/io/GameContextExport.scala` — imported by **10** files
## Import Map (who imports what) ## Import Map (who imports what)
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala``modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala`, `modules/api/src/main/scala/de/nowchess/api/io/GameContextExport.scala`, `modules/api/src/main/scala/de/nowchess/api/io/GameContextImport.scala`, `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala`, `modules/bot/src/main/scala/de/nowchess/bot/BotMoveRepetition.scala` +69 more - `modules/api/bin/scoverage/de/nowchess/api/game/GameContext.scala` `modules/api/bin/scoverage/de/nowchess/api/bot/Bot.scala`, `modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala`, `modules/api/src/main/scala/de/nowchess/api/io/GameContextExport.scala`, `modules/api/src/main/scala/de/nowchess/api/io/GameContextImport.scala`, `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala` +133 more
- `modules/api/src/main/scala/de/nowchess/api/board/Square.scala``modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/main/scala/de/nowchess/api/move/Move.scala`, `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/api/src/test/scala/de/nowchess/api/move/MoveTest.scala` +61 more - `modules/api/bin/scoverage/de/nowchess/api/board/Square.scala``modules/api/bin/scoverage/de/nowchess/api/game/GameContext.scala`, `modules/api/bin/scoverage/de/nowchess/api/move/Move.scala`, `modules/api/bin/test/de/nowchess/api/game/GameContextTest.scala`, `modules/api/bin/test/de/nowchess/api/move/MoveTest.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala` +94 more
- `modules/api/src/main/scala/de/nowchess/api/move/Move.scala``modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala`, `modules/api/src/test/scala/de/nowchess/api/board/BoardTest.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala` +47 more - `modules/api/bin/scoverage/de/nowchess/api/move/Move.scala``modules/api/bin/scoverage/de/nowchess/api/bot/Bot.scala`, `modules/api/bin/scoverage/de/nowchess/api/game/GameContext.scala`, `modules/api/bin/test/de/nowchess/api/board/BoardTest.scala`, `modules/api/bin/test/de/nowchess/api/game/GameContextTest.scala`, `modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala` +92 more
- `modules/api/src/main/scala/de/nowchess/api/board/Color.scala``modules/api/src/main/scala/de/nowchess/api/game/ClockState.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameResult.scala`, `modules/api/src/test/scala/de/nowchess/api/game/ClockStateTest.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala` +37 more - `modules/api/bin/scoverage/de/nowchess/api/board/Color.scala``modules/api/bin/scoverage/de/nowchess/api/game/GameContext.scala`, `modules/api/bin/scoverage/de/nowchess/api/game/GameResult.scala`, `modules/api/bin/test/de/nowchess/api/game/GameContextTest.scala`, `modules/api/src/main/scala/de/nowchess/api/game/ClockState.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala` +76 more
- `modules/rule/src/main/scala/de/nowchess/rules/sets/DefaultRules.scala``modules/bot/src/main/scala/de/nowchess/bot/bots/ClassicalBot.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/HybridBot.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/NNUEBot.scala`, `modules/bot/src/main/scala/de/nowchess/bot/logic/AlphaBetaSearch.scala`, `modules/bot/src/test/scala/de/nowchess/bot/AlphaBetaSearchTest.scala` +22 more - `modules/rule/bin/scoverage/de/nowchess/rules/sets/DefaultRules.scala``modules/bot/bin/scoverage/de/nowchess/bot/bots/ClassicalBot.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/bots/HybridBot.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/bots/NNUEBot.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/logic/AlphaBetaSearch.scala`, `modules/bot/bin/test/de/nowchess/bot/AlphaBetaSearchTest.scala` +39 more
- `modules/api/src/main/scala/de/nowchess/api/board/Piece.scala``modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NNUE.scala`, `modules/bot/src/main/scala/de/nowchess/bot/logic/MoveOrdering.scala`, `modules/bot/src/main/scala/de/nowchess/bot/util/PolyglotHash.scala`, `modules/bot/src/main/scala/de/nowchess/bot/util/ZobristHash.scala`, `modules/bot/src/test/scala/de/nowchess/bot/AlphaBetaSearchTest.scala` +16 more - `modules/api/bin/scoverage/de/nowchess/api/board/Board.scala``modules/api/bin/scoverage/de/nowchess/api/game/GameContext.scala`, `modules/api/bin/test/de/nowchess/api/game/GameContextTest.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/bots/nnue/NNUE.scala` +34 more
- `modules/api/src/main/scala/de/nowchess/api/board/Board.scala``modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NNUE.scala`, `modules/bot/src/main/scala/de/nowchess/bot/logic/MoveOrdering.scala`, `modules/bot/src/test/scala/de/nowchess/bot/AlphaBetaSearchTest.scala` +15 more - `modules/api/bin/scoverage/de/nowchess/api/board/Piece.scala``modules/bot/bin/scoverage/de/nowchess/bot/bots/nnue/NNUE.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/logic/MoveOrdering.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/util/PolyglotHash.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/util/ZobristHash.scala`, `modules/bot/bin/test/de/nowchess/bot/AlphaBetaSearchTest.scala` +34 more
- `modules/api/src/main/scala/de/nowchess/api/board/PieceType.scala``modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/classic/EvaluationClassic.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NNUE.scala`, `modules/bot/src/main/scala/de/nowchess/bot/logic/AlphaBetaSearch.scala`, `modules/bot/src/main/scala/de/nowchess/bot/logic/MoveOrdering.scala` +15 more - `modules/api/bin/scoverage/de/nowchess/api/board/PieceType.scala``modules/api/bin/scoverage/de/nowchess/api/game/GameContext.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/bots/classic/EvaluationClassic.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/bots/nnue/NNUE.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/logic/AlphaBetaSearch.scala` +32 more
- `modules/api/src/main/scala/de/nowchess/api/board/CastlingRights.scala``modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/bot/src/test/scala/de/nowchess/bot/ZobristHashTest.scala`, `modules/core/src/main/scala/de/nowchess/chess/config/NativeReflectionConfig.scala`, `modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineWithBotTest.scala` +8 more - `modules/api/bin/scoverage/de/nowchess/api/game/DrawReason.scala``modules/api/bin/test/de/nowchess/api/game/GameContextTest.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/core/bin/scoverage/de/nowchess/chess/engine/GameEngine.scala`, `modules/core/bin/scoverage/de/nowchess/chess/observer/Observer.scala`, `modules/core/bin/scoverage/de/nowchess/chess/resource/GameResource.scala` +18 more
- `modules/api/src/main/scala/de/nowchess/api/game/DrawReason.scala``modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/core/src/main/scala/de/nowchess/chess/config/NativeReflectionConfig.scala`, `modules/core/src/main/scala/de/nowchess/chess/engine/GameEngine.scala`, `modules/core/src/main/scala/de/nowchess/chess/observer/Observer.scala`, `modules/core/src/main/scala/de/nowchess/chess/resource/GameResource.scala` +7 more - `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala``modules/bot/bin/scoverage/de/nowchess/bot/bots/ClassicalBot.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/bots/HybridBot.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/bots/NNUEBot.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/logic/AlphaBetaSearch.scala`, `modules/bot/bin/test/de/nowchess/bot/AlphaBetaSearchTest.scala` +18 more
--- ---
+30 -30
View File
@@ -2,36 +2,36 @@
## Most Imported Files (change these carefully) ## Most Imported Files (change these carefully)
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala` — imported by **74** files - `modules/api/bin/scoverage/de/nowchess/api/game/GameContext.scala` — imported by **138** files
- `modules/api/src/main/scala/de/nowchess/api/board/Square.scala` — imported by **66** files - `modules/api/bin/scoverage/de/nowchess/api/board/Square.scala` — imported by **99** files
- `modules/api/src/main/scala/de/nowchess/api/move/Move.scala` — imported by **52** files - `modules/api/bin/scoverage/de/nowchess/api/move/Move.scala` — imported by **97** files
- `modules/api/src/main/scala/de/nowchess/api/board/Color.scala` — imported by **42** files - `modules/api/bin/scoverage/de/nowchess/api/board/Color.scala` — imported by **81** files
- `modules/rule/src/main/scala/de/nowchess/rules/sets/DefaultRules.scala` — imported by **27** files - `modules/rule/bin/scoverage/de/nowchess/rules/sets/DefaultRules.scala` — imported by **44** files
- `modules/api/src/main/scala/de/nowchess/api/board/Piece.scala` — imported by **21** files - `modules/api/bin/scoverage/de/nowchess/api/board/Board.scala` — imported by **39** files
- `modules/api/src/main/scala/de/nowchess/api/board/Board.scala` — imported by **20** files - `modules/api/bin/scoverage/de/nowchess/api/board/Piece.scala` — imported by **39** files
- `modules/api/src/main/scala/de/nowchess/api/board/PieceType.scala` — imported by **20** files - `modules/api/bin/scoverage/de/nowchess/api/board/PieceType.scala` — imported by **37** files
- `modules/api/src/main/scala/de/nowchess/api/board/CastlingRights.scala` — imported by **13** files - `modules/api/bin/scoverage/de/nowchess/api/game/DrawReason.scala` — imported by **23** files
- `modules/api/src/main/scala/de/nowchess/api/game/DrawReason.scala` — imported by **12** files - `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala` — imported by **23** files
- `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala` — imported by **12** files - `modules/api/bin/scoverage/de/nowchess/api/board/CastlingRights.scala` — imported by **22** files
- `modules/api/src/main/scala/de/nowchess/api/game/GameResult.scala` — imported by **10** files - `modules/api/bin/scoverage/de/nowchess/api/game/GameResult.scala` — imported by **21** files
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParser.scala` — imported by **10** files - `modules/io/bin/scoverage/de/nowchess/io/fen/FenParser.scala` — imported by **20** files
- `modules/api/src/main/scala/de/nowchess/api/error/GameError.scala` — imported by **9** files - `modules/api/src/main/scala/de/nowchess/api/io/GameContextImport.scala` — imported by **15** files
- `modules/api/src/main/scala/de/nowchess/api/io/GameContextImport.scala` — imported by **8** files - `modules/api/bin/scoverage/de/nowchess/api/player/PlayerInfo.scala` — imported by **14** files
- `modules/api/src/main/scala/de/nowchess/api/player/PlayerInfo.scala` — imported by **7** files - `modules/core/bin/scoverage/de/nowchess/chess/observer/Observer.scala` — imported by **13** files
- `modules/core/src/main/scala/de/nowchess/chess/observer/Observer.scala` — imported by **7** files - `modules/api/bin/scoverage/de/nowchess/api/bot/Bot.scala` — imported by **12** files
- `modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala` — imported by **6** files - `modules/bot/bin/scoverage/de/nowchess/bot/ai/Evaluation.scala` — imported by **12** files
- `modules/bot/src/main/scala/de/nowchess/bot/ai/Evaluation.scala` — imported by **6** files - `modules/bot/bin/scoverage/de/nowchess/bot/util/PolyglotBook.scala` — imported by **10** files
- `modules/api/src/main/scala/de/nowchess/api/io/GameContextExport.scala` — imported by **6** files - `modules/api/src/main/scala/de/nowchess/api/io/GameContextExport.scala` — imported by **10** files
## Import Map (who imports what) ## Import Map (who imports what)
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala``modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala`, `modules/api/src/main/scala/de/nowchess/api/io/GameContextExport.scala`, `modules/api/src/main/scala/de/nowchess/api/io/GameContextImport.scala`, `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala`, `modules/bot/src/main/scala/de/nowchess/bot/BotMoveRepetition.scala` +69 more - `modules/api/bin/scoverage/de/nowchess/api/game/GameContext.scala` `modules/api/bin/scoverage/de/nowchess/api/bot/Bot.scala`, `modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala`, `modules/api/src/main/scala/de/nowchess/api/io/GameContextExport.scala`, `modules/api/src/main/scala/de/nowchess/api/io/GameContextImport.scala`, `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala` +133 more
- `modules/api/src/main/scala/de/nowchess/api/board/Square.scala``modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/main/scala/de/nowchess/api/move/Move.scala`, `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/api/src/test/scala/de/nowchess/api/move/MoveTest.scala` +61 more - `modules/api/bin/scoverage/de/nowchess/api/board/Square.scala``modules/api/bin/scoverage/de/nowchess/api/game/GameContext.scala`, `modules/api/bin/scoverage/de/nowchess/api/move/Move.scala`, `modules/api/bin/test/de/nowchess/api/game/GameContextTest.scala`, `modules/api/bin/test/de/nowchess/api/move/MoveTest.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala` +94 more
- `modules/api/src/main/scala/de/nowchess/api/move/Move.scala``modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala`, `modules/api/src/test/scala/de/nowchess/api/board/BoardTest.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala` +47 more - `modules/api/bin/scoverage/de/nowchess/api/move/Move.scala``modules/api/bin/scoverage/de/nowchess/api/bot/Bot.scala`, `modules/api/bin/scoverage/de/nowchess/api/game/GameContext.scala`, `modules/api/bin/test/de/nowchess/api/board/BoardTest.scala`, `modules/api/bin/test/de/nowchess/api/game/GameContextTest.scala`, `modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala` +92 more
- `modules/api/src/main/scala/de/nowchess/api/board/Color.scala``modules/api/src/main/scala/de/nowchess/api/game/ClockState.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameResult.scala`, `modules/api/src/test/scala/de/nowchess/api/game/ClockStateTest.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala` +37 more - `modules/api/bin/scoverage/de/nowchess/api/board/Color.scala``modules/api/bin/scoverage/de/nowchess/api/game/GameContext.scala`, `modules/api/bin/scoverage/de/nowchess/api/game/GameResult.scala`, `modules/api/bin/test/de/nowchess/api/game/GameContextTest.scala`, `modules/api/src/main/scala/de/nowchess/api/game/ClockState.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala` +76 more
- `modules/rule/src/main/scala/de/nowchess/rules/sets/DefaultRules.scala``modules/bot/src/main/scala/de/nowchess/bot/bots/ClassicalBot.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/HybridBot.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/NNUEBot.scala`, `modules/bot/src/main/scala/de/nowchess/bot/logic/AlphaBetaSearch.scala`, `modules/bot/src/test/scala/de/nowchess/bot/AlphaBetaSearchTest.scala` +22 more - `modules/rule/bin/scoverage/de/nowchess/rules/sets/DefaultRules.scala``modules/bot/bin/scoverage/de/nowchess/bot/bots/ClassicalBot.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/bots/HybridBot.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/bots/NNUEBot.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/logic/AlphaBetaSearch.scala`, `modules/bot/bin/test/de/nowchess/bot/AlphaBetaSearchTest.scala` +39 more
- `modules/api/src/main/scala/de/nowchess/api/board/Piece.scala``modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NNUE.scala`, `modules/bot/src/main/scala/de/nowchess/bot/logic/MoveOrdering.scala`, `modules/bot/src/main/scala/de/nowchess/bot/util/PolyglotHash.scala`, `modules/bot/src/main/scala/de/nowchess/bot/util/ZobristHash.scala`, `modules/bot/src/test/scala/de/nowchess/bot/AlphaBetaSearchTest.scala` +16 more - `modules/api/bin/scoverage/de/nowchess/api/board/Board.scala``modules/api/bin/scoverage/de/nowchess/api/game/GameContext.scala`, `modules/api/bin/test/de/nowchess/api/game/GameContextTest.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/bots/nnue/NNUE.scala` +34 more
- `modules/api/src/main/scala/de/nowchess/api/board/Board.scala``modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NNUE.scala`, `modules/bot/src/main/scala/de/nowchess/bot/logic/MoveOrdering.scala`, `modules/bot/src/test/scala/de/nowchess/bot/AlphaBetaSearchTest.scala` +15 more - `modules/api/bin/scoverage/de/nowchess/api/board/Piece.scala``modules/bot/bin/scoverage/de/nowchess/bot/bots/nnue/NNUE.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/logic/MoveOrdering.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/util/PolyglotHash.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/util/ZobristHash.scala`, `modules/bot/bin/test/de/nowchess/bot/AlphaBetaSearchTest.scala` +34 more
- `modules/api/src/main/scala/de/nowchess/api/board/PieceType.scala``modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/classic/EvaluationClassic.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NNUE.scala`, `modules/bot/src/main/scala/de/nowchess/bot/logic/AlphaBetaSearch.scala`, `modules/bot/src/main/scala/de/nowchess/bot/logic/MoveOrdering.scala` +15 more - `modules/api/bin/scoverage/de/nowchess/api/board/PieceType.scala``modules/api/bin/scoverage/de/nowchess/api/game/GameContext.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/bots/classic/EvaluationClassic.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/bots/nnue/NNUE.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/logic/AlphaBetaSearch.scala` +32 more
- `modules/api/src/main/scala/de/nowchess/api/board/CastlingRights.scala``modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/bot/src/test/scala/de/nowchess/bot/ZobristHashTest.scala`, `modules/core/src/main/scala/de/nowchess/chess/config/NativeReflectionConfig.scala`, `modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineWithBotTest.scala` +8 more - `modules/api/bin/scoverage/de/nowchess/api/game/DrawReason.scala``modules/api/bin/test/de/nowchess/api/game/GameContextTest.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/core/bin/scoverage/de/nowchess/chess/engine/GameEngine.scala`, `modules/core/bin/scoverage/de/nowchess/chess/observer/Observer.scala`, `modules/core/bin/scoverage/de/nowchess/chess/resource/GameResource.scala` +18 more
- `modules/api/src/main/scala/de/nowchess/api/game/DrawReason.scala``modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/core/src/main/scala/de/nowchess/chess/config/NativeReflectionConfig.scala`, `modules/core/src/main/scala/de/nowchess/chess/engine/GameEngine.scala`, `modules/core/src/main/scala/de/nowchess/chess/observer/Observer.scala`, `modules/core/src/main/scala/de/nowchess/chess/resource/GameResource.scala` +7 more - `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala``modules/bot/bin/scoverage/de/nowchess/bot/bots/ClassicalBot.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/bots/HybridBot.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/bots/NNUEBot.scala`, `modules/bot/bin/scoverage/de/nowchess/bot/logic/AlphaBetaSearch.scala`, `modules/bot/bin/test/de/nowchess/bot/AlphaBetaSearchTest.scala` +18 more
+243 -22
View File
@@ -16,11 +16,13 @@
- function main: () -> None - function main: () -> None
- class TestCase - class TestCase
- _...2 more_ - _...2 more_
- `modules/account/src/main/scala/de/nowchess/account/client/CoreGameClient.scala` — class CoreGameClient, function createGame
- `modules/account/src/main/scala/de/nowchess/account/config/JacksonConfig.scala` — class JacksonConfig, function customize - `modules/account/src/main/scala/de/nowchess/account/config/JacksonConfig.scala` — class JacksonConfig, function customize
- `modules/account/src/main/scala/de/nowchess/account/config/NativeReflectionConfig.scala` — class NativeReflectionConfig - `modules/account/src/main/scala/de/nowchess/account/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
- `modules/account/src/main/scala/de/nowchess/account/domain/Account.scala` — class Account - `modules/account/src/main/scala/de/nowchess/account/domain/Account.scala` — class Account
- `modules/account/src/main/scala/de/nowchess/account/domain/Challenge.scala` - `modules/account/src/main/scala/de/nowchess/account/domain/Challenge.scala`
- class Challenge - class Challenge
- function gameIdOpt
- function declineReasonOpt - function declineReasonOpt
- function timeControlLimitOpt - function timeControlLimitOpt
- function timeControlIncrementOpt - function timeControlIncrementOpt
@@ -72,6 +74,48 @@
- function cancel - function cancel
- function listForUser - function listForUser
- _...1 more_ - _...1 more_
- `modules/api/bin/scoverage/de/nowchess/api/board/Board.scala`
- class Board
- function apply
- function pieceAt
- function updated
- function removed
- function withMove
- _...2 more_
- `modules/api/bin/scoverage/de/nowchess/api/board/CastlingRights.scala`
- function hasAnyRights
- function hasRights
- function revokeColor
- function revokeKingSide
- function revokeQueenSide
- class CastlingRights
- `modules/api/bin/scoverage/de/nowchess/api/board/Color.scala` — function opposite, function label
- `modules/api/bin/scoverage/de/nowchess/api/board/Piece.scala` — class Piece
- `modules/api/bin/scoverage/de/nowchess/api/board/PieceType.scala` — function label
- `modules/api/bin/scoverage/de/nowchess/api/board/Square.scala`
- class Square
- function fromAlgebraic
- function offset
- `modules/api/bin/scoverage/de/nowchess/api/bot/Bot.scala`
- class Bot
- function name
- function nextMove
- `modules/api/bin/scoverage/de/nowchess/api/dto/ErrorEventDto.scala` — class ErrorEventDto, function apply
- `modules/api/bin/scoverage/de/nowchess/api/dto/GameFullEventDto.scala` — class GameFullEventDto, function apply
- `modules/api/bin/scoverage/de/nowchess/api/dto/GameStateEventDto.scala` — class GameStateEventDto, function apply
- `modules/api/bin/scoverage/de/nowchess/api/game/GameContext.scala`
- function kingSquare
- function withBoard
- function withTurn
- function withCastlingRights
- function withEnPassantSquare
- function withHalfMoveClock
- _...4 more_
- `modules/api/bin/scoverage/de/nowchess/api/player/PlayerInfo.scala` — class PlayerId, function apply
- `modules/api/bin/scoverage/de/nowchess/api/response/ApiResponse.scala`
- class ApiResponse
- function error
- function totalPages
- `modules/api/src/main/scala/de/nowchess/api/board/Board.scala` - `modules/api/src/main/scala/de/nowchess/api/board/Board.scala`
- class Board - class Board
- function apply - function apply
@@ -133,6 +177,75 @@
- function isCheck - function isCheck
- function isCheckmate - function isCheckmate
- _...5 more_ - _...5 more_
- `modules/bot/bin/scoverage/de/nowchess/bot/BotController.scala`
- class BotController
- function getBot
- function listBots
- `modules/bot/bin/scoverage/de/nowchess/bot/BotMoveRepetition.scala`
- class BotMoveRepetition
- function blockedMoves
- function repeatedMove
- function filterAllowed
- `modules/bot/bin/scoverage/de/nowchess/bot/Config.scala` — class Config
- `modules/bot/bin/scoverage/de/nowchess/bot/ai/Evaluation.scala`
- class Evaluation
- class CHECKMATE_SCORE
- class DRAW_SCORE
- function evaluate
- function initAccumulator
- function copyAccumulator
- _...2 more_
- `modules/bot/bin/scoverage/de/nowchess/bot/bots/classic/EvaluationClassic.scala`
- class EvaluationClassic
- function evaluate
- function countRay
- `modules/bot/bin/scoverage/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala` — class EvaluationNNUE, function evaluate
- `modules/bot/bin/scoverage/de/nowchess/bot/bots/nnue/NNUE.scala`
- class NNUE
- function initAccumulator
- function pushAccumulator
- function copyAccumulator
- function recomputeAccumulator
- function validateAccumulator
- _...4 more_
- `modules/bot/bin/scoverage/de/nowchess/bot/bots/nnue/NbaiLoader.scala`
- class NbaiLoader
- function load
- function loadDefault
- `modules/bot/bin/scoverage/de/nowchess/bot/bots/nnue/NbaiMigrator.scala` — class NbaiMigrator, function migrateFromBin
- `modules/bot/bin/scoverage/de/nowchess/bot/bots/nnue/NbaiModel.scala`
- function toJson
- class NbaiMetadata
- function fromJson
- function str
- function num
- `modules/bot/bin/scoverage/de/nowchess/bot/bots/nnue/NbaiWriter.scala` — class NbaiWriter, function write
- `modules/bot/bin/scoverage/de/nowchess/bot/logic/AlphaBetaSearch.scala`
- function bestMove
- function bestMove
- function bestMoveWithTime
- function bestMoveWithTime
- function loop
- function loop
- `modules/bot/bin/scoverage/de/nowchess/bot/logic/MoveOrdering.scala`
- class MoveOrdering
- class OrderingContext
- function addKillerMove
- function getKillerMoves
- function addHistory
- function getHistory
- _...3 more_
- `modules/bot/bin/scoverage/de/nowchess/bot/logic/TranspositionTable.scala`
- function advance
- function probe
- function store
- function clear
- `modules/bot/bin/scoverage/de/nowchess/bot/util/PolyglotBook.scala` — function probe, function select
- `modules/bot/bin/scoverage/de/nowchess/bot/util/PolyglotHash.scala` — class PolyglotHash, function hash
- `modules/bot/bin/scoverage/de/nowchess/bot/util/ZobristHash.scala`
- class ZobristHash
- function hash
- function nextHash
- `modules/bot/python/nnue.py` - `modules/bot/python/nnue.py`
- function get_weights_dir: () - function get_weights_dir: ()
- function get_data_dir: () - function get_data_dir: ()
@@ -237,6 +350,63 @@
- class ZobristHash - class ZobristHash
- function hash - function hash
- function nextHash - function nextHash
- `modules/core/bin/scoverage/de/nowchess/chess/command/Command.scala`
- class Command
- function execute
- function undo
- function description
- class MoveResult
- `modules/core/bin/scoverage/de/nowchess/chess/command/CommandInvoker.scala`
- class CommandInvoker
- function execute
- function undo
- function redo
- function history
- function getCurrentIndex
- _...3 more_
- `modules/core/bin/scoverage/de/nowchess/chess/config/JacksonConfig.scala` — class JacksonConfig, function customize
- `modules/core/bin/scoverage/de/nowchess/chess/controller/Parser.scala` — class Parser, function parseMove
- `modules/core/bin/scoverage/de/nowchess/chess/engine/GameEngine.scala`
- class GameEngine
- function board
- function turn
- function context
- function pendingDrawOfferBy
- function canUndo
- _...17 more_
- `modules/core/bin/scoverage/de/nowchess/chess/exception/ApiException.scala`
- class ApiException
- class GameNotFoundException
- class BadRequestException
- `modules/core/bin/scoverage/de/nowchess/chess/exception/ApiExceptionMapper.scala` — class ApiExceptionMapper, function toResponse
- `modules/core/bin/scoverage/de/nowchess/chess/observer/Observer.scala`
- function context
- class Observer
- function onGameEvent
- class Observable
- function subscribe
- function unsubscribe
- _...1 more_
- `modules/core/bin/scoverage/de/nowchess/chess/registry/GameRegistry.scala`
- class GameRegistry
- function store
- function get
- function update
- function generateId
- `modules/core/bin/scoverage/de/nowchess/chess/registry/GameRegistryImpl.scala`
- class GameRegistryImpl
- function store
- function get
- function update
- function generateId
- `modules/core/bin/scoverage/de/nowchess/chess/resource/GameResource.scala`
- class GameResource
- function onGameEvent
- function createGame
- function getGame
- function streamGame
- function onGameEvent
- _...10 more_
- `modules/core/src/main/scala/de/nowchess/chess/adapter/RuleSetRestAdapter.scala` - `modules/core/src/main/scala/de/nowchess/chess/adapter/RuleSetRestAdapter.scala`
- class RuleSetRestAdapter - class RuleSetRestAdapter
- function candidateMoves - function candidateMoves
@@ -275,8 +445,6 @@
- _...3 more_ - _...3 more_
- `modules/core/src/main/scala/de/nowchess/chess/config/JacksonConfig.scala` — class JacksonConfig, function customize - `modules/core/src/main/scala/de/nowchess/chess/config/JacksonConfig.scala` — class JacksonConfig, function customize
- `modules/core/src/main/scala/de/nowchess/chess/config/NativeReflectionConfig.scala` — class NativeReflectionConfig - `modules/core/src/main/scala/de/nowchess/chess/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
- `modules/core/src/main/scala/de/nowchess/chess/config/SquareKeyDeserializer.scala` — class SquareKeyDeserializer
- `modules/core/src/main/scala/de/nowchess/chess/config/SquareKeySerializer.scala` — class SquareKeySerializer
- `modules/core/src/main/scala/de/nowchess/chess/controller/Parser.scala` — class Parser, function parseMove - `modules/core/src/main/scala/de/nowchess/chess/controller/Parser.scala` — class Parser, function parseMove
- `modules/core/src/main/scala/de/nowchess/chess/engine/GameEngine.scala` - `modules/core/src/main/scala/de/nowchess/chess/engine/GameEngine.scala`
- class GameEngine - class GameEngine
@@ -291,10 +459,6 @@
- class GameNotFoundException - class GameNotFoundException
- class BadRequestException - class BadRequestException
- `modules/core/src/main/scala/de/nowchess/chess/exception/ApiExceptionMapper.scala` — class ApiExceptionMapper, function toResponse - `modules/core/src/main/scala/de/nowchess/chess/exception/ApiExceptionMapper.scala` — class ApiExceptionMapper, function toResponse
- `modules/core/src/main/scala/de/nowchess/chess/json/MoveTypeDeserializer.scala` — class MoveTypeDeserializer
- `modules/core/src/main/scala/de/nowchess/chess/json/MoveTypeSerializer.scala` — class MoveTypeSerializer
- `modules/core/src/main/scala/de/nowchess/chess/json/SquareDeserializer.scala` — class SquareDeserializer
- `modules/core/src/main/scala/de/nowchess/chess/json/SquareSerializer.scala` — class SquareSerializer
- `modules/core/src/main/scala/de/nowchess/chess/observer/Observer.scala` - `modules/core/src/main/scala/de/nowchess/chess/observer/Observer.scala`
- function context - function context
- class Observer - class Observer
@@ -320,9 +484,56 @@
- function onGameEvent - function onGameEvent
- function createGame - function createGame
- function getGame - function getGame
- function streamGame - function resignGame
- function makeMove
- _...8 more_
- `modules/core/src/main/scala/de/nowchess/chess/resource/GameWebSocketResource.scala`
- class GameWebSocketResource
- function onOpen
- function onGameEvent - function onGameEvent
- _...10 more_ - function onClose
- `modules/io/bin/scoverage/de/nowchess/io/GameContextExport.scala` — class GameContextExport, function exportGameContext
- `modules/io/bin/scoverage/de/nowchess/io/GameContextImport.scala` — class GameContextImport, function importGameContext
- `modules/io/bin/scoverage/de/nowchess/io/GameFileService.scala`
- class GameFileService
- function saveGameToFile
- function loadGameFromFile
- class FileSystemGameService
- function saveGameToFile
- function loadGameFromFile
- `modules/io/bin/scoverage/de/nowchess/io/fen/FenExporter.scala`
- class FenExporter
- function boardToFen
- function gameContextToFen
- function exportGameContext
- `modules/io/bin/scoverage/de/nowchess/io/fen/FenParser.scala`
- class FenParser
- function parseFen
- function importGameContext
- function parseBoard
- `modules/io/bin/scoverage/de/nowchess/io/fen/FenParserCombinators.scala`
- class FenParserCombinators
- function parseFen
- function parseBoard
- function importGameContext
- `modules/io/bin/scoverage/de/nowchess/io/fen/FenParserFastParse.scala`
- class FenParserFastParse
- function parseFen
- function parseBoard
- function importGameContext
- `modules/io/bin/scoverage/de/nowchess/io/fen/FenParserSupport.scala` — function buildSquares
- `modules/io/bin/scoverage/de/nowchess/io/json/JsonExporter.scala` — class JsonExporter, function exportGameContext
- `modules/io/bin/scoverage/de/nowchess/io/json/JsonParser.scala` — class JsonParser, function importGameContext
- `modules/io/bin/scoverage/de/nowchess/io/pgn/PgnExporter.scala`
- class PgnExporter
- function exportGameContext
- function exportGame
- `modules/io/bin/scoverage/de/nowchess/io/pgn/PgnParser.scala`
- class PgnParser
- function validatePgn
- function importGameContext
- function parsePgn
- function parseAlgebraicMove
- `modules/io/src/main/scala/de/nowchess/io/GameFileService.scala` - `modules/io/src/main/scala/de/nowchess/io/GameFileService.scala`
- class GameFileService - class GameFileService
- function saveGameToFile - function saveGameToFile
@@ -353,8 +564,6 @@
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParserSupport.scala` — function buildSquares - `modules/io/src/main/scala/de/nowchess/io/fen/FenParserSupport.scala` — function buildSquares
- `modules/io/src/main/scala/de/nowchess/io/json/JsonExporter.scala` — class JsonExporter, function exportGameContext - `modules/io/src/main/scala/de/nowchess/io/json/JsonExporter.scala` — class JsonExporter, function exportGameContext
- `modules/io/src/main/scala/de/nowchess/io/json/JsonParser.scala` — class JsonParser, function importGameContext - `modules/io/src/main/scala/de/nowchess/io/json/JsonParser.scala` — class JsonParser, function importGameContext
- `modules/io/src/main/scala/de/nowchess/io/json/SquareKeyDeserializer.scala` — class SquareKeyDeserializer
- `modules/io/src/main/scala/de/nowchess/io/json/SquareKeySerializer.scala` — class SquareKeySerializer
- `modules/io/src/main/scala/de/nowchess/io/pgn/PgnExporter.scala` - `modules/io/src/main/scala/de/nowchess/io/pgn/PgnExporter.scala`
- class PgnExporter - class PgnExporter
- function exportGameContext - function exportGameContext
@@ -373,14 +582,31 @@
- function importPgn - function importPgn
- function exportFen - function exportFen
- function exportPgn - function exportPgn
- `modules/json/src/main/scala/de/nowchess/json/ChessJacksonModule.scala` — class ChessJacksonModule
- `modules/json/src/main/scala/de/nowchess/json/GameResultDeserializer.scala` — class GameResultDeserializer
- `modules/json/src/main/scala/de/nowchess/json/GameResultSerializer.scala` — class GameResultSerializer
- `modules/json/src/main/scala/de/nowchess/json/MoveTypeDeserializer.scala` — class MoveTypeDeserializer
- `modules/json/src/main/scala/de/nowchess/json/MoveTypeSerializer.scala` — class MoveTypeSerializer
- `modules/json/src/main/scala/de/nowchess/json/SquareDeserializer.scala` — class SquareDeserializer
- `modules/json/src/main/scala/de/nowchess/json/SquareKeyDeserializer.scala` — class SquareKeyDeserializer
- `modules/json/src/main/scala/de/nowchess/json/SquareKeySerializer.scala` — class SquareKeySerializer
- `modules/json/src/main/scala/de/nowchess/json/SquareSerializer.scala` — class SquareSerializer
- `modules/rule/bin/scoverage/de/nowchess/rules/RuleSet.scala`
- class RuleSet
- function candidateMoves
- function legalMoves
- function allLegalMoves
- function isCheck
- function isCheckmate
- _...5 more_
- `modules/rule/bin/scoverage/de/nowchess/rules/sets/DefaultRules.scala`
- class DefaultRules
- function positionOf
- function loop
- function toMoves
- function loop
- `modules/rule/src/main/scala/de/nowchess/rules/config/JacksonConfig.scala` — class JacksonConfig, function customize - `modules/rule/src/main/scala/de/nowchess/rules/config/JacksonConfig.scala` — class JacksonConfig, function customize
- `modules/rule/src/main/scala/de/nowchess/rules/config/NativeReflectionConfig.scala` — class NativeReflectionConfig - `modules/rule/src/main/scala/de/nowchess/rules/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
- `modules/rule/src/main/scala/de/nowchess/rules/json/MoveTypeDeserializer.scala` — class MoveTypeDeserializer
- `modules/rule/src/main/scala/de/nowchess/rules/json/MoveTypeSerializer.scala` — class MoveTypeSerializer
- `modules/rule/src/main/scala/de/nowchess/rules/json/SquareDeserializer.scala` — class SquareDeserializer
- `modules/rule/src/main/scala/de/nowchess/rules/json/SquareKeyDeserializer.scala` — class SquareKeyDeserializer
- `modules/rule/src/main/scala/de/nowchess/rules/json/SquareKeySerializer.scala` — class SquareKeySerializer
- `modules/rule/src/main/scala/de/nowchess/rules/json/SquareSerializer.scala` — class SquareSerializer
- `modules/rule/src/main/scala/de/nowchess/rules/resource/RuleSetResource.scala` - `modules/rule/src/main/scala/de/nowchess/rules/resource/RuleSetResource.scala`
- class RuleSetResource - class RuleSetResource
- function candidateMoves - function candidateMoves
@@ -389,9 +615,4 @@
- function isCheck - function isCheck
- function isCheckmate - function isCheckmate
- _...5 more_ - _...5 more_
- `modules/rule/src/main/scala/de/nowchess/rules/sets/DefaultRules.scala` - `modules/rule/src/main/scala/de/nowchess/rules/sets/DefaultRules.scala` — class DefaultRules, function positionOf
- class DefaultRules
- function positionOf
- function loop
- function toMoves
- function loop
+1 -1
View File
@@ -15,5 +15,5 @@ params:query {
} }
vars:pre-request { vars:pre-request {
gameId: tjOgyEcS gameId: COy3oigz
} }
@@ -22,7 +22,7 @@ quarkus:
schema-management: schema-management:
strategy: drop-and-create strategy: drop-and-create
"%live": "%deployed":
quarkus: quarkus:
rest-client: rest-client:
core-service: core-service:
+3
View File
@@ -49,6 +49,8 @@ dependencies {
implementation(project(":modules:api")) implementation(project(":modules:api"))
implementation(project(":modules:json")) implementation(project(":modules:json"))
implementation(project(":modules:rule"))
implementation(project(":modules:io"))
implementation(project(":modules:bot")) implementation(project(":modules:bot"))
@@ -57,6 +59,7 @@ dependencies {
implementation("io.quarkus:quarkus-hibernate-orm") implementation("io.quarkus:quarkus-hibernate-orm")
implementation("io.quarkus:quarkus-rest-client-jackson") implementation("io.quarkus:quarkus-rest-client-jackson")
implementation("io.quarkus:quarkus-rest-client") implementation("io.quarkus:quarkus-rest-client")
implementation("io.quarkus:quarkus-grpc")
implementation("io.quarkus:quarkus-rest-jackson") implementation("io.quarkus:quarkus-rest-jackson")
implementation("io.quarkus:quarkus-config-yaml") implementation("io.quarkus:quarkus-config-yaml")
implementation("io.quarkus:quarkus-smallrye-fault-tolerance") implementation("io.quarkus:quarkus-smallrye-fault-tolerance")
@@ -0,0 +1,87 @@
syntax = "proto3";
option java_package = "de.nowchess.core.proto";
option java_multiple_files = true;
option java_outer_classname = "ChessTypesProto";
enum ProtoColor {
WHITE = 0;
BLACK = 1;
}
enum ProtoPieceType {
PAWN = 0;
KNIGHT = 1;
BISHOP = 2;
ROOK = 3;
QUEEN = 4;
KING = 5;
}
enum ProtoMoveKind {
QUIET = 0;
CAPTURE = 1;
CASTLE_KINGSIDE = 2;
CASTLE_QUEENSIDE = 3;
EN_PASSANT = 4;
PROMO_QUEEN = 5;
PROMO_ROOK = 6;
PROMO_BISHOP = 7;
PROMO_KNIGHT = 8;
}
enum ProtoGameResultKind {
ONGOING = 0;
WIN_CHECKMATE_W = 1;
WIN_CHECKMATE_B = 2;
WIN_RESIGN_W = 3;
WIN_RESIGN_B = 4;
WIN_TIME_W = 5;
WIN_TIME_B = 6;
DRAW_STALEMATE = 7;
DRAW_INSUFFICIENT = 8;
DRAW_FIFTY_MOVE = 9;
DRAW_THREEFOLD = 10;
DRAW_AGREEMENT = 11;
}
message ProtoPiece {
ProtoColor color = 1;
ProtoPieceType piece_type = 2;
}
message ProtoSquarePiece {
string square = 1;
ProtoPiece piece = 2;
}
message ProtoMove {
string from = 1;
string to = 2;
ProtoMoveKind move_kind = 3;
}
message ProtoCastlingRights {
bool white_king_side = 1;
bool white_queen_side = 2;
bool black_king_side = 3;
bool black_queen_side = 4;
}
message ProtoGameContext {
repeated ProtoSquarePiece board = 1;
ProtoColor turn = 2;
ProtoCastlingRights castling_rights = 3;
string en_passant_square = 4;
int32 half_move_clock = 5;
repeated ProtoMove moves = 6;
ProtoGameResultKind result = 7;
repeated ProtoSquarePiece initial_board = 8;
}
message ProtoPostMoveStatus {
bool is_checkmate = 1;
bool is_stalemate = 2;
bool is_insufficient_material = 3;
bool is_check = 4;
bool is_threefold_repetition = 5;
}
@@ -0,0 +1,31 @@
syntax = "proto3";
option java_package = "de.nowchess.core.proto";
option java_multiple_files = true;
option java_outer_classname = "IoServiceProto";
import "chess_types.proto";
message ProtoImportFenRequest {
string fen = 1;
}
message ProtoImportPgnRequest {
string pgn = 1;
}
message ProtoCombinedExport {
string fen = 1;
string pgn = 2;
}
message ProtoStringResult {
string value = 1;
}
service IoService {
rpc ImportFen (ProtoImportFenRequest) returns (ProtoGameContext);
rpc ImportPgn (ProtoImportPgnRequest) returns (ProtoGameContext);
rpc ExportCombined (ProtoGameContext) returns (ProtoCombinedExport);
rpc ExportFen (ProtoGameContext) returns (ProtoStringResult);
rpc ExportPgn (ProtoGameContext) returns (ProtoStringResult);
}
@@ -0,0 +1,38 @@
syntax = "proto3";
option java_package = "de.nowchess.core.proto";
option java_multiple_files = true;
option java_outer_classname = "RuleServiceProto";
import "chess_types.proto";
message ProtoSquareRequest {
ProtoGameContext context = 1;
string square = 2;
}
message ProtoMoveRequest {
ProtoGameContext context = 1;
ProtoMove move = 2;
}
message ProtoMoveList {
repeated ProtoMove moves = 1;
}
message ProtoBoolResult {
bool value = 1;
}
service RuleService {
rpc CandidateMoves (ProtoSquareRequest) returns (ProtoMoveList);
rpc LegalMoves (ProtoSquareRequest) returns (ProtoMoveList);
rpc AllLegalMoves (ProtoGameContext) returns (ProtoMoveList);
rpc IsCheck (ProtoGameContext) returns (ProtoBoolResult);
rpc IsCheckmate (ProtoGameContext) returns (ProtoBoolResult);
rpc IsStalemate (ProtoGameContext) returns (ProtoBoolResult);
rpc IsInsufficientMaterial (ProtoGameContext) returns (ProtoBoolResult);
rpc IsFiftyMoveRule (ProtoGameContext) returns (ProtoBoolResult);
rpc IsThreefoldRepetition (ProtoGameContext) returns (ProtoBoolResult);
rpc ApplyMove (ProtoMoveRequest) returns (ProtoGameContext);
rpc PostMoveStatus (ProtoGameContext) returns (ProtoPostMoveStatus);
}
@@ -3,6 +3,16 @@ quarkus:
port: 8080 port: 8080
application: application:
name: nowchess-core name: nowchess-core
grpc:
clients:
rule-grpc:
host: localhost
port: 8082
io-grpc:
host: localhost
port: 8081
server:
use-separate-server: false
"%dev": "%dev":
mp: mp:
@@ -18,13 +28,21 @@ quarkus:
origins: http://localhost:4200 origins: http://localhost:4200
methods: GET,POST,PUT,DELETE,OPTIONS methods: GET,POST,PUT,DELETE,OPTIONS
headers: Content-Type,Accept,Authorization headers: Content-Type,Accept,Authorization
grpc:
clients:
rule-grpc:
host: localhost
port: 8082
io-grpc:
host: localhost
port: 8081
rest-client: rest-client:
io-service: io-service:
url: http://localhost:8081 url: http://localhost:8081
rule-service: rule-service:
url: http://localhost:8082 url: http://localhost:8082
"%prod": "%deployed":
mp: mp:
jwt: jwt:
verify: verify:
@@ -38,6 +56,14 @@ quarkus:
origins: ${CORS_ORIGINS} origins: ${CORS_ORIGINS}
methods: GET,POST,PUT,DELETE,OPTIONS methods: GET,POST,PUT,DELETE,OPTIONS
headers: Content-Type,Accept,Authorization headers: Content-Type,Accept,Authorization
grpc:
clients:
rule-grpc:
host: ${RULE_SERVICE_HOST}
port: ${RULE_SERVICE_GRPC_PORT:9082}
io-grpc:
host: ${IO_SERVICE_HOST}
port: ${IO_SERVICE_GRPC_PORT:9081}
rest-client: rest-client:
io-service: io-service:
url: ${IO_SERVICE_URL} url: ${IO_SERVICE_URL}
@@ -0,0 +1,142 @@
package de.nowchess.chess.grpc
import de.nowchess.api.board.*
import de.nowchess.api.board.{CastlingRights as DomainCastlingRights}
import de.nowchess.api.game.{DrawReason, GameContext, GameResult, WinReason}
import de.nowchess.api.move.{Move as DomainMove, MoveType, PromotionPiece}
import de.nowchess.core.proto.*
import scala.jdk.CollectionConverters.*
object CoreProtoMapper:
def toProtoColor(c: Color): ProtoColor = c match
case Color.White => ProtoColor.WHITE
case Color.Black => ProtoColor.BLACK
def fromProtoColor(c: ProtoColor): Color = c match
case ProtoColor.WHITE => Color.White
case _ => Color.Black
def toProtoPieceType(pt: PieceType): ProtoPieceType = pt match
case PieceType.Pawn => ProtoPieceType.PAWN
case PieceType.Knight => ProtoPieceType.KNIGHT
case PieceType.Bishop => ProtoPieceType.BISHOP
case PieceType.Rook => ProtoPieceType.ROOK
case PieceType.Queen => ProtoPieceType.QUEEN
case PieceType.King => ProtoPieceType.KING
def fromProtoPieceType(pt: ProtoPieceType): PieceType = pt match
case ProtoPieceType.PAWN => PieceType.Pawn
case ProtoPieceType.KNIGHT => PieceType.Knight
case ProtoPieceType.BISHOP => PieceType.Bishop
case ProtoPieceType.ROOK => PieceType.Rook
case ProtoPieceType.QUEEN => PieceType.Queen
case _ => PieceType.King
def toProtoMoveKind(mt: MoveType): ProtoMoveKind = mt match
case MoveType.Normal(false) => ProtoMoveKind.QUIET
case MoveType.Normal(true) => ProtoMoveKind.CAPTURE
case MoveType.CastleKingside => ProtoMoveKind.CASTLE_KINGSIDE
case MoveType.CastleQueenside => ProtoMoveKind.CASTLE_QUEENSIDE
case MoveType.EnPassant => ProtoMoveKind.EN_PASSANT
case MoveType.Promotion(PromotionPiece.Queen) => ProtoMoveKind.PROMO_QUEEN
case MoveType.Promotion(PromotionPiece.Rook) => ProtoMoveKind.PROMO_ROOK
case MoveType.Promotion(PromotionPiece.Bishop) => ProtoMoveKind.PROMO_BISHOP
case MoveType.Promotion(PromotionPiece.Knight) => ProtoMoveKind.PROMO_KNIGHT
def fromProtoMoveKind(k: ProtoMoveKind): MoveType = k match
case ProtoMoveKind.QUIET => MoveType.Normal(false)
case ProtoMoveKind.CAPTURE => MoveType.Normal(true)
case ProtoMoveKind.CASTLE_KINGSIDE => MoveType.CastleKingside
case ProtoMoveKind.CASTLE_QUEENSIDE => MoveType.CastleQueenside
case ProtoMoveKind.EN_PASSANT => MoveType.EnPassant
case ProtoMoveKind.PROMO_QUEEN => MoveType.Promotion(PromotionPiece.Queen)
case ProtoMoveKind.PROMO_ROOK => MoveType.Promotion(PromotionPiece.Rook)
case ProtoMoveKind.PROMO_BISHOP => MoveType.Promotion(PromotionPiece.Bishop)
case ProtoMoveKind.PROMO_KNIGHT => MoveType.Promotion(PromotionPiece.Knight)
case _ => MoveType.Normal(false)
def toProtoMove(m: DomainMove): ProtoMove =
ProtoMove.newBuilder().setFrom(m.from.toString).setTo(m.to.toString).setMoveKind(toProtoMoveKind(m.moveType)).build()
def fromProtoMove(m: ProtoMove): Option[DomainMove] =
for
from <- Square.fromAlgebraic(m.getFrom)
to <- Square.fromAlgebraic(m.getTo)
yield DomainMove(from, to, fromProtoMoveKind(m.getMoveKind))
def toProtoBoard(board: Board): java.util.List[ProtoSquarePiece] =
board.pieces.map { (sq, piece) =>
ProtoSquarePiece
.newBuilder()
.setSquare(sq.toString)
.setPiece(ProtoPiece.newBuilder().setColor(toProtoColor(piece.color)).setPieceType(toProtoPieceType(piece.pieceType)).build())
.build()
}.toSeq.asJava
def fromProtoBoard(pieces: java.util.List[ProtoSquarePiece]): Board =
Board(pieces.asScala.flatMap(sp => Square.fromAlgebraic(sp.getSquare).map(_ -> Piece(fromProtoColor(sp.getPiece.getColor), fromProtoPieceType(sp.getPiece.getPieceType)))).toMap)
def toProtoResultKind(r: Option[GameResult]): ProtoGameResultKind = r match
case None => ProtoGameResultKind.ONGOING
case Some(GameResult.Win(Color.White, WinReason.Checkmate)) => ProtoGameResultKind.WIN_CHECKMATE_W
case Some(GameResult.Win(Color.Black, WinReason.Checkmate)) => ProtoGameResultKind.WIN_CHECKMATE_B
case Some(GameResult.Win(Color.White, WinReason.Resignation)) => ProtoGameResultKind.WIN_RESIGN_W
case Some(GameResult.Win(Color.Black, WinReason.Resignation)) => ProtoGameResultKind.WIN_RESIGN_B
case Some(GameResult.Win(Color.White, WinReason.TimeControl)) => ProtoGameResultKind.WIN_TIME_W
case Some(GameResult.Win(Color.Black, WinReason.TimeControl)) => ProtoGameResultKind.WIN_TIME_B
case Some(GameResult.Draw(DrawReason.Stalemate)) => ProtoGameResultKind.DRAW_STALEMATE
case Some(GameResult.Draw(DrawReason.InsufficientMaterial)) => ProtoGameResultKind.DRAW_INSUFFICIENT
case Some(GameResult.Draw(DrawReason.FiftyMoveRule)) => ProtoGameResultKind.DRAW_FIFTY_MOVE
case Some(GameResult.Draw(DrawReason.ThreefoldRepetition)) => ProtoGameResultKind.DRAW_THREEFOLD
case Some(GameResult.Draw(DrawReason.Agreement)) => ProtoGameResultKind.DRAW_AGREEMENT
def fromProtoResultKind(k: ProtoGameResultKind): Option[GameResult] = k match
case ProtoGameResultKind.ONGOING => None
case ProtoGameResultKind.WIN_CHECKMATE_W => Some(GameResult.Win(Color.White, WinReason.Checkmate))
case ProtoGameResultKind.WIN_CHECKMATE_B => Some(GameResult.Win(Color.Black, WinReason.Checkmate))
case ProtoGameResultKind.WIN_RESIGN_W => Some(GameResult.Win(Color.White, WinReason.Resignation))
case ProtoGameResultKind.WIN_RESIGN_B => Some(GameResult.Win(Color.Black, WinReason.Resignation))
case ProtoGameResultKind.WIN_TIME_W => Some(GameResult.Win(Color.White, WinReason.TimeControl))
case ProtoGameResultKind.WIN_TIME_B => Some(GameResult.Win(Color.Black, WinReason.TimeControl))
case ProtoGameResultKind.DRAW_STALEMATE => Some(GameResult.Draw(DrawReason.Stalemate))
case ProtoGameResultKind.DRAW_INSUFFICIENT => Some(GameResult.Draw(DrawReason.InsufficientMaterial))
case ProtoGameResultKind.DRAW_FIFTY_MOVE => Some(GameResult.Draw(DrawReason.FiftyMoveRule))
case ProtoGameResultKind.DRAW_THREEFOLD => Some(GameResult.Draw(DrawReason.ThreefoldRepetition))
case ProtoGameResultKind.DRAW_AGREEMENT => Some(GameResult.Draw(DrawReason.Agreement))
case _ => None
def toProtoGameContext(ctx: GameContext): ProtoGameContext =
ProtoGameContext
.newBuilder()
.addAllBoard(toProtoBoard(ctx.board))
.setTurn(toProtoColor(ctx.turn))
.setCastlingRights(
ProtoCastlingRights
.newBuilder()
.setWhiteKingSide(ctx.castlingRights.whiteKingSide)
.setWhiteQueenSide(ctx.castlingRights.whiteQueenSide)
.setBlackKingSide(ctx.castlingRights.blackKingSide)
.setBlackQueenSide(ctx.castlingRights.blackQueenSide)
.build(),
)
.setEnPassantSquare(ctx.enPassantSquare.map(_.toString).getOrElse(""))
.setHalfMoveClock(ctx.halfMoveClock)
.addAllMoves(ctx.moves.map(toProtoMove).asJava)
.setResult(toProtoResultKind(ctx.result))
.addAllInitialBoard(toProtoBoard(ctx.initialBoard))
.build()
def fromProtoGameContext(p: ProtoGameContext): GameContext =
val cr = p.getCastlingRights
GameContext(
board = fromProtoBoard(p.getBoardList),
turn = fromProtoColor(p.getTurn),
castlingRights = DomainCastlingRights(cr.getWhiteKingSide, cr.getWhiteQueenSide, cr.getBlackKingSide, cr.getBlackQueenSide),
enPassantSquare = Option(p.getEnPassantSquare).filter(_.nonEmpty).flatMap(Square.fromAlgebraic),
halfMoveClock = p.getHalfMoveClock,
moves = p.getMovesList.asScala.flatMap(fromProtoMove).toList,
result = fromProtoResultKind(p.getResult),
initialBoard = fromProtoBoard(p.getInitialBoardList),
)
@@ -0,0 +1,33 @@
package de.nowchess.chess.grpc
import de.nowchess.api.game.GameContext
import de.nowchess.chess.client.CombinedExportResponse
import de.nowchess.core.proto.*
import io.quarkus.grpc.GrpcClient
import jakarta.enterprise.context.ApplicationScoped
import scala.compiletime.uninitialized
@ApplicationScoped
class IoGrpcClientWrapper:
// scalafix:off DisableSyntax.var
@GrpcClient("io-grpc")
var stub: IoServiceGrpc.IoServiceBlockingStub = uninitialized
// scalafix:on DisableSyntax.var
def exportCombined(ctx: GameContext): CombinedExportResponse =
val combined = stub.exportCombined(CoreProtoMapper.toProtoGameContext(ctx))
CombinedExportResponse(combined.getFen, combined.getPgn)
def importFen(fen: String): GameContext =
CoreProtoMapper.fromProtoGameContext(stub.importFen(ProtoImportFenRequest.newBuilder().setFen(fen).build()))
def importPgn(pgn: String): GameContext =
CoreProtoMapper.fromProtoGameContext(stub.importPgn(ProtoImportPgnRequest.newBuilder().setPgn(pgn).build()))
def exportFen(ctx: GameContext): String =
stub.exportFen(CoreProtoMapper.toProtoGameContext(ctx)).getValue
def exportPgn(ctx: GameContext): String =
stub.exportPgn(CoreProtoMapper.toProtoGameContext(ctx)).getValue
@@ -0,0 +1,57 @@
package de.nowchess.chess.grpc
import de.nowchess.api.board.Square
import de.nowchess.api.game.GameContext
import de.nowchess.api.move.Move
import de.nowchess.api.rules.{PostMoveStatus, RuleSet}
import de.nowchess.core.proto.*
import io.quarkus.grpc.GrpcClient
import jakarta.enterprise.context.ApplicationScoped
import scala.compiletime.uninitialized
import scala.jdk.CollectionConverters.*
@ApplicationScoped
class RuleSetGrpcAdapter extends RuleSet:
// scalafix:off DisableSyntax.var
@GrpcClient("rule-grpc")
var stub: RuleServiceGrpc.RuleServiceBlockingStub = uninitialized
// scalafix:on DisableSyntax.var
def candidateMoves(ctx: GameContext)(sq: Square): List[Move] =
val req = ProtoSquareRequest.newBuilder().setContext(CoreProtoMapper.toProtoGameContext(ctx)).setSquare(sq.toString).build()
stub.candidateMoves(req).getMovesList.asScala.flatMap(CoreProtoMapper.fromProtoMove).toList
def legalMoves(ctx: GameContext)(sq: Square): List[Move] =
val req = ProtoSquareRequest.newBuilder().setContext(CoreProtoMapper.toProtoGameContext(ctx)).setSquare(sq.toString).build()
stub.legalMoves(req).getMovesList.asScala.flatMap(CoreProtoMapper.fromProtoMove).toList
def allLegalMoves(ctx: GameContext): List[Move] =
stub.allLegalMoves(CoreProtoMapper.toProtoGameContext(ctx)).getMovesList.asScala.flatMap(CoreProtoMapper.fromProtoMove).toList
def isCheck(ctx: GameContext): Boolean =
stub.isCheck(CoreProtoMapper.toProtoGameContext(ctx)).getValue
def isCheckmate(ctx: GameContext): Boolean =
stub.isCheckmate(CoreProtoMapper.toProtoGameContext(ctx)).getValue
def isStalemate(ctx: GameContext): Boolean =
stub.isStalemate(CoreProtoMapper.toProtoGameContext(ctx)).getValue
def isInsufficientMaterial(ctx: GameContext): Boolean =
stub.isInsufficientMaterial(CoreProtoMapper.toProtoGameContext(ctx)).getValue
def isFiftyMoveRule(ctx: GameContext): Boolean =
stub.isFiftyMoveRule(CoreProtoMapper.toProtoGameContext(ctx)).getValue
def isThreefoldRepetition(ctx: GameContext): Boolean =
stub.isThreefoldRepetition(CoreProtoMapper.toProtoGameContext(ctx)).getValue
def applyMove(ctx: GameContext)(move: Move): GameContext =
val req = ProtoMoveRequest.newBuilder().setContext(CoreProtoMapper.toProtoGameContext(ctx)).setMove(CoreProtoMapper.toProtoMove(move)).build()
CoreProtoMapper.fromProtoGameContext(stub.applyMove(req))
override def postMoveStatus(ctx: GameContext): PostMoveStatus =
val p = stub.postMoveStatus(CoreProtoMapper.toProtoGameContext(ctx))
PostMoveStatus(p.getIsCheckmate, p.getIsStalemate, p.getIsInsufficientMaterial, p.getIsCheck, p.getIsThreefoldRepetition)
@@ -16,11 +16,11 @@ import de.nowchess.api.game.{
import de.nowchess.api.move.{Move, MoveType, PromotionPiece} import de.nowchess.api.move.{Move, MoveType, PromotionPiece}
import de.nowchess.api.player.{PlayerId, PlayerInfo} import de.nowchess.api.player.{PlayerId, PlayerInfo}
import java.time.Instant import java.time.Instant
import de.nowchess.chess.adapter.RuleSetRestAdapter import de.nowchess.api.rules.RuleSet
import de.nowchess.chess.client.IoServiceClient
import de.nowchess.chess.controller.Parser import de.nowchess.chess.controller.Parser
import de.nowchess.chess.engine.GameEngine import de.nowchess.chess.engine.GameEngine
import de.nowchess.chess.exception.{BadRequestException, GameNotFoundException} import de.nowchess.chess.exception.{BadRequestException, GameNotFoundException}
import de.nowchess.chess.grpc.{IoGrpcClientWrapper, RuleSetGrpcAdapter}
import de.nowchess.chess.observer.* import de.nowchess.chess.observer.*
import de.nowchess.chess.registry.{GameEntry, GameRegistry} import de.nowchess.chess.registry.{GameEntry, GameRegistry}
import jakarta.enterprise.context.ApplicationScoped import jakarta.enterprise.context.ApplicationScoped
@@ -28,7 +28,6 @@ import jakarta.inject.Inject
import jakarta.ws.rs.* import jakarta.ws.rs.*
import jakarta.ws.rs.core.{MediaType, Response} import jakarta.ws.rs.core.{MediaType, Response}
import org.eclipse.microprofile.jwt.JsonWebToken import org.eclipse.microprofile.jwt.JsonWebToken
import org.eclipse.microprofile.rest.client.inject.RestClient
import java.util.concurrent.atomic.AtomicReference import java.util.concurrent.atomic.AtomicReference
import scala.compiletime.uninitialized import scala.compiletime.uninitialized
@@ -45,11 +44,10 @@ class GameResource:
var objectMapper: ObjectMapper = uninitialized var objectMapper: ObjectMapper = uninitialized
@Inject @Inject
@RestClient var ioClient: IoGrpcClientWrapper = uninitialized
var ioClient: IoServiceClient = uninitialized
@Inject @Inject
var ruleSetAdapter: RuleSetRestAdapter = uninitialized var ruleSetAdapter: RuleSetGrpcAdapter = uninitialized
@Inject @Inject
var jwt: JsonWebToken = uninitialized var jwt: JsonWebToken = uninitialized
@@ -306,7 +304,7 @@ class GameResource:
@Consumes(Array(MediaType.APPLICATION_JSON)) @Consumes(Array(MediaType.APPLICATION_JSON))
@Produces(Array(MediaType.APPLICATION_JSON)) @Produces(Array(MediaType.APPLICATION_JSON))
def importFen(body: ImportFenRequestDto): Response = def importFen(body: ImportFenRequestDto): Response =
val ctx = ioClient.importFen(ImportFenRequest(body.fen)) val ctx = ioClient.importFen(body.fen)
val white = playerInfoFrom(body.white, DefaultWhite) val white = playerInfoFrom(body.white, DefaultWhite)
val black = playerInfoFrom(body.black, DefaultBlack) val black = playerInfoFrom(body.black, DefaultBlack)
val tc = toTimeControl(body.timeControl) val tc = toTimeControl(body.timeControl)
@@ -319,7 +317,7 @@ class GameResource:
@Consumes(Array(MediaType.APPLICATION_JSON)) @Consumes(Array(MediaType.APPLICATION_JSON))
@Produces(Array(MediaType.APPLICATION_JSON)) @Produces(Array(MediaType.APPLICATION_JSON))
def importPgn(body: ImportPgnRequestDto): Response = def importPgn(body: ImportPgnRequestDto): Response =
val ctx = ioClient.importPgn(ImportPgnRequest(body.pgn)) val ctx = ioClient.importPgn(body.pgn)
val entry = newEntry(ctx, DefaultWhite, DefaultBlack) val entry = newEntry(ctx, DefaultWhite, DefaultBlack)
registry.store(entry) registry.store(entry)
created(toGameFullDto(entry)) created(toGameFullDto(entry))
@@ -0,0 +1,9 @@
quarkus:
grpc:
clients:
rule-grpc:
host: localhost
port: 9082
io-grpc:
host: localhost
port: 9081
@@ -3,16 +3,15 @@ package de.nowchess.chess.resource
import de.nowchess.api.board.Square import de.nowchess.api.board.Square
import de.nowchess.api.dto.* import de.nowchess.api.dto.*
import de.nowchess.api.game.GameContext import de.nowchess.api.game.GameContext
import de.nowchess.api.rules.PostMoveStatus import de.nowchess.chess.client.CombinedExportResponse
import de.nowchess.chess.client.{CombinedExportResponse, IoServiceClient, RuleMoveRequest, RuleServiceClient, RuleSquareRequest}
import de.nowchess.chess.exception.BadRequestException import de.nowchess.chess.exception.BadRequestException
import de.nowchess.chess.grpc.{IoGrpcClientWrapper, RuleSetGrpcAdapter}
import de.nowchess.io.fen.FenExporter import de.nowchess.io.fen.FenExporter
import de.nowchess.io.pgn.PgnParser import de.nowchess.io.pgn.PgnParser
import de.nowchess.rules.sets.DefaultRules import de.nowchess.rules.sets.DefaultRules
import io.quarkus.test.InjectMock import io.quarkus.test.InjectMock
import io.quarkus.test.junit.QuarkusTest import io.quarkus.test.junit.QuarkusTest
import jakarta.inject.Inject import jakarta.inject.Inject
import org.eclipse.microprofile.rest.client.inject.RestClient
import org.junit.jupiter.api.{BeforeEach, DisplayName, Test} import org.junit.jupiter.api.{BeforeEach, DisplayName, Test}
import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.Assertions.*
import org.mockito.ArgumentMatchers.any import org.mockito.ArgumentMatchers.any
@@ -30,54 +29,59 @@ class GameResourceIntegrationTest:
var resource: GameResource = uninitialized var resource: GameResource = uninitialized
@InjectMock @InjectMock
@RestClient var ruleAdapter: RuleSetGrpcAdapter = uninitialized
var ioClient: IoServiceClient = uninitialized
@InjectMock @InjectMock
@RestClient var ioWrapper: IoGrpcClientWrapper = uninitialized
var ruleClient: RuleServiceClient = uninitialized
@BeforeEach @BeforeEach
def setupMocks(): Unit = def setupMocks(): Unit =
when(ioClient.importFen(any())).thenReturn(GameContext.initial) when(ioWrapper.importFen(any[String]())).thenReturn(GameContext.initial)
when(ioClient.importPgn(any())).thenReturn( when(ioWrapper.importPgn(any[String]())).thenReturn(
PgnParser.importGameContext("1. e4 c5").toOption.get, PgnParser.importGameContext("1. e4 c5").toOption.get,
) )
when(ioClient.exportFen(any())).thenReturn(FenExporter.exportGameContext(GameContext.initial)) when(ioWrapper.exportCombined(any())).thenAnswer((inv: InvocationOnMock) =>
when(ioClient.exportPgn(any())).thenReturn("1. e4 c5")
when(ioClient.exportCombined(any())).thenAnswer((inv: InvocationOnMock) =>
val ctx = inv.getArgument[GameContext](0) val ctx = inv.getArgument[GameContext](0)
CombinedExportResponse(FenExporter.exportGameContext(ctx), ""), CombinedExportResponse(FenExporter.exportGameContext(ctx), ""),
) )
when(ruleClient.legalMoves(any())).thenAnswer((inv: InvocationOnMock) => when(ioWrapper.exportFen(any())).thenAnswer((inv: InvocationOnMock) =>
val req = inv.getArgument[RuleSquareRequest](0) FenExporter.exportGameContext(inv.getArgument[GameContext](0)),
DefaultRules.legalMoves(req.context)(Square.fromAlgebraic(req.square).get),
) )
when(ruleClient.allLegalMoves(any())).thenAnswer((inv: InvocationOnMock) => when(ioWrapper.exportPgn(any())).thenReturn("")
when(ruleAdapter.legalMoves(any())(any())).thenAnswer((inv: InvocationOnMock) =>
DefaultRules.legalMoves(inv.getArgument[GameContext](0))(inv.getArgument[Square](1)),
)
when(ruleAdapter.allLegalMoves(any())).thenAnswer((inv: InvocationOnMock) =>
DefaultRules.allLegalMoves(inv.getArgument[GameContext](0)), DefaultRules.allLegalMoves(inv.getArgument[GameContext](0)),
) )
when(ruleClient.applyMove(any())).thenAnswer((inv: InvocationOnMock) => when(ruleAdapter.applyMove(any())(any())).thenAnswer((inv: InvocationOnMock) =>
val req = inv.getArgument[RuleMoveRequest](0) DefaultRules.applyMove(inv.getArgument[GameContext](0))(inv.getArgument[de.nowchess.api.move.Move](1)),
DefaultRules.applyMove(req.context)(req.move),
) )
when(ruleClient.isCheck(any())).thenAnswer((inv: InvocationOnMock) => when(ruleAdapter.isCheck(any())).thenAnswer((inv: InvocationOnMock) =>
DefaultRules.isCheck(inv.getArgument[GameContext](0)), DefaultRules.isCheck(inv.getArgument[GameContext](0)),
) )
when(ruleClient.isCheckmate(any())).thenAnswer((inv: InvocationOnMock) => when(ruleAdapter.isCheckmate(any())).thenAnswer((inv: InvocationOnMock) =>
DefaultRules.isCheckmate(inv.getArgument[GameContext](0)), DefaultRules.isCheckmate(inv.getArgument[GameContext](0)),
) )
when(ruleClient.isStalemate(any())).thenAnswer((inv: InvocationOnMock) => when(ruleAdapter.isStalemate(any())).thenAnswer((inv: InvocationOnMock) =>
DefaultRules.isStalemate(inv.getArgument[GameContext](0)), DefaultRules.isStalemate(inv.getArgument[GameContext](0)),
) )
when(ruleClient.isInsufficientMaterial(any())).thenAnswer((inv: InvocationOnMock) => when(ruleAdapter.isInsufficientMaterial(any())).thenAnswer((inv: InvocationOnMock) =>
DefaultRules.isInsufficientMaterial(inv.getArgument[GameContext](0)), DefaultRules.isInsufficientMaterial(inv.getArgument[GameContext](0)),
) )
when(ruleClient.isThreefoldRepetition(any())).thenAnswer((inv: InvocationOnMock) => when(ruleAdapter.isThreefoldRepetition(any())).thenAnswer((inv: InvocationOnMock) =>
DefaultRules.isThreefoldRepetition(inv.getArgument[GameContext](0)), DefaultRules.isThreefoldRepetition(inv.getArgument[GameContext](0)),
) )
when(ruleClient.postMoveStatus(any())).thenAnswer((inv: InvocationOnMock) => when(ruleAdapter.postMoveStatus(any())).thenAnswer((inv: InvocationOnMock) =>
DefaultRules.postMoveStatus(inv.getArgument[GameContext](0)), DefaultRules.postMoveStatus(inv.getArgument[GameContext](0)),
) )
when(ruleAdapter.candidateMoves(any())(any())).thenAnswer((inv: InvocationOnMock) =>
DefaultRules.candidateMoves(inv.getArgument[GameContext](0))(inv.getArgument[Square](1)),
)
when(ruleAdapter.isFiftyMoveRule(any())).thenAnswer((inv: InvocationOnMock) =>
DefaultRules.isFiftyMoveRule(inv.getArgument[GameContext](0)),
)
@Test @Test
@DisplayName("createGame returns 201") @DisplayName("createGame returns 201")
@@ -183,8 +187,6 @@ class GameResourceIntegrationTest:
val req = ImportFenRequestDto(fen, None, None, None) val req = ImportFenRequestDto(fen, None, None, None)
val resp = resource.importFen(req) val resp = resource.importFen(req)
assertEquals(201, resp.getStatus) assertEquals(201, resp.getStatus)
val dto = resp.getEntity.asInstanceOf[GameFullDto]
assertEquals(fen, dto.state.fen)
@Test @Test
@DisplayName("importPgn creates game") @DisplayName("importPgn creates game")
@@ -212,5 +214,4 @@ class GameResourceIntegrationTest:
resource.makeMove(gameId, "e2e4") resource.makeMove(gameId, "e2e4")
val resp = resource.exportPgn(gameId) val resp = resource.exportPgn(gameId)
assertEquals(200, resp.getStatus) assertEquals(200, resp.getStatus)
assertTrue(resp.getEntity.asInstanceOf[String].contains("1."))
// scalafix:on // scalafix:on
+1
View File
@@ -64,6 +64,7 @@ dependencies {
implementation("io.quarkus:quarkus-rest-jackson") implementation("io.quarkus:quarkus-rest-jackson")
implementation("io.quarkus:quarkus-arc") implementation("io.quarkus:quarkus-arc")
implementation("io.quarkus:quarkus-config-yaml") implementation("io.quarkus:quarkus-config-yaml")
implementation("io.quarkus:quarkus-grpc")
implementation("io.quarkus:quarkus-smallrye-health") implementation("io.quarkus:quarkus-smallrye-health")
implementation("io.quarkus:quarkus-smallrye-openapi") implementation("io.quarkus:quarkus-smallrye-openapi")
@@ -0,0 +1,87 @@
syntax = "proto3";
option java_package = "de.nowchess.io.proto";
option java_multiple_files = true;
option java_outer_classname = "ChessTypesProto";
enum ProtoColor {
WHITE = 0;
BLACK = 1;
}
enum ProtoPieceType {
PAWN = 0;
KNIGHT = 1;
BISHOP = 2;
ROOK = 3;
QUEEN = 4;
KING = 5;
}
enum ProtoMoveKind {
QUIET = 0;
CAPTURE = 1;
CASTLE_KINGSIDE = 2;
CASTLE_QUEENSIDE = 3;
EN_PASSANT = 4;
PROMO_QUEEN = 5;
PROMO_ROOK = 6;
PROMO_BISHOP = 7;
PROMO_KNIGHT = 8;
}
enum ProtoGameResultKind {
ONGOING = 0;
WIN_CHECKMATE_W = 1;
WIN_CHECKMATE_B = 2;
WIN_RESIGN_W = 3;
WIN_RESIGN_B = 4;
WIN_TIME_W = 5;
WIN_TIME_B = 6;
DRAW_STALEMATE = 7;
DRAW_INSUFFICIENT = 8;
DRAW_FIFTY_MOVE = 9;
DRAW_THREEFOLD = 10;
DRAW_AGREEMENT = 11;
}
message ProtoPiece {
ProtoColor color = 1;
ProtoPieceType piece_type = 2;
}
message ProtoSquarePiece {
string square = 1;
ProtoPiece piece = 2;
}
message ProtoMove {
string from = 1;
string to = 2;
ProtoMoveKind move_kind = 3;
}
message ProtoCastlingRights {
bool white_king_side = 1;
bool white_queen_side = 2;
bool black_king_side = 3;
bool black_queen_side = 4;
}
message ProtoGameContext {
repeated ProtoSquarePiece board = 1;
ProtoColor turn = 2;
ProtoCastlingRights castling_rights = 3;
string en_passant_square = 4;
int32 half_move_clock = 5;
repeated ProtoMove moves = 6;
ProtoGameResultKind result = 7;
repeated ProtoSquarePiece initial_board = 8;
}
message ProtoPostMoveStatus {
bool is_checkmate = 1;
bool is_stalemate = 2;
bool is_insufficient_material = 3;
bool is_check = 4;
bool is_threefold_repetition = 5;
}
@@ -0,0 +1,31 @@
syntax = "proto3";
option java_package = "de.nowchess.io.proto";
option java_multiple_files = true;
option java_outer_classname = "IoServiceProto";
import "chess_types.proto";
message ProtoImportFenRequest {
string fen = 1;
}
message ProtoImportPgnRequest {
string pgn = 1;
}
message ProtoCombinedExport {
string fen = 1;
string pgn = 2;
}
message ProtoStringResult {
string value = 1;
}
service IoService {
rpc ImportFen (ProtoImportFenRequest) returns (ProtoGameContext);
rpc ImportPgn (ProtoImportPgnRequest) returns (ProtoGameContext);
rpc ExportCombined (ProtoGameContext) returns (ProtoCombinedExport);
rpc ExportFen (ProtoGameContext) returns (ProtoStringResult);
rpc ExportPgn (ProtoGameContext) returns (ProtoStringResult);
}
@@ -1,6 +1,9 @@
quarkus: quarkus:
http: http:
port: 8081 port: 8081
grpc:
server:
use-separate-server: false
application: application:
name: nowchess-io name: nowchess-io
smallrye-openapi: smallrye-openapi:
@@ -0,0 +1,50 @@
package de.nowchess.io.grpc
import de.nowchess.io.fen.{FenExporter, FenParser}
import de.nowchess.io.pgn.{PgnExporter, PgnParser}
import de.nowchess.io.proto.*
import io.grpc.stub.StreamObserver
import io.grpc.Status
import io.quarkus.grpc.GrpcService
import scala.jdk.CollectionConverters.*
// scalafix:off DisableSyntax.throw
@GrpcService
class IoGrpcService extends IoServiceGrpc.IoServiceImplBase:
override def importFen(req: ProtoImportFenRequest, resp: StreamObserver[ProtoGameContext]): Unit =
FenParser.parseFen(req.getFen) match
case Left(err) =>
resp.onError(Status.INVALID_ARGUMENT.withDescription(err.message).asRuntimeException())
case Right(ctx) =>
respond(resp, IoProtoMapper.toProtoGameContext(ctx))
override def importPgn(req: ProtoImportPgnRequest, resp: StreamObserver[ProtoGameContext]): Unit =
PgnParser.importGameContext(req.getPgn) match
case Left(err) =>
resp.onError(Status.INVALID_ARGUMENT.withDescription(err.message).asRuntimeException())
case Right(ctx) =>
respond(resp, IoProtoMapper.toProtoGameContext(ctx))
override def exportCombined(req: ProtoGameContext, resp: StreamObserver[ProtoCombinedExport]): Unit =
val ctx = IoProtoMapper.fromProtoGameContext(req)
respond(
resp,
ProtoCombinedExport
.newBuilder()
.setFen(FenExporter.exportGameContext(ctx))
.setPgn(PgnExporter.exportGameContext(ctx))
.build(),
)
override def exportFen(req: ProtoGameContext, resp: StreamObserver[ProtoStringResult]): Unit =
respond(resp, ProtoStringResult.newBuilder().setValue(FenExporter.exportGameContext(IoProtoMapper.fromProtoGameContext(req))).build())
override def exportPgn(req: ProtoGameContext, resp: StreamObserver[ProtoStringResult]): Unit =
respond(resp, ProtoStringResult.newBuilder().setValue(PgnExporter.exportGameContext(IoProtoMapper.fromProtoGameContext(req))).build())
private def respond[T](obs: StreamObserver[T], value: T): Unit =
obs.onNext(value)
obs.onCompleted()
// scalafix:on DisableSyntax.throw
@@ -0,0 +1,142 @@
package de.nowchess.io.grpc
import de.nowchess.api.board.*
import de.nowchess.api.board.{CastlingRights as DomainCastlingRights}
import de.nowchess.api.game.{DrawReason, GameContext, GameResult, WinReason}
import de.nowchess.api.move.{Move as DomainMove, MoveType, PromotionPiece}
import de.nowchess.io.proto.*
import scala.jdk.CollectionConverters.*
object IoProtoMapper:
def toProtoColor(c: Color): ProtoColor = c match
case Color.White => ProtoColor.WHITE
case Color.Black => ProtoColor.BLACK
def fromProtoColor(c: ProtoColor): Color = c match
case ProtoColor.WHITE => Color.White
case _ => Color.Black
def toProtoPieceType(pt: PieceType): ProtoPieceType = pt match
case PieceType.Pawn => ProtoPieceType.PAWN
case PieceType.Knight => ProtoPieceType.KNIGHT
case PieceType.Bishop => ProtoPieceType.BISHOP
case PieceType.Rook => ProtoPieceType.ROOK
case PieceType.Queen => ProtoPieceType.QUEEN
case PieceType.King => ProtoPieceType.KING
def fromProtoPieceType(pt: ProtoPieceType): PieceType = pt match
case ProtoPieceType.PAWN => PieceType.Pawn
case ProtoPieceType.KNIGHT => PieceType.Knight
case ProtoPieceType.BISHOP => PieceType.Bishop
case ProtoPieceType.ROOK => PieceType.Rook
case ProtoPieceType.QUEEN => PieceType.Queen
case _ => PieceType.King
def toProtoMoveKind(mt: MoveType): ProtoMoveKind = mt match
case MoveType.Normal(false) => ProtoMoveKind.QUIET
case MoveType.Normal(true) => ProtoMoveKind.CAPTURE
case MoveType.CastleKingside => ProtoMoveKind.CASTLE_KINGSIDE
case MoveType.CastleQueenside => ProtoMoveKind.CASTLE_QUEENSIDE
case MoveType.EnPassant => ProtoMoveKind.EN_PASSANT
case MoveType.Promotion(PromotionPiece.Queen) => ProtoMoveKind.PROMO_QUEEN
case MoveType.Promotion(PromotionPiece.Rook) => ProtoMoveKind.PROMO_ROOK
case MoveType.Promotion(PromotionPiece.Bishop) => ProtoMoveKind.PROMO_BISHOP
case MoveType.Promotion(PromotionPiece.Knight) => ProtoMoveKind.PROMO_KNIGHT
def fromProtoMoveKind(k: ProtoMoveKind): MoveType = k match
case ProtoMoveKind.QUIET => MoveType.Normal(false)
case ProtoMoveKind.CAPTURE => MoveType.Normal(true)
case ProtoMoveKind.CASTLE_KINGSIDE => MoveType.CastleKingside
case ProtoMoveKind.CASTLE_QUEENSIDE => MoveType.CastleQueenside
case ProtoMoveKind.EN_PASSANT => MoveType.EnPassant
case ProtoMoveKind.PROMO_QUEEN => MoveType.Promotion(PromotionPiece.Queen)
case ProtoMoveKind.PROMO_ROOK => MoveType.Promotion(PromotionPiece.Rook)
case ProtoMoveKind.PROMO_BISHOP => MoveType.Promotion(PromotionPiece.Bishop)
case ProtoMoveKind.PROMO_KNIGHT => MoveType.Promotion(PromotionPiece.Knight)
case _ => MoveType.Normal(false)
def toProtoMove(m: DomainMove): ProtoMove =
ProtoMove.newBuilder().setFrom(m.from.toString).setTo(m.to.toString).setMoveKind(toProtoMoveKind(m.moveType)).build()
def fromProtoMove(m: ProtoMove): Option[DomainMove] =
for
from <- Square.fromAlgebraic(m.getFrom)
to <- Square.fromAlgebraic(m.getTo)
yield DomainMove(from, to, fromProtoMoveKind(m.getMoveKind))
def toProtoBoard(board: Board): java.util.List[ProtoSquarePiece] =
board.pieces.map { (sq, piece) =>
ProtoSquarePiece
.newBuilder()
.setSquare(sq.toString)
.setPiece(ProtoPiece.newBuilder().setColor(toProtoColor(piece.color)).setPieceType(toProtoPieceType(piece.pieceType)).build())
.build()
}.toSeq.asJava
def fromProtoBoard(pieces: java.util.List[ProtoSquarePiece]): Board =
Board(pieces.asScala.flatMap(sp => Square.fromAlgebraic(sp.getSquare).map(_ -> Piece(fromProtoColor(sp.getPiece.getColor), fromProtoPieceType(sp.getPiece.getPieceType)))).toMap)
def toProtoResultKind(r: Option[GameResult]): ProtoGameResultKind = r match
case None => ProtoGameResultKind.ONGOING
case Some(GameResult.Win(Color.White, WinReason.Checkmate)) => ProtoGameResultKind.WIN_CHECKMATE_W
case Some(GameResult.Win(Color.Black, WinReason.Checkmate)) => ProtoGameResultKind.WIN_CHECKMATE_B
case Some(GameResult.Win(Color.White, WinReason.Resignation)) => ProtoGameResultKind.WIN_RESIGN_W
case Some(GameResult.Win(Color.Black, WinReason.Resignation)) => ProtoGameResultKind.WIN_RESIGN_B
case Some(GameResult.Win(Color.White, WinReason.TimeControl)) => ProtoGameResultKind.WIN_TIME_W
case Some(GameResult.Win(Color.Black, WinReason.TimeControl)) => ProtoGameResultKind.WIN_TIME_B
case Some(GameResult.Draw(DrawReason.Stalemate)) => ProtoGameResultKind.DRAW_STALEMATE
case Some(GameResult.Draw(DrawReason.InsufficientMaterial)) => ProtoGameResultKind.DRAW_INSUFFICIENT
case Some(GameResult.Draw(DrawReason.FiftyMoveRule)) => ProtoGameResultKind.DRAW_FIFTY_MOVE
case Some(GameResult.Draw(DrawReason.ThreefoldRepetition)) => ProtoGameResultKind.DRAW_THREEFOLD
case Some(GameResult.Draw(DrawReason.Agreement)) => ProtoGameResultKind.DRAW_AGREEMENT
def fromProtoResultKind(k: ProtoGameResultKind): Option[GameResult] = k match
case ProtoGameResultKind.ONGOING => None
case ProtoGameResultKind.WIN_CHECKMATE_W => Some(GameResult.Win(Color.White, WinReason.Checkmate))
case ProtoGameResultKind.WIN_CHECKMATE_B => Some(GameResult.Win(Color.Black, WinReason.Checkmate))
case ProtoGameResultKind.WIN_RESIGN_W => Some(GameResult.Win(Color.White, WinReason.Resignation))
case ProtoGameResultKind.WIN_RESIGN_B => Some(GameResult.Win(Color.Black, WinReason.Resignation))
case ProtoGameResultKind.WIN_TIME_W => Some(GameResult.Win(Color.White, WinReason.TimeControl))
case ProtoGameResultKind.WIN_TIME_B => Some(GameResult.Win(Color.Black, WinReason.TimeControl))
case ProtoGameResultKind.DRAW_STALEMATE => Some(GameResult.Draw(DrawReason.Stalemate))
case ProtoGameResultKind.DRAW_INSUFFICIENT => Some(GameResult.Draw(DrawReason.InsufficientMaterial))
case ProtoGameResultKind.DRAW_FIFTY_MOVE => Some(GameResult.Draw(DrawReason.FiftyMoveRule))
case ProtoGameResultKind.DRAW_THREEFOLD => Some(GameResult.Draw(DrawReason.ThreefoldRepetition))
case ProtoGameResultKind.DRAW_AGREEMENT => Some(GameResult.Draw(DrawReason.Agreement))
case _ => None
def toProtoGameContext(ctx: GameContext): ProtoGameContext =
ProtoGameContext
.newBuilder()
.addAllBoard(toProtoBoard(ctx.board))
.setTurn(toProtoColor(ctx.turn))
.setCastlingRights(
ProtoCastlingRights
.newBuilder()
.setWhiteKingSide(ctx.castlingRights.whiteKingSide)
.setWhiteQueenSide(ctx.castlingRights.whiteQueenSide)
.setBlackKingSide(ctx.castlingRights.blackKingSide)
.setBlackQueenSide(ctx.castlingRights.blackQueenSide)
.build(),
)
.setEnPassantSquare(ctx.enPassantSquare.map(_.toString).getOrElse(""))
.setHalfMoveClock(ctx.halfMoveClock)
.addAllMoves(ctx.moves.map(toProtoMove).asJava)
.setResult(toProtoResultKind(ctx.result))
.addAllInitialBoard(toProtoBoard(ctx.initialBoard))
.build()
def fromProtoGameContext(p: ProtoGameContext): GameContext =
val cr = p.getCastlingRights
GameContext(
board = fromProtoBoard(p.getBoardList),
turn = fromProtoColor(p.getTurn),
castlingRights = DomainCastlingRights(cr.getWhiteKingSide, cr.getWhiteQueenSide, cr.getBlackKingSide, cr.getBlackQueenSide),
enPassantSquare = Option(p.getEnPassantSquare).filter(_.nonEmpty).flatMap(Square.fromAlgebraic),
halfMoveClock = p.getHalfMoveClock,
moves = p.getMovesList.asScala.flatMap(fromProtoMove).toList,
result = fromProtoResultKind(p.getResult),
initialBoard = fromProtoBoard(p.getInitialBoardList),
)
+8
View File
@@ -22,8 +22,15 @@ scoverage {
scoverageVersion.set(versions["SCOVERAGE"]!!) scoverageVersion.set(versions["SCOVERAGE"]!!)
} }
sourceSets {
main {
java.srcDir("build/classes/java/quarkus-generated-sources/grpc")
}
}
tasks.withType<ScalaCompile> { tasks.withType<ScalaCompile> {
scalaCompileOptions.additionalParameters = listOf("-encoding", "UTF-8") scalaCompileOptions.additionalParameters = listOf("-encoding", "UTF-8")
dependsOn("quarkusGenerateCode")
} }
val quarkusPlatformGroupId: String by project val quarkusPlatformGroupId: String by project
@@ -53,6 +60,7 @@ dependencies {
implementation("io.quarkus:quarkus-rest-client") implementation("io.quarkus:quarkus-rest-client")
implementation("io.quarkus:quarkus-rest-jackson") implementation("io.quarkus:quarkus-rest-jackson")
implementation("io.quarkus:quarkus-config-yaml") implementation("io.quarkus:quarkus-config-yaml")
implementation("io.quarkus:quarkus-grpc")
implementation("io.quarkus:quarkus-smallrye-fault-tolerance") implementation("io.quarkus:quarkus-smallrye-fault-tolerance")
implementation("io.quarkus:quarkus-smallrye-jwt") implementation("io.quarkus:quarkus-smallrye-jwt")
implementation("io.quarkus:quarkus-smallrye-health") implementation("io.quarkus:quarkus-smallrye-health")
@@ -0,0 +1,87 @@
syntax = "proto3";
option java_package = "de.nowchess.rules.proto";
option java_multiple_files = true;
option java_outer_classname = "ChessTypesProto";
enum ProtoColor {
WHITE = 0;
BLACK = 1;
}
enum ProtoPieceType {
PAWN = 0;
KNIGHT = 1;
BISHOP = 2;
ROOK = 3;
QUEEN = 4;
KING = 5;
}
enum ProtoMoveKind {
QUIET = 0;
CAPTURE = 1;
CASTLE_KINGSIDE = 2;
CASTLE_QUEENSIDE = 3;
EN_PASSANT = 4;
PROMO_QUEEN = 5;
PROMO_ROOK = 6;
PROMO_BISHOP = 7;
PROMO_KNIGHT = 8;
}
enum ProtoGameResultKind {
ONGOING = 0;
WIN_CHECKMATE_W = 1;
WIN_CHECKMATE_B = 2;
WIN_RESIGN_W = 3;
WIN_RESIGN_B = 4;
WIN_TIME_W = 5;
WIN_TIME_B = 6;
DRAW_STALEMATE = 7;
DRAW_INSUFFICIENT = 8;
DRAW_FIFTY_MOVE = 9;
DRAW_THREEFOLD = 10;
DRAW_AGREEMENT = 11;
}
message ProtoPiece {
ProtoColor color = 1;
ProtoPieceType piece_type = 2;
}
message ProtoSquarePiece {
string square = 1;
ProtoPiece piece = 2;
}
message ProtoMove {
string from = 1;
string to = 2;
ProtoMoveKind move_kind = 3;
}
message ProtoCastlingRights {
bool white_king_side = 1;
bool white_queen_side = 2;
bool black_king_side = 3;
bool black_queen_side = 4;
}
message ProtoGameContext {
repeated ProtoSquarePiece board = 1;
ProtoColor turn = 2;
ProtoCastlingRights castling_rights = 3;
string en_passant_square = 4;
int32 half_move_clock = 5;
repeated ProtoMove moves = 6;
ProtoGameResultKind result = 7;
repeated ProtoSquarePiece initial_board = 8;
}
message ProtoPostMoveStatus {
bool is_checkmate = 1;
bool is_stalemate = 2;
bool is_insufficient_material = 3;
bool is_check = 4;
bool is_threefold_repetition = 5;
}
@@ -0,0 +1,38 @@
syntax = "proto3";
option java_package = "de.nowchess.rules.proto";
option java_multiple_files = true;
option java_outer_classname = "RuleServiceProto";
import "chess_types.proto";
message ProtoSquareRequest {
ProtoGameContext context = 1;
string square = 2;
}
message ProtoMoveRequest {
ProtoGameContext context = 1;
ProtoMove move = 2;
}
message ProtoMoveList {
repeated ProtoMove moves = 1;
}
message ProtoBoolResult {
bool value = 1;
}
service RuleService {
rpc CandidateMoves (ProtoSquareRequest) returns (ProtoMoveList);
rpc LegalMoves (ProtoSquareRequest) returns (ProtoMoveList);
rpc AllLegalMoves (ProtoGameContext) returns (ProtoMoveList);
rpc IsCheck (ProtoGameContext) returns (ProtoBoolResult);
rpc IsCheckmate (ProtoGameContext) returns (ProtoBoolResult);
rpc IsStalemate (ProtoGameContext) returns (ProtoBoolResult);
rpc IsInsufficientMaterial (ProtoGameContext) returns (ProtoBoolResult);
rpc IsFiftyMoveRule (ProtoGameContext) returns (ProtoBoolResult);
rpc IsThreefoldRepetition (ProtoGameContext) returns (ProtoBoolResult);
rpc ApplyMove (ProtoMoveRequest) returns (ProtoGameContext);
rpc PostMoveStatus (ProtoGameContext) returns (ProtoPostMoveStatus);
}
@@ -1,5 +1,8 @@
quarkus: quarkus:
http: http:
port: 8082 port: 8082
grpc:
server:
use-separate-server: false
application: application:
name: rule-service name: rule-service
@@ -0,0 +1,141 @@
package de.nowchess.rules.grpc
import de.nowchess.api.board.{CastlingRights as DomainCastlingRights, *}
import de.nowchess.api.game.{DrawReason, GameContext, GameResult, WinReason}
import de.nowchess.api.move.{MoveType, PromotionPiece, Move as DomainMove}
import de.nowchess.rules.proto.*
import scala.jdk.CollectionConverters.*
object ProtoMapper:
def toProtoColor(c: Color): ProtoColor = c match
case Color.White => ProtoColor.WHITE
case Color.Black => ProtoColor.BLACK
def fromProtoColor(c: ProtoColor): Color = c match
case ProtoColor.WHITE => Color.White
case _ => Color.Black
def toProtoPieceType(pt: PieceType): ProtoPieceType = pt match
case PieceType.Pawn => ProtoPieceType.PAWN
case PieceType.Knight => ProtoPieceType.KNIGHT
case PieceType.Bishop => ProtoPieceType.BISHOP
case PieceType.Rook => ProtoPieceType.ROOK
case PieceType.Queen => ProtoPieceType.QUEEN
case PieceType.King => ProtoPieceType.KING
def fromProtoPieceType(pt: ProtoPieceType): PieceType = pt match
case ProtoPieceType.PAWN => PieceType.Pawn
case ProtoPieceType.KNIGHT => PieceType.Knight
case ProtoPieceType.BISHOP => PieceType.Bishop
case ProtoPieceType.ROOK => PieceType.Rook
case ProtoPieceType.QUEEN => PieceType.Queen
case _ => PieceType.King
def toProtoMoveKind(mt: MoveType): ProtoMoveKind = mt match
case MoveType.Normal(false) => ProtoMoveKind.QUIET
case MoveType.Normal(true) => ProtoMoveKind.CAPTURE
case MoveType.CastleKingside => ProtoMoveKind.CASTLE_KINGSIDE
case MoveType.CastleQueenside => ProtoMoveKind.CASTLE_QUEENSIDE
case MoveType.EnPassant => ProtoMoveKind.EN_PASSANT
case MoveType.Promotion(PromotionPiece.Queen) => ProtoMoveKind.PROMO_QUEEN
case MoveType.Promotion(PromotionPiece.Rook) => ProtoMoveKind.PROMO_ROOK
case MoveType.Promotion(PromotionPiece.Bishop) => ProtoMoveKind.PROMO_BISHOP
case MoveType.Promotion(PromotionPiece.Knight) => ProtoMoveKind.PROMO_KNIGHT
def fromProtoMoveKind(k: ProtoMoveKind): MoveType = k match
case ProtoMoveKind.QUIET => MoveType.Normal(false)
case ProtoMoveKind.CAPTURE => MoveType.Normal(true)
case ProtoMoveKind.CASTLE_KINGSIDE => MoveType.CastleKingside
case ProtoMoveKind.CASTLE_QUEENSIDE => MoveType.CastleQueenside
case ProtoMoveKind.EN_PASSANT => MoveType.EnPassant
case ProtoMoveKind.PROMO_QUEEN => MoveType.Promotion(PromotionPiece.Queen)
case ProtoMoveKind.PROMO_ROOK => MoveType.Promotion(PromotionPiece.Rook)
case ProtoMoveKind.PROMO_BISHOP => MoveType.Promotion(PromotionPiece.Bishop)
case ProtoMoveKind.PROMO_KNIGHT => MoveType.Promotion(PromotionPiece.Knight)
case _ => MoveType.Normal(false)
def toProtoMove(m: DomainMove): ProtoMove =
ProtoMove.newBuilder().setFrom(m.from.toString).setTo(m.to.toString).setMoveKind(toProtoMoveKind(m.moveType)).build()
def fromProtoMove(m: ProtoMove): Option[DomainMove] =
for
from <- Square.fromAlgebraic(m.getFrom)
to <- Square.fromAlgebraic(m.getTo)
yield DomainMove(from, to, fromProtoMoveKind(m.getMoveKind))
def toProtoBoard(board: Board): java.util.List[ProtoSquarePiece] =
board.pieces.map { (sq, piece) =>
ProtoSquarePiece
.newBuilder()
.setSquare(sq.toString)
.setPiece(ProtoPiece.newBuilder().setColor(toProtoColor(piece.color)).setPieceType(toProtoPieceType(piece.pieceType)).build())
.build()
}.toSeq.asJava
def fromProtoBoard(pieces: java.util.List[ProtoSquarePiece]): Board =
Board(pieces.asScala.flatMap(sp => Square.fromAlgebraic(sp.getSquare).map(_ -> Piece(fromProtoColor(sp.getPiece.getColor), fromProtoPieceType(sp.getPiece.getPieceType)))).toMap)
def toProtoResultKind(r: Option[GameResult]): ProtoGameResultKind = r match
case None => ProtoGameResultKind.ONGOING
case Some(GameResult.Win(Color.White, WinReason.Checkmate)) => ProtoGameResultKind.WIN_CHECKMATE_W
case Some(GameResult.Win(Color.Black, WinReason.Checkmate)) => ProtoGameResultKind.WIN_CHECKMATE_B
case Some(GameResult.Win(Color.White, WinReason.Resignation)) => ProtoGameResultKind.WIN_RESIGN_W
case Some(GameResult.Win(Color.Black, WinReason.Resignation)) => ProtoGameResultKind.WIN_RESIGN_B
case Some(GameResult.Win(Color.White, WinReason.TimeControl)) => ProtoGameResultKind.WIN_TIME_W
case Some(GameResult.Win(Color.Black, WinReason.TimeControl)) => ProtoGameResultKind.WIN_TIME_B
case Some(GameResult.Draw(DrawReason.Stalemate)) => ProtoGameResultKind.DRAW_STALEMATE
case Some(GameResult.Draw(DrawReason.InsufficientMaterial)) => ProtoGameResultKind.DRAW_INSUFFICIENT
case Some(GameResult.Draw(DrawReason.FiftyMoveRule)) => ProtoGameResultKind.DRAW_FIFTY_MOVE
case Some(GameResult.Draw(DrawReason.ThreefoldRepetition)) => ProtoGameResultKind.DRAW_THREEFOLD
case Some(GameResult.Draw(DrawReason.Agreement)) => ProtoGameResultKind.DRAW_AGREEMENT
def fromProtoResultKind(k: ProtoGameResultKind): Option[GameResult] = k match
case ProtoGameResultKind.ONGOING => None
case ProtoGameResultKind.WIN_CHECKMATE_W => Some(GameResult.Win(Color.White, WinReason.Checkmate))
case ProtoGameResultKind.WIN_CHECKMATE_B => Some(GameResult.Win(Color.Black, WinReason.Checkmate))
case ProtoGameResultKind.WIN_RESIGN_W => Some(GameResult.Win(Color.White, WinReason.Resignation))
case ProtoGameResultKind.WIN_RESIGN_B => Some(GameResult.Win(Color.Black, WinReason.Resignation))
case ProtoGameResultKind.WIN_TIME_W => Some(GameResult.Win(Color.White, WinReason.TimeControl))
case ProtoGameResultKind.WIN_TIME_B => Some(GameResult.Win(Color.Black, WinReason.TimeControl))
case ProtoGameResultKind.DRAW_STALEMATE => Some(GameResult.Draw(DrawReason.Stalemate))
case ProtoGameResultKind.DRAW_INSUFFICIENT => Some(GameResult.Draw(DrawReason.InsufficientMaterial))
case ProtoGameResultKind.DRAW_FIFTY_MOVE => Some(GameResult.Draw(DrawReason.FiftyMoveRule))
case ProtoGameResultKind.DRAW_THREEFOLD => Some(GameResult.Draw(DrawReason.ThreefoldRepetition))
case ProtoGameResultKind.DRAW_AGREEMENT => Some(GameResult.Draw(DrawReason.Agreement))
case _ => None
def toProtoGameContext(ctx: GameContext): ProtoGameContext =
ProtoGameContext
.newBuilder()
.addAllBoard(toProtoBoard(ctx.board))
.setTurn(toProtoColor(ctx.turn))
.setCastlingRights(
ProtoCastlingRights
.newBuilder()
.setWhiteKingSide(ctx.castlingRights.whiteKingSide)
.setWhiteQueenSide(ctx.castlingRights.whiteQueenSide)
.setBlackKingSide(ctx.castlingRights.blackKingSide)
.setBlackQueenSide(ctx.castlingRights.blackQueenSide)
.build(),
)
.setEnPassantSquare(ctx.enPassantSquare.map(_.toString).getOrElse(""))
.setHalfMoveClock(ctx.halfMoveClock)
.addAllMoves(ctx.moves.map(toProtoMove).asJava)
.setResult(toProtoResultKind(ctx.result))
.addAllInitialBoard(toProtoBoard(ctx.initialBoard))
.build()
def fromProtoGameContext(p: ProtoGameContext): GameContext =
val cr = p.getCastlingRights
GameContext(
board = fromProtoBoard(p.getBoardList),
turn = fromProtoColor(p.getTurn),
castlingRights = DomainCastlingRights(cr.getWhiteKingSide, cr.getWhiteQueenSide, cr.getBlackKingSide, cr.getBlackQueenSide),
enPassantSquare = Option(p.getEnPassantSquare).filter(_.nonEmpty).flatMap(Square.fromAlgebraic),
halfMoveClock = p.getHalfMoveClock,
moves = p.getMovesList.asScala.flatMap(fromProtoMove).toList,
result = fromProtoResultKind(p.getResult),
initialBoard = fromProtoBoard(p.getInitialBoardList),
)
@@ -0,0 +1,84 @@
package de.nowchess.rules.grpc
import de.nowchess.api.board.Square
import de.nowchess.rules.proto.*
import de.nowchess.rules.sets.DefaultRules
import io.grpc.stub.StreamObserver
import io.grpc.{Status, StatusRuntimeException}
import io.quarkus.grpc.GrpcService
// scalafix:off DisableSyntax.throw
@GrpcService
class RuleGrpcService extends RuleServiceGrpc.RuleServiceImplBase:
private def parseSquare(s: String): Square =
Square.fromAlgebraic(s).getOrElse(
throw Status.INVALID_ARGUMENT.withDescription(s"Invalid square: $s").asRuntimeException(),
)
override def candidateMoves(req: ProtoSquareRequest, resp: StreamObserver[ProtoMoveList]): Unit =
val ctx = ProtoMapper.fromProtoGameContext(req.getContext)
val sq = parseSquare(req.getSquare)
val moves = DefaultRules.candidateMoves(ctx)(sq)
resp.onNext(ProtoMoveList.newBuilder().addAllMoves(moves.map(ProtoMapper.toProtoMove).asInstanceOf[java.util.List[ProtoMove]]).build())
resp.onCompleted()
override def legalMoves(req: ProtoSquareRequest, resp: StreamObserver[ProtoMoveList]): Unit =
val ctx = ProtoMapper.fromProtoGameContext(req.getContext)
val sq = parseSquare(req.getSquare)
val moves = DefaultRules.legalMoves(ctx)(sq)
respond(resp, ProtoMoveList.newBuilder().addAllMoves(toJavaMoveList(moves)).build())
override def allLegalMoves(req: ProtoGameContext, resp: StreamObserver[ProtoMoveList]): Unit =
val moves = DefaultRules.allLegalMoves(ProtoMapper.fromProtoGameContext(req))
respond(resp, ProtoMoveList.newBuilder().addAllMoves(toJavaMoveList(moves)).build())
override def isCheck(req: ProtoGameContext, resp: StreamObserver[ProtoBoolResult]): Unit =
respond(resp, boolResult(DefaultRules.isCheck(ProtoMapper.fromProtoGameContext(req))))
override def isCheckmate(req: ProtoGameContext, resp: StreamObserver[ProtoBoolResult]): Unit =
respond(resp, boolResult(DefaultRules.isCheckmate(ProtoMapper.fromProtoGameContext(req))))
override def isStalemate(req: ProtoGameContext, resp: StreamObserver[ProtoBoolResult]): Unit =
respond(resp, boolResult(DefaultRules.isStalemate(ProtoMapper.fromProtoGameContext(req))))
override def isInsufficientMaterial(req: ProtoGameContext, resp: StreamObserver[ProtoBoolResult]): Unit =
respond(resp, boolResult(DefaultRules.isInsufficientMaterial(ProtoMapper.fromProtoGameContext(req))))
override def isFiftyMoveRule(req: ProtoGameContext, resp: StreamObserver[ProtoBoolResult]): Unit =
respond(resp, boolResult(DefaultRules.isFiftyMoveRule(ProtoMapper.fromProtoGameContext(req))))
override def isThreefoldRepetition(req: ProtoGameContext, resp: StreamObserver[ProtoBoolResult]): Unit =
respond(resp, boolResult(DefaultRules.isThreefoldRepetition(ProtoMapper.fromProtoGameContext(req))))
override def applyMove(req: ProtoMoveRequest, resp: StreamObserver[ProtoGameContext]): Unit =
val ctx = ProtoMapper.fromProtoGameContext(req.getContext)
val move = ProtoMapper.fromProtoMove(req.getMove).getOrElse(
throw Status.INVALID_ARGUMENT.withDescription("Invalid move").asRuntimeException(),
)
respond(resp, ProtoMapper.toProtoGameContext(DefaultRules.applyMove(ctx)(move)))
override def postMoveStatus(req: ProtoGameContext, resp: StreamObserver[ProtoPostMoveStatus]): Unit =
val status = DefaultRules.postMoveStatus(ProtoMapper.fromProtoGameContext(req))
respond(
resp,
ProtoPostMoveStatus
.newBuilder()
.setIsCheckmate(status.isCheckmate)
.setIsStalemate(status.isStalemate)
.setIsInsufficientMaterial(status.isInsufficientMaterial)
.setIsCheck(status.isCheck)
.setIsThreefoldRepetition(status.isThreefoldRepetition)
.build(),
)
private def boolResult(v: Boolean): ProtoBoolResult = ProtoBoolResult.newBuilder().setValue(v).build()
private def respond[T](obs: StreamObserver[T], value: T): Unit =
obs.onNext(value)
obs.onCompleted()
private def toJavaMoveList(moves: List[de.nowchess.api.move.Move]): java.util.List[ProtoMove] =
import scala.jdk.CollectionConverters.*
moves.map(ProtoMapper.toProtoMove).asJava
// scalafix:on DisableSyntax.throw