Compare commits
15 Commits
785d9beac4
...
74cafff6b3
| Author | SHA1 | Date | |
|---|---|---|---|
| 74cafff6b3 | |||
| f2cf899faa | |||
| 5fafd94ea8 | |||
| c567aacf56 | |||
| 22beaa3fda | |||
| a8be2ad608 | |||
| df7cfa1e3f | |||
| 4e5a1b5f89 | |||
| f6c48ee265 | |||
| aea9f1a1ca | |||
| f0bde2df92 | |||
| fa828bf453 | |||
| 3849885c66 | |||
| b50a9eca40 | |||
| f215ec681a |
@@ -47,14 +47,21 @@
|
|||||||
- class Square
|
- class Square
|
||||||
- function fromAlgebraic
|
- function fromAlgebraic
|
||||||
- function offset
|
- function offset
|
||||||
|
- `modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala`
|
||||||
|
- class Bot
|
||||||
|
- function name
|
||||||
|
- function nextMove
|
||||||
|
- `modules/api/src/main/scala/de/nowchess/api/dto/ErrorEventDto.scala` — class ErrorEventDto, function apply
|
||||||
|
- `modules/api/src/main/scala/de/nowchess/api/dto/GameFullEventDto.scala` — class GameFullEventDto, function apply
|
||||||
|
- `modules/api/src/main/scala/de/nowchess/api/dto/GameStateEventDto.scala` — class GameStateEventDto, function apply
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`
|
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`
|
||||||
|
- function kingSquare
|
||||||
- function withBoard
|
- function withBoard
|
||||||
- function withTurn
|
- function withTurn
|
||||||
- function withCastlingRights
|
- function withCastlingRights
|
||||||
- function withEnPassantSquare
|
- function withEnPassantSquare
|
||||||
- function withHalfMoveClock
|
- function withHalfMoveClock
|
||||||
- function withMove
|
- _...4 more_
|
||||||
- _...2 more_
|
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/player/PlayerInfo.scala` — class PlayerId, function apply
|
- `modules/api/src/main/scala/de/nowchess/api/player/PlayerInfo.scala` — class PlayerId, function apply
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/response/ApiResponse.scala`
|
- `modules/api/src/main/scala/de/nowchess/api/response/ApiResponse.scala`
|
||||||
- class ApiResponse
|
- class ApiResponse
|
||||||
@@ -79,6 +86,7 @@
|
|||||||
- `modules/bot/python/src/export.py` — function export_to_nbai: (weights_file, output_file, trained_by, train_loss)
|
- `modules/bot/python/src/export.py` — function export_to_nbai: (weights_file, output_file, trained_by, train_loss)
|
||||||
- `modules/bot/python/src/generate.py` — function play_random_game_and_collect_positions: (output_file, total_positions, samples_per_game, min_move, max_move, num_workers)
|
- `modules/bot/python/src/generate.py` — function play_random_game_and_collect_positions: (output_file, total_positions, samples_per_game, min_move, max_move, num_workers)
|
||||||
- `modules/bot/python/src/label.py` — function normalize_evaluation: (cp_value, method, scale), function label_positions_with_stockfish: (positions_file, output_file, stockfish_path, batch_size, depth, verbose, normalize, num_workers)
|
- `modules/bot/python/src/label.py` — function normalize_evaluation: (cp_value, method, scale), function label_positions_with_stockfish: (positions_file, output_file, stockfish_path, batch_size, depth, verbose, normalize, num_workers)
|
||||||
|
- `modules/bot/python/src/lichess_importer.py` — function import_lichess_evals: (input_path, output_file, max_positions, min_depth, verbose) -> int
|
||||||
- `modules/bot/python/src/tactical_positions_extractor.py`
|
- `modules/bot/python/src/tactical_positions_extractor.py`
|
||||||
- function download_and_extract_puzzle_db: (url, output_dir)
|
- function download_and_extract_puzzle_db: (url, output_dir)
|
||||||
- function extract_puzzle_positions: (puzzle_csv, max_puzzles) -> Set[str]
|
- function extract_puzzle_positions: (puzzle_csv, max_puzzles) -> Set[str]
|
||||||
@@ -90,14 +98,10 @@
|
|||||||
- function fen_to_features: (fen)
|
- function fen_to_features: (fen)
|
||||||
- function find_next_version: (base_name)
|
- function find_next_version: (base_name)
|
||||||
- function save_metadata: (weights_file, metadata)
|
- function save_metadata: (weights_file, metadata)
|
||||||
- function train_nnue: (data_file, output_file, epochs, batch_size, lr, checkpoint, stockfish_depth, use_versioning, early_stopping_patience, weight_decay, subsample_ratio)
|
- function train_nnue: (data_file, output_file, epochs, batch_size, lr, checkpoint, stockfish_depth, use_versioning, early_stopping_patience, weight_decay, subsample_ratio, hidden_sizes)
|
||||||
- function burst_train: (data_file, output_file, duration_minutes, epochs_per_season, early_stopping_patience, batch_size, lr, initial_checkpoint, stockfish_depth, use_versioning, weight_decay, subsample_ratio)
|
- function burst_train: (data_file, output_file, duration_minutes, epochs_per_season, early_stopping_patience, batch_size, lr, initial_checkpoint, stockfish_depth, use_versioning, weight_decay, subsample_ratio, hidden_sizes)
|
||||||
- class NNUEDataset
|
- class NNUEDataset
|
||||||
- _...1 more_
|
- _...1 more_
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/Bot.scala`
|
|
||||||
- class Bot
|
|
||||||
- function name
|
|
||||||
- function nextMove
|
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/BotController.scala`
|
- `modules/bot/src/main/scala/de/nowchess/bot/BotController.scala`
|
||||||
- class BotController
|
- class BotController
|
||||||
- function getBot
|
- function getBot
|
||||||
@@ -148,7 +152,6 @@
|
|||||||
- function bestMoveWithTime
|
- function bestMoveWithTime
|
||||||
- function loop
|
- function loop
|
||||||
- function loop
|
- function loop
|
||||||
- _...2 more_
|
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/logic/MoveOrdering.scala`
|
- `modules/bot/src/main/scala/de/nowchess/bot/logic/MoveOrdering.scala`
|
||||||
- class MoveOrdering
|
- class MoveOrdering
|
||||||
- class OrderingContext
|
- class OrderingContext
|
||||||
@@ -158,6 +161,7 @@
|
|||||||
- function getHistory
|
- function getHistory
|
||||||
- _...3 more_
|
- _...3 more_
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/logic/TranspositionTable.scala`
|
- `modules/bot/src/main/scala/de/nowchess/bot/logic/TranspositionTable.scala`
|
||||||
|
- function advance
|
||||||
- function probe
|
- function probe
|
||||||
- function store
|
- function store
|
||||||
- function clear
|
- function clear
|
||||||
@@ -181,14 +185,15 @@
|
|||||||
- function history
|
- function history
|
||||||
- function getCurrentIndex
|
- function getCurrentIndex
|
||||||
- _...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/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
|
||||||
- function isPendingPromotion
|
|
||||||
- function board
|
- function board
|
||||||
- function turn
|
- function turn
|
||||||
- function context
|
- function context
|
||||||
- function canUndo
|
- function canUndo
|
||||||
|
- function canRedo
|
||||||
- _...11 more_
|
- _...11 more_
|
||||||
- `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
|
||||||
@@ -198,6 +203,26 @@
|
|||||||
- function subscribe
|
- function subscribe
|
||||||
- function unsubscribe
|
- function unsubscribe
|
||||||
- _...1 more_
|
- _...1 more_
|
||||||
|
- `modules/core/src/main/scala/de/nowchess/chess/registry/GameRegistry.scala`
|
||||||
|
- class GameRegistry
|
||||||
|
- function store
|
||||||
|
- function get
|
||||||
|
- function update
|
||||||
|
- function generateId
|
||||||
|
- `modules/core/src/main/scala/de/nowchess/chess/registry/GameRegistryImpl.scala`
|
||||||
|
- class GameRegistryImpl
|
||||||
|
- function store
|
||||||
|
- function get
|
||||||
|
- function update
|
||||||
|
- function generateId
|
||||||
|
- `modules/core/src/main/scala/de/nowchess/chess/resource/GameResource.scala`
|
||||||
|
- function onGameEvent
|
||||||
|
- function createGame
|
||||||
|
- function getGame
|
||||||
|
- function streamGame
|
||||||
|
- function onGameEvent
|
||||||
|
- function resignGame
|
||||||
|
- _...9 more_
|
||||||
- `modules/io/src/main/scala/de/nowchess/io/GameContextExport.scala` — class GameContextExport, function exportGameContext
|
- `modules/io/src/main/scala/de/nowchess/io/GameContextExport.scala` — class GameContextExport, function exportGameContext
|
||||||
- `modules/io/src/main/scala/de/nowchess/io/GameContextImport.scala` — class GameContextImport, function importGameContext
|
- `modules/io/src/main/scala/de/nowchess/io/GameContextImport.scala` — class GameContextImport, function importGameContext
|
||||||
- `modules/io/src/main/scala/de/nowchess/io/GameFileService.scala`
|
- `modules/io/src/main/scala/de/nowchess/io/GameFileService.scala`
|
||||||
@@ -247,32 +272,13 @@
|
|||||||
- function allLegalMoves
|
- function allLegalMoves
|
||||||
- function isCheck
|
- function isCheck
|
||||||
- function isCheckmate
|
- function isCheckmate
|
||||||
- _...4 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
|
- class DefaultRules
|
||||||
|
- function positionOf
|
||||||
- function loop
|
- function loop
|
||||||
- function toMoves
|
- function toMoves
|
||||||
- function loop
|
- function loop
|
||||||
- `modules/ui/src/main/scala/de/nowchess/ui/Main.scala` — class Main, function main
|
|
||||||
- `modules/ui/src/main/scala/de/nowchess/ui/gui/ChessBoardView.scala`
|
|
||||||
- class ChessBoardView
|
|
||||||
- function updateBoard
|
|
||||||
- function updateUndoRedoButtons
|
|
||||||
- function showMessage
|
|
||||||
- function showPromotionDialog
|
|
||||||
- `modules/ui/src/main/scala/de/nowchess/ui/gui/ChessGUI.scala`
|
|
||||||
- class ChessGUIApp
|
|
||||||
- class ChessGUILauncher
|
|
||||||
- function getEngine
|
|
||||||
- function launch
|
|
||||||
- `modules/ui/src/main/scala/de/nowchess/ui/gui/GUIObserver.scala` — class GUIObserver
|
|
||||||
- `modules/ui/src/main/scala/de/nowchess/ui/gui/PieceSprites.scala`
|
|
||||||
- class PieceSprites
|
|
||||||
- function loadPieceImage
|
|
||||||
- class SquareColors
|
|
||||||
- `modules/ui/src/main/scala/de/nowchess/ui/terminal/TerminalUI.scala` — class TerminalUI, function start
|
|
||||||
- `modules/ui/src/main/scala/de/nowchess/ui/utils/PieceUnicode.scala` — function unicode
|
|
||||||
- `modules/ui/src/main/scala/de/nowchess/ui/utils/Renderer.scala` — class Renderer, function render
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -295,39 +301,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 **60** files
|
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala` — imported by **64** files
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/move/Move.scala` — imported by **40** files
|
- `modules/api/src/main/scala/de/nowchess/api/move/Move.scala` — imported by **44** files
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/board/Square.scala` — imported by **39** files
|
- `modules/api/src/main/scala/de/nowchess/api/board/Square.scala` — imported by **40** files
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/board/Color.scala` — imported by **36** files
|
- `modules/api/src/main/scala/de/nowchess/api/board/Color.scala` — imported by **35** files
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/board/Board.scala` — imported by **22** files
|
- `modules/api/src/main/scala/de/nowchess/api/board/Board.scala` — imported by **19** files
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/board/PieceType.scala` — imported by **21** files
|
- `modules/api/src/main/scala/de/nowchess/api/board/Piece.scala` — imported by **18** files
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/board/Piece.scala` — imported by **21** files
|
- `modules/api/src/main/scala/de/nowchess/api/board/PieceType.scala` — imported by **17** files
|
||||||
- `modules/rule/src/main/scala/de/nowchess/rules/sets/DefaultRules.scala` — imported by **17** files
|
- `modules/rule/src/main/scala/de/nowchess/rules/sets/DefaultRules.scala` — imported by **17** files
|
||||||
- `modules/rule/src/main/scala/de/nowchess/rules/RuleSet.scala` — imported by **10** files
|
- `modules/rule/src/main/scala/de/nowchess/rules/RuleSet.scala` — imported by **11** files
|
||||||
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParser.scala` — imported by **10** files
|
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParser.scala` — imported by **10** files
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/board/CastlingRights.scala` — imported by **8** files
|
- `modules/api/src/main/scala/de/nowchess/api/board/CastlingRights.scala` — imported by **9** files
|
||||||
- `modules/io/src/main/scala/de/nowchess/io/GameContextImport.scala` — imported by **8** files
|
- `modules/api/src/main/scala/de/nowchess/api/game/DrawReason.scala` — imported by **7** files
|
||||||
|
- `modules/io/src/main/scala/de/nowchess/io/GameContextImport.scala` — imported by **7** files
|
||||||
|
- `modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala` — imported by **6** files
|
||||||
|
- `modules/bot/src/main/scala/de/nowchess/bot/ai/Evaluation.scala` — imported by **6** files
|
||||||
|
- `modules/api/src/main/scala/de/nowchess/api/player/PlayerInfo.scala` — imported by **5** files
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/util/PolyglotBook.scala` — imported by **5** files
|
- `modules/bot/src/main/scala/de/nowchess/bot/util/PolyglotBook.scala` — imported by **5** files
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/BotDifficulty.scala` — imported by **5** files
|
- `modules/api/src/main/scala/de/nowchess/api/game/GameResult.scala` — imported by **4** files
|
||||||
- `modules/io/src/main/scala/de/nowchess/io/GameContextExport.scala` — imported by **5** files
|
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/bots/ClassicalBot.scala` — imported by **4** files
|
- `modules/bot/src/main/scala/de/nowchess/bot/bots/ClassicalBot.scala` — imported by **4** files
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/bots/classic/EvaluationClassic.scala` — imported by **4** files
|
- `modules/bot/src/main/scala/de/nowchess/bot/bots/classic/EvaluationClassic.scala` — imported by **4** files
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/logic/AlphaBetaSearch.scala` — imported by **4** files
|
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/Bot.scala` — imported by **4** files
|
|
||||||
- `modules/core/src/main/scala/de/nowchess/chess/observer/Observer.scala` — imported by **4** files
|
|
||||||
|
|
||||||
## Import Map (who imports what)
|
## Import Map (who imports what)
|
||||||
|
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala` ← `modules/bot/src/main/scala/de/nowchess/bot/Bot.scala`, `modules/bot/src/main/scala/de/nowchess/bot/BotMoveRepetition.scala`, `modules/bot/src/main/scala/de/nowchess/bot/ai/Evaluation.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/ClassicalBot.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/HybridBot.scala` +55 more
|
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala` ← `modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala`, `modules/bot/src/main/scala/de/nowchess/bot/BotMoveRepetition.scala`, `modules/bot/src/main/scala/de/nowchess/bot/ai/Evaluation.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/ClassicalBot.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/HybridBot.scala` +59 more
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/move/Move.scala` ← `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/test/scala/de/nowchess/api/board/BoardTest.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/bot/src/main/scala/de/nowchess/bot/Bot.scala`, `modules/bot/src/main/scala/de/nowchess/bot/BotMoveRepetition.scala` +35 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/test/scala/de/nowchess/api/board/BoardTest.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/bot/src/main/scala/de/nowchess/bot/BotMoveRepetition.scala` +39 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/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/api/src/test/scala/de/nowchess/api/move/MoveTest.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/classic/EvaluationClassic.scala` +34 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/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/api/src/test/scala/de/nowchess/api/move/MoveTest.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/classic/EvaluationClassic.scala` +35 more
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/board/Color.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/classic/EvaluationClassic.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NNUE.scala`, `modules/bot/src/main/scala/de/nowchess/bot/logic/MoveOrdering.scala` +31 more
|
- `modules/api/src/main/scala/de/nowchess/api/board/Color.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/GameContextTest.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` +30 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` +17 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` +14 more
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/board/PieceType.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`, `modules/bot/src/main/scala/de/nowchess/bot/util/PolyglotHash.scala` +16 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` +13 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/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` +12 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` +12 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` +12 more
|
||||||
- `modules/rule/src/main/scala/de/nowchess/rules/RuleSet.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` +5 more
|
- `modules/rule/src/main/scala/de/nowchess/rules/RuleSet.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` +6 more
|
||||||
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParser.scala` ← `modules/bot/src/test/scala/de/nowchess/bot/PolyglotHashTest.scala`, `modules/core/src/test/scala/de/nowchess/chess/engine/EngineTestHelpers.scala`, `modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineLoadGameTest.scala`, `modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineNotationTest.scala`, `modules/core/src/test/scala/de/nowchess/chess/engine/GameEnginePromotionTest.scala` +5 more
|
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParser.scala` ← `modules/bot/src/test/scala/de/nowchess/bot/PolyglotHashTest.scala`, `modules/core/src/main/scala/de/nowchess/chess/resource/GameResource.scala`, `modules/core/src/test/scala/de/nowchess/chess/engine/EngineTestHelpers.scala`, `modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineLoadGameTest.scala`, `modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineNotationTest.scala` +5 more
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -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 **60** files
|
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala` — imported by **64** files
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/move/Move.scala` — imported by **40** files
|
- `modules/api/src/main/scala/de/nowchess/api/move/Move.scala` — imported by **44** files
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/board/Square.scala` — imported by **39** files
|
- `modules/api/src/main/scala/de/nowchess/api/board/Square.scala` — imported by **40** files
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/board/Color.scala` — imported by **36** files
|
- `modules/api/src/main/scala/de/nowchess/api/board/Color.scala` — imported by **35** files
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/board/Board.scala` — imported by **22** files
|
- `modules/api/src/main/scala/de/nowchess/api/board/Board.scala` — imported by **19** files
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/board/PieceType.scala` — imported by **21** files
|
- `modules/api/src/main/scala/de/nowchess/api/board/Piece.scala` — imported by **18** files
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/board/Piece.scala` — imported by **21** files
|
- `modules/api/src/main/scala/de/nowchess/api/board/PieceType.scala` — imported by **17** files
|
||||||
- `modules/rule/src/main/scala/de/nowchess/rules/sets/DefaultRules.scala` — imported by **17** files
|
- `modules/rule/src/main/scala/de/nowchess/rules/sets/DefaultRules.scala` — imported by **17** files
|
||||||
- `modules/rule/src/main/scala/de/nowchess/rules/RuleSet.scala` — imported by **10** files
|
- `modules/rule/src/main/scala/de/nowchess/rules/RuleSet.scala` — imported by **11** files
|
||||||
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParser.scala` — imported by **10** files
|
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParser.scala` — imported by **10** files
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/board/CastlingRights.scala` — imported by **8** files
|
- `modules/api/src/main/scala/de/nowchess/api/board/CastlingRights.scala` — imported by **9** files
|
||||||
- `modules/io/src/main/scala/de/nowchess/io/GameContextImport.scala` — imported by **8** files
|
- `modules/api/src/main/scala/de/nowchess/api/game/DrawReason.scala` — imported by **7** files
|
||||||
|
- `modules/io/src/main/scala/de/nowchess/io/GameContextImport.scala` — imported by **7** files
|
||||||
|
- `modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala` — imported by **6** files
|
||||||
|
- `modules/bot/src/main/scala/de/nowchess/bot/ai/Evaluation.scala` — imported by **6** files
|
||||||
|
- `modules/api/src/main/scala/de/nowchess/api/player/PlayerInfo.scala` — imported by **5** files
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/util/PolyglotBook.scala` — imported by **5** files
|
- `modules/bot/src/main/scala/de/nowchess/bot/util/PolyglotBook.scala` — imported by **5** files
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/BotDifficulty.scala` — imported by **5** files
|
- `modules/api/src/main/scala/de/nowchess/api/game/GameResult.scala` — imported by **4** files
|
||||||
- `modules/io/src/main/scala/de/nowchess/io/GameContextExport.scala` — imported by **5** files
|
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/bots/ClassicalBot.scala` — imported by **4** files
|
- `modules/bot/src/main/scala/de/nowchess/bot/bots/ClassicalBot.scala` — imported by **4** files
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/bots/classic/EvaluationClassic.scala` — imported by **4** files
|
- `modules/bot/src/main/scala/de/nowchess/bot/bots/classic/EvaluationClassic.scala` — imported by **4** files
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/logic/AlphaBetaSearch.scala` — imported by **4** files
|
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/Bot.scala` — imported by **4** files
|
|
||||||
- `modules/core/src/main/scala/de/nowchess/chess/observer/Observer.scala` — imported by **4** files
|
|
||||||
|
|
||||||
## Import Map (who imports what)
|
## Import Map (who imports what)
|
||||||
|
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala` ← `modules/bot/src/main/scala/de/nowchess/bot/Bot.scala`, `modules/bot/src/main/scala/de/nowchess/bot/BotMoveRepetition.scala`, `modules/bot/src/main/scala/de/nowchess/bot/ai/Evaluation.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/ClassicalBot.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/HybridBot.scala` +55 more
|
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala` ← `modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala`, `modules/bot/src/main/scala/de/nowchess/bot/BotMoveRepetition.scala`, `modules/bot/src/main/scala/de/nowchess/bot/ai/Evaluation.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/ClassicalBot.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/HybridBot.scala` +59 more
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/move/Move.scala` ← `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/test/scala/de/nowchess/api/board/BoardTest.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/bot/src/main/scala/de/nowchess/bot/Bot.scala`, `modules/bot/src/main/scala/de/nowchess/bot/BotMoveRepetition.scala` +35 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/test/scala/de/nowchess/api/board/BoardTest.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/bot/src/main/scala/de/nowchess/bot/BotMoveRepetition.scala` +39 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/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/api/src/test/scala/de/nowchess/api/move/MoveTest.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/classic/EvaluationClassic.scala` +34 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/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/api/src/test/scala/de/nowchess/api/move/MoveTest.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/classic/EvaluationClassic.scala` +35 more
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/board/Color.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/classic/EvaluationClassic.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NNUE.scala`, `modules/bot/src/main/scala/de/nowchess/bot/logic/MoveOrdering.scala` +31 more
|
- `modules/api/src/main/scala/de/nowchess/api/board/Color.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/GameContextTest.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` +30 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` +17 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` +14 more
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/board/PieceType.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`, `modules/bot/src/main/scala/de/nowchess/bot/util/PolyglotHash.scala` +16 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` +13 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/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` +12 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` +12 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` +12 more
|
||||||
- `modules/rule/src/main/scala/de/nowchess/rules/RuleSet.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` +5 more
|
- `modules/rule/src/main/scala/de/nowchess/rules/RuleSet.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` +6 more
|
||||||
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParser.scala` ← `modules/bot/src/test/scala/de/nowchess/bot/PolyglotHashTest.scala`, `modules/core/src/test/scala/de/nowchess/chess/engine/EngineTestHelpers.scala`, `modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineLoadGameTest.scala`, `modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineNotationTest.scala`, `modules/core/src/test/scala/de/nowchess/chess/engine/GameEnginePromotionTest.scala` +5 more
|
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParser.scala` ← `modules/bot/src/test/scala/de/nowchess/bot/PolyglotHashTest.scala`, `modules/core/src/main/scala/de/nowchess/chess/resource/GameResource.scala`, `modules/core/src/test/scala/de/nowchess/chess/engine/EngineTestHelpers.scala`, `modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineLoadGameTest.scala`, `modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineNotationTest.scala` +5 more
|
||||||
|
|||||||
@@ -38,14 +38,21 @@
|
|||||||
- class Square
|
- class Square
|
||||||
- function fromAlgebraic
|
- function fromAlgebraic
|
||||||
- function offset
|
- function offset
|
||||||
|
- `modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala`
|
||||||
|
- class Bot
|
||||||
|
- function name
|
||||||
|
- function nextMove
|
||||||
|
- `modules/api/src/main/scala/de/nowchess/api/dto/ErrorEventDto.scala` — class ErrorEventDto, function apply
|
||||||
|
- `modules/api/src/main/scala/de/nowchess/api/dto/GameFullEventDto.scala` — class GameFullEventDto, function apply
|
||||||
|
- `modules/api/src/main/scala/de/nowchess/api/dto/GameStateEventDto.scala` — class GameStateEventDto, function apply
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`
|
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`
|
||||||
|
- function kingSquare
|
||||||
- function withBoard
|
- function withBoard
|
||||||
- function withTurn
|
- function withTurn
|
||||||
- function withCastlingRights
|
- function withCastlingRights
|
||||||
- function withEnPassantSquare
|
- function withEnPassantSquare
|
||||||
- function withHalfMoveClock
|
- function withHalfMoveClock
|
||||||
- function withMove
|
- _...4 more_
|
||||||
- _...2 more_
|
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/player/PlayerInfo.scala` — class PlayerId, function apply
|
- `modules/api/src/main/scala/de/nowchess/api/player/PlayerInfo.scala` — class PlayerId, function apply
|
||||||
- `modules/api/src/main/scala/de/nowchess/api/response/ApiResponse.scala`
|
- `modules/api/src/main/scala/de/nowchess/api/response/ApiResponse.scala`
|
||||||
- class ApiResponse
|
- class ApiResponse
|
||||||
@@ -70,6 +77,7 @@
|
|||||||
- `modules/bot/python/src/export.py` — function export_to_nbai: (weights_file, output_file, trained_by, train_loss)
|
- `modules/bot/python/src/export.py` — function export_to_nbai: (weights_file, output_file, trained_by, train_loss)
|
||||||
- `modules/bot/python/src/generate.py` — function play_random_game_and_collect_positions: (output_file, total_positions, samples_per_game, min_move, max_move, num_workers)
|
- `modules/bot/python/src/generate.py` — function play_random_game_and_collect_positions: (output_file, total_positions, samples_per_game, min_move, max_move, num_workers)
|
||||||
- `modules/bot/python/src/label.py` — function normalize_evaluation: (cp_value, method, scale), function label_positions_with_stockfish: (positions_file, output_file, stockfish_path, batch_size, depth, verbose, normalize, num_workers)
|
- `modules/bot/python/src/label.py` — function normalize_evaluation: (cp_value, method, scale), function label_positions_with_stockfish: (positions_file, output_file, stockfish_path, batch_size, depth, verbose, normalize, num_workers)
|
||||||
|
- `modules/bot/python/src/lichess_importer.py` — function import_lichess_evals: (input_path, output_file, max_positions, min_depth, verbose) -> int
|
||||||
- `modules/bot/python/src/tactical_positions_extractor.py`
|
- `modules/bot/python/src/tactical_positions_extractor.py`
|
||||||
- function download_and_extract_puzzle_db: (url, output_dir)
|
- function download_and_extract_puzzle_db: (url, output_dir)
|
||||||
- function extract_puzzle_positions: (puzzle_csv, max_puzzles) -> Set[str]
|
- function extract_puzzle_positions: (puzzle_csv, max_puzzles) -> Set[str]
|
||||||
@@ -81,14 +89,10 @@
|
|||||||
- function fen_to_features: (fen)
|
- function fen_to_features: (fen)
|
||||||
- function find_next_version: (base_name)
|
- function find_next_version: (base_name)
|
||||||
- function save_metadata: (weights_file, metadata)
|
- function save_metadata: (weights_file, metadata)
|
||||||
- function train_nnue: (data_file, output_file, epochs, batch_size, lr, checkpoint, stockfish_depth, use_versioning, early_stopping_patience, weight_decay, subsample_ratio)
|
- function train_nnue: (data_file, output_file, epochs, batch_size, lr, checkpoint, stockfish_depth, use_versioning, early_stopping_patience, weight_decay, subsample_ratio, hidden_sizes)
|
||||||
- function burst_train: (data_file, output_file, duration_minutes, epochs_per_season, early_stopping_patience, batch_size, lr, initial_checkpoint, stockfish_depth, use_versioning, weight_decay, subsample_ratio)
|
- function burst_train: (data_file, output_file, duration_minutes, epochs_per_season, early_stopping_patience, batch_size, lr, initial_checkpoint, stockfish_depth, use_versioning, weight_decay, subsample_ratio, hidden_sizes)
|
||||||
- class NNUEDataset
|
- class NNUEDataset
|
||||||
- _...1 more_
|
- _...1 more_
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/Bot.scala`
|
|
||||||
- class Bot
|
|
||||||
- function name
|
|
||||||
- function nextMove
|
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/BotController.scala`
|
- `modules/bot/src/main/scala/de/nowchess/bot/BotController.scala`
|
||||||
- class BotController
|
- class BotController
|
||||||
- function getBot
|
- function getBot
|
||||||
@@ -139,7 +143,6 @@
|
|||||||
- function bestMoveWithTime
|
- function bestMoveWithTime
|
||||||
- function loop
|
- function loop
|
||||||
- function loop
|
- function loop
|
||||||
- _...2 more_
|
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/logic/MoveOrdering.scala`
|
- `modules/bot/src/main/scala/de/nowchess/bot/logic/MoveOrdering.scala`
|
||||||
- class MoveOrdering
|
- class MoveOrdering
|
||||||
- class OrderingContext
|
- class OrderingContext
|
||||||
@@ -149,6 +152,7 @@
|
|||||||
- function getHistory
|
- function getHistory
|
||||||
- _...3 more_
|
- _...3 more_
|
||||||
- `modules/bot/src/main/scala/de/nowchess/bot/logic/TranspositionTable.scala`
|
- `modules/bot/src/main/scala/de/nowchess/bot/logic/TranspositionTable.scala`
|
||||||
|
- function advance
|
||||||
- function probe
|
- function probe
|
||||||
- function store
|
- function store
|
||||||
- function clear
|
- function clear
|
||||||
@@ -172,14 +176,15 @@
|
|||||||
- function history
|
- function history
|
||||||
- function getCurrentIndex
|
- function getCurrentIndex
|
||||||
- _...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/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
|
||||||
- function isPendingPromotion
|
|
||||||
- function board
|
- function board
|
||||||
- function turn
|
- function turn
|
||||||
- function context
|
- function context
|
||||||
- function canUndo
|
- function canUndo
|
||||||
|
- function canRedo
|
||||||
- _...11 more_
|
- _...11 more_
|
||||||
- `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
|
||||||
@@ -189,6 +194,26 @@
|
|||||||
- function subscribe
|
- function subscribe
|
||||||
- function unsubscribe
|
- function unsubscribe
|
||||||
- _...1 more_
|
- _...1 more_
|
||||||
|
- `modules/core/src/main/scala/de/nowchess/chess/registry/GameRegistry.scala`
|
||||||
|
- class GameRegistry
|
||||||
|
- function store
|
||||||
|
- function get
|
||||||
|
- function update
|
||||||
|
- function generateId
|
||||||
|
- `modules/core/src/main/scala/de/nowchess/chess/registry/GameRegistryImpl.scala`
|
||||||
|
- class GameRegistryImpl
|
||||||
|
- function store
|
||||||
|
- function get
|
||||||
|
- function update
|
||||||
|
- function generateId
|
||||||
|
- `modules/core/src/main/scala/de/nowchess/chess/resource/GameResource.scala`
|
||||||
|
- function onGameEvent
|
||||||
|
- function createGame
|
||||||
|
- function getGame
|
||||||
|
- function streamGame
|
||||||
|
- function onGameEvent
|
||||||
|
- function resignGame
|
||||||
|
- _...9 more_
|
||||||
- `modules/io/src/main/scala/de/nowchess/io/GameContextExport.scala` — class GameContextExport, function exportGameContext
|
- `modules/io/src/main/scala/de/nowchess/io/GameContextExport.scala` — class GameContextExport, function exportGameContext
|
||||||
- `modules/io/src/main/scala/de/nowchess/io/GameContextImport.scala` — class GameContextImport, function importGameContext
|
- `modules/io/src/main/scala/de/nowchess/io/GameContextImport.scala` — class GameContextImport, function importGameContext
|
||||||
- `modules/io/src/main/scala/de/nowchess/io/GameFileService.scala`
|
- `modules/io/src/main/scala/de/nowchess/io/GameFileService.scala`
|
||||||
@@ -238,29 +263,10 @@
|
|||||||
- function allLegalMoves
|
- function allLegalMoves
|
||||||
- function isCheck
|
- function isCheck
|
||||||
- function isCheckmate
|
- function isCheckmate
|
||||||
- _...4 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
|
- class DefaultRules
|
||||||
|
- function positionOf
|
||||||
- function loop
|
- function loop
|
||||||
- function toMoves
|
- function toMoves
|
||||||
- function loop
|
- function loop
|
||||||
- `modules/ui/src/main/scala/de/nowchess/ui/Main.scala` — class Main, function main
|
|
||||||
- `modules/ui/src/main/scala/de/nowchess/ui/gui/ChessBoardView.scala`
|
|
||||||
- class ChessBoardView
|
|
||||||
- function updateBoard
|
|
||||||
- function updateUndoRedoButtons
|
|
||||||
- function showMessage
|
|
||||||
- function showPromotionDialog
|
|
||||||
- `modules/ui/src/main/scala/de/nowchess/ui/gui/ChessGUI.scala`
|
|
||||||
- class ChessGUIApp
|
|
||||||
- class ChessGUILauncher
|
|
||||||
- function getEngine
|
|
||||||
- function launch
|
|
||||||
- `modules/ui/src/main/scala/de/nowchess/ui/gui/GUIObserver.scala` — class GUIObserver
|
|
||||||
- `modules/ui/src/main/scala/de/nowchess/ui/gui/PieceSprites.scala`
|
|
||||||
- class PieceSprites
|
|
||||||
- function loadPieceImage
|
|
||||||
- class SquareColors
|
|
||||||
- `modules/ui/src/main/scala/de/nowchess/ui/terminal/TerminalUI.scala` — class TerminalUI, function start
|
|
||||||
- `modules/ui/src/main/scala/de/nowchess/ui/utils/PieceUnicode.scala` — function unicode
|
|
||||||
- `modules/ui/src/main/scala/de/nowchess/ui/utils/Renderer.scala` — class Renderer, function render
|
|
||||||
|
|||||||
@@ -0,0 +1,198 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>NowChessSystems — codesight report</title>
|
||||||
|
<style>
|
||||||
|
*{margin:0;padding:0;box-sizing:border-box}
|
||||||
|
:root{--bg:#0a0a0f;--card:#12121a;--border:#1e1e2e;--text:#e0e0e8;--muted:#6b6b80;--accent:#6366f1;--accent2:#22d3ee;--green:#22c55e;--orange:#f59e0b;--red:#ef4444;--pink:#ec4899}
|
||||||
|
body{background:var(--bg);color:var(--text);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;padding:2rem;max-width:1400px;margin:0 auto;line-height:1.6}
|
||||||
|
h1{font-size:2.5rem;font-weight:800;background:linear-gradient(135deg,var(--accent),var(--accent2));-webkit-background-clip:text;-webkit-text-fill-color:transparent;margin-bottom:.25rem}
|
||||||
|
.subtitle{color:var(--muted);font-size:1rem;margin-bottom:2rem}
|
||||||
|
.stack-badge{display:inline-block;background:var(--card);border:1px solid var(--border);border-radius:6px;padding:2px 10px;font-size:.85rem;color:var(--accent2);margin:0 4px 4px 0}
|
||||||
|
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:1rem;margin:2rem 0}
|
||||||
|
.stat{background:var(--card);border:1px solid var(--border);border-radius:12px;padding:1.25rem;text-align:center}
|
||||||
|
.stat-value{font-size:2rem;font-weight:800;background:linear-gradient(135deg,var(--accent),var(--accent2));-webkit-background-clip:text;-webkit-text-fill-color:transparent}
|
||||||
|
.stat-label{color:var(--muted);font-size:.85rem;margin-top:.25rem}
|
||||||
|
.token-hero{background:linear-gradient(135deg,#1a1a2e,#16213e);border:1px solid var(--accent);border-radius:16px;padding:2rem;margin:2rem 0;text-align:center}
|
||||||
|
.token-saved{font-size:3rem;font-weight:900;color:var(--green)}
|
||||||
|
.token-detail{color:var(--muted);font-size:.9rem;margin-top:.5rem}
|
||||||
|
.section{margin:2.5rem 0}
|
||||||
|
.section h2{font-size:1.4rem;font-weight:700;margin-bottom:1rem;padding-bottom:.5rem;border-bottom:1px solid var(--border)}
|
||||||
|
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:1rem}
|
||||||
|
.card{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:1rem;transition:border-color .2s}
|
||||||
|
.card:hover{border-color:var(--accent)}
|
||||||
|
.card-title{font-weight:700;font-size:1rem;margin-bottom:.5rem}
|
||||||
|
.card-meta{color:var(--muted);font-size:.8rem}
|
||||||
|
.tag{display:inline-block;background:rgba(99,102,241,.15);color:var(--accent);border-radius:4px;padding:1px 6px;font-size:.75rem;margin:1px}
|
||||||
|
.tag-auth{background:rgba(239,68,68,.15);color:var(--red)}
|
||||||
|
.tag-db{background:rgba(34,211,238,.15);color:var(--accent2)}
|
||||||
|
.tag-ai{background:rgba(236,72,153,.15);color:var(--pink)}
|
||||||
|
.tag-payment{background:rgba(245,158,11,.15);color:var(--orange)}
|
||||||
|
.tag-email{background:rgba(34,197,94,.15);color:var(--green)}
|
||||||
|
.tag-queue{background:rgba(168,85,247,.15);color:#a855f7}
|
||||||
|
.tag-cache{background:rgba(245,158,11,.15);color:var(--orange)}
|
||||||
|
.method{font-weight:700;font-size:.8rem;padding:2px 6px;border-radius:4px;margin-right:6px}
|
||||||
|
.method-GET{background:rgba(34,197,94,.2);color:var(--green)}
|
||||||
|
.method-POST{background:rgba(99,102,241,.2);color:var(--accent)}
|
||||||
|
.method-PUT{background:rgba(245,158,11,.2);color:var(--orange)}
|
||||||
|
.method-PATCH{background:rgba(245,158,11,.2);color:var(--orange)}
|
||||||
|
.method-DELETE{background:rgba(239,68,68,.2);color:var(--red)}
|
||||||
|
.method-ALL{background:rgba(107,107,128,.2);color:var(--muted)}
|
||||||
|
.route-path{font-family:'Fira Code',monospace;font-size:.9rem}
|
||||||
|
.route-contract{color:var(--muted);font-size:.8rem;font-style:italic;margin-left:.5rem}
|
||||||
|
.field{display:flex;gap:.5rem;padding:3px 0;font-size:.9rem}
|
||||||
|
.field-name{font-family:monospace;color:var(--accent2)}
|
||||||
|
.field-type{color:var(--muted);font-family:monospace}
|
||||||
|
.field-flags{display:flex;gap:3px}
|
||||||
|
.flag{font-size:.7rem;padding:0 4px;border-radius:3px;background:rgba(99,102,241,.1);color:var(--accent)}
|
||||||
|
.flag-pk{background:rgba(245,158,11,.2);color:var(--orange)}
|
||||||
|
.flag-fk{background:rgba(34,211,238,.2);color:var(--accent2)}
|
||||||
|
.flag-unique{background:rgba(236,72,153,.2);color:var(--pink)}
|
||||||
|
.hot-bar{height:8px;background:linear-gradient(90deg,var(--accent),var(--accent2));border-radius:4px;margin-top:4px}
|
||||||
|
.component-props{color:var(--muted);font-size:.85rem}
|
||||||
|
.badge-client{background:rgba(34,197,94,.15);color:var(--green);font-size:.75rem;padding:1px 6px;border-radius:4px}
|
||||||
|
.badge-server{background:rgba(99,102,241,.15);color:var(--accent);font-size:.75rem;padding:1px 6px;border-radius:4px}
|
||||||
|
.env-required{color:var(--red);font-weight:600;font-size:.8rem}
|
||||||
|
.env-default{color:var(--green);font-size:.8rem}
|
||||||
|
.footer{text-align:center;color:var(--muted);margin-top:4rem;padding-top:2rem;border-top:1px solid var(--border);font-size:.85rem}
|
||||||
|
.footer a{color:var(--accent);text-decoration:none}
|
||||||
|
table{width:100%;border-collapse:collapse}
|
||||||
|
table td,table th{padding:8px 12px;text-align:left;border-bottom:1px solid var(--border);font-size:.9rem}
|
||||||
|
table th{color:var(--muted);font-size:.8rem;font-weight:600;text-transform:uppercase}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1>NowChessSystems</h1>
|
||||||
|
<div class="subtitle">AI Context Map — generated by codesight</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<span class="stack-badge">raw-http</span>
|
||||||
|
|
||||||
|
<span class="stack-badge">unknown</span>
|
||||||
|
<span class="stack-badge">scala</span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="token-hero">
|
||||||
|
<div class="token-saved">~20,573 tokens saved</div>
|
||||||
|
<div class="token-detail">
|
||||||
|
Output: 5,297 tokens — Exploration cost without codesight: ~25,870 tokens — 149 files scanned
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stats">
|
||||||
|
<div class="stat"><div class="stat-value">0</div><div class="stat-label">Routes</div></div>
|
||||||
|
<div class="stat"><div class="stat-value">0</div><div class="stat-label">Models</div></div>
|
||||||
|
<div class="stat"><div class="stat-value">0</div><div class="stat-label">Components</div></div>
|
||||||
|
<div class="stat"><div class="stat-value">63</div><div class="stat-label">Libraries</div></div>
|
||||||
|
<div class="stat"><div class="stat-value">1</div><div class="stat-label">Env Vars</div></div>
|
||||||
|
<div class="stat"><div class="stat-value">1</div><div class="stat-label">Middleware</div></div>
|
||||||
|
<div class="stat"><div class="stat-value">383</div><div class="stat-label">Import Links</div></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<h2>Dependency Hot Files</h2>
|
||||||
|
<div class="grid">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title" style="font-size:.9rem">modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala</div>
|
||||||
|
<div class="card-meta">imported by 64 files</div>
|
||||||
|
<div class="hot-bar" style="width:100%"></div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title" style="font-size:.9rem">modules/api/src/main/scala/de/nowchess/api/move/Move.scala</div>
|
||||||
|
<div class="card-meta">imported by 44 files</div>
|
||||||
|
<div class="hot-bar" style="width:69%"></div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title" style="font-size:.9rem">modules/api/src/main/scala/de/nowchess/api/board/Square.scala</div>
|
||||||
|
<div class="card-meta">imported by 40 files</div>
|
||||||
|
<div class="hot-bar" style="width:63%"></div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title" style="font-size:.9rem">modules/api/src/main/scala/de/nowchess/api/board/Color.scala</div>
|
||||||
|
<div class="card-meta">imported by 35 files</div>
|
||||||
|
<div class="hot-bar" style="width:55%"></div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title" style="font-size:.9rem">modules/api/src/main/scala/de/nowchess/api/board/Board.scala</div>
|
||||||
|
<div class="card-meta">imported by 19 files</div>
|
||||||
|
<div class="hot-bar" style="width:30%"></div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title" style="font-size:.9rem">modules/api/src/main/scala/de/nowchess/api/board/Piece.scala</div>
|
||||||
|
<div class="card-meta">imported by 18 files</div>
|
||||||
|
<div class="hot-bar" style="width:28%"></div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title" style="font-size:.9rem">modules/api/src/main/scala/de/nowchess/api/board/PieceType.scala</div>
|
||||||
|
<div class="card-meta">imported by 17 files</div>
|
||||||
|
<div class="hot-bar" style="width:27%"></div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title" style="font-size:.9rem">modules/rule/src/main/scala/de/nowchess/rules/sets/DefaultRules.scala</div>
|
||||||
|
<div class="card-meta">imported by 17 files</div>
|
||||||
|
<div class="hot-bar" style="width:27%"></div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title" style="font-size:.9rem">modules/rule/src/main/scala/de/nowchess/rules/RuleSet.scala</div>
|
||||||
|
<div class="card-meta">imported by 11 files</div>
|
||||||
|
<div class="hot-bar" style="width:17%"></div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title" style="font-size:.9rem">modules/io/src/main/scala/de/nowchess/io/fen/FenParser.scala</div>
|
||||||
|
<div class="card-meta">imported by 10 files</div>
|
||||||
|
<div class="hot-bar" style="width:16%"></div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title" style="font-size:.9rem">modules/api/src/main/scala/de/nowchess/api/board/CastlingRights.scala</div>
|
||||||
|
<div class="card-meta">imported by 9 files</div>
|
||||||
|
<div class="hot-bar" style="width:14%"></div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title" style="font-size:.9rem">modules/api/src/main/scala/de/nowchess/api/game/DrawReason.scala</div>
|
||||||
|
<div class="card-meta">imported by 7 files</div>
|
||||||
|
<div class="hot-bar" style="width:11%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<h2>Environment Variables</h2>
|
||||||
|
<table>
|
||||||
|
<tr><th>Variable</th><th>Status</th><th>Source</th></tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>STOCKFISH_PATH</code></td>
|
||||||
|
<td><span class="env-required">required</span></td>
|
||||||
|
<td class="card-meta">modules/bot/python/nnue.py</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<h2>Middleware</h2>
|
||||||
|
<div class="grid">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title">generate <span class="tag tag-custom">custom</span></div>
|
||||||
|
<div class="card-meta">modules/bot/python/src/generate.py</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
Generated by <a href="https://github.com/Houseofmvps/codesight">codesight</a> — see your codebase clearly
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -15,7 +15,6 @@
|
|||||||
<option value="$PROJECT_DIR$/modules/core" />
|
<option value="$PROJECT_DIR$/modules/core" />
|
||||||
<option value="$PROJECT_DIR$/modules/io" />
|
<option value="$PROJECT_DIR$/modules/io" />
|
||||||
<option value="$PROJECT_DIR$/modules/rule" />
|
<option value="$PROJECT_DIR$/modules/rule" />
|
||||||
<option value="$PROJECT_DIR$/modules/ui" />
|
|
||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
</GradleProjectSettings>
|
</GradleProjectSettings>
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="NowChessSystems.modules.core.main" type="QuarkusRunConfigurationType" factoryName="Quarkus" nameIsGenerated="true">
|
||||||
|
<module name="NowChessSystems.modules.core.main" />
|
||||||
|
<QsGradleRunConfiguration>
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$/modules/core" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list>
|
||||||
|
<option value="quarkusDev" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<ExternalSystemDebugDisabled>false</ExternalSystemDebugDisabled>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<RunAsTest>false</RunAsTest>
|
||||||
|
<GradleProfilingDisabled>false</GradleProfilingDisabled>
|
||||||
|
<GradleCoverageDisabled>false</GradleCoverageDisabled>
|
||||||
|
<profile>dev</profile>
|
||||||
|
</QsGradleRunConfiguration>
|
||||||
|
<method v="2">
|
||||||
|
<option name="Make" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
<option name="deprecationWarnings" value="true" />
|
<option name="deprecationWarnings" value="true" />
|
||||||
<option name="uncheckedWarnings" value="true" />
|
<option name="uncheckedWarnings" value="true" />
|
||||||
</profile>
|
</profile>
|
||||||
<profile name="Gradle 2" modules="NowChessSystems.modules.bot.main,NowChessSystems.modules.bot.scoverage,NowChessSystems.modules.bot.test,NowChessSystems.modules.core.main,NowChessSystems.modules.core.scoverage,NowChessSystems.modules.core.test,NowChessSystems.modules.io.main,NowChessSystems.modules.io.scoverage,NowChessSystems.modules.io.test,NowChessSystems.modules.rule.main,NowChessSystems.modules.rule.scoverage,NowChessSystems.modules.rule.test,NowChessSystems.modules.ui.main,NowChessSystems.modules.ui.scoverage,NowChessSystems.modules.ui.test">
|
<profile name="Gradle 2" modules="NowChessSystems.modules.bot.main,NowChessSystems.modules.bot.scoverage,NowChessSystems.modules.bot.test,NowChessSystems.modules.core.integrationTest,NowChessSystems.modules.core.main,NowChessSystems.modules.core.native-test,NowChessSystems.modules.core.quarkus-generated-sources,NowChessSystems.modules.core.quarkus-test-generated-sources,NowChessSystems.modules.core.scoverage,NowChessSystems.modules.core.test,NowChessSystems.modules.io.main,NowChessSystems.modules.io.scoverage,NowChessSystems.modules.io.test,NowChessSystems.modules.rule.main,NowChessSystems.modules.rule.scoverage,NowChessSystems.modules.rule.test,NowChessSystems.modules.ui.main,NowChessSystems.modules.ui.scoverage,NowChessSystems.modules.ui.test">
|
||||||
<option name="deprecationWarnings" value="true" />
|
<option name="deprecationWarnings" value="true" />
|
||||||
<option name="uncheckedWarnings" value="true" />
|
<option name="uncheckedWarnings" value="true" />
|
||||||
<parameters>
|
<parameters>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ Scala 3.5.1 · Gradle 9
|
|||||||
./test # Run all tests
|
./test # Run all tests
|
||||||
./coverage # Check coverage
|
./coverage # Check coverage
|
||||||
```
|
```
|
||||||
Try to stick to these commands for consistency.
|
Use consistently.
|
||||||
|
|
||||||
## Modules
|
## Modules
|
||||||
|
|
||||||
@@ -25,14 +25,14 @@ Try to stick to these commands for consistency.
|
|||||||
|
|
||||||
## Style
|
## Style
|
||||||
|
|
||||||
- Use immutable data and pure functions.
|
- Immutable data, pure functions.
|
||||||
- Keep functions under 30 lines. If you need "and" to describe it, split it.
|
- Functions under 30 lines. Need "and"? Split it.
|
||||||
- Keep cyclomatic complexity under 15.
|
- Cyclomatic complexity under 15.
|
||||||
- Avoid comments. Let names carry intent; comment only non-obvious algorithms.
|
- No comments. Names carry intent. Comment non-obvious algorithms only.
|
||||||
- Scan for duplicated logic before finishing. Extract it.
|
- Scan duplicated logic. Extract.
|
||||||
- Follow default Sonar style for Scala.
|
- Follow default Sonar style for Scala.
|
||||||
- Use `Option` or `Either` for fallible operations; avoid exceptions for control flow.
|
- `Option`/`Either` for fallible ops. Skip exceptions for control flow.
|
||||||
- Naming: types are PascalCase, functions/values are camelCase.
|
- Naming: types PascalCase, functions/values camelCase.
|
||||||
|
|
||||||
## Code Quality
|
## Code Quality
|
||||||
|
|
||||||
@@ -40,23 +40,23 @@ Try to stick to these commands for consistency.
|
|||||||
|
|
||||||
### Linters
|
### Linters
|
||||||
|
|
||||||
- **scalafmt** — enforces formatting; run `./gradlew spotlessScalaCheck` to check and `./gradlew spotlessScalaApply` to refactor.
|
- **scalafmt** — Enforces formatting. Check: `./gradlew spotlessScalaCheck`. Refactor: `./gradlew spotlessScalaApply`.
|
||||||
- **scalafix** — enforces style and detects unused imports/code; run `./gradlew scalafix` to apply rules.
|
- **scalafix** — Enforces style, detects unused imports/code. Run: `./gradlew scalafix`.
|
||||||
|
|
||||||
## Architecture Decisions
|
## Architecture Decisions
|
||||||
|
|
||||||
- **Immutable state as primary model:** GameContext (api) holds board, history, player state — immutable, passed through the system. Each move creates a new GameContext, enabling undo/redo without side effects.
|
- **Immutable state as primary model:** GameContext (api) holds board, history, player state—immutable throughout. Each move → new GameContext. Enables undo/redo without side effects.
|
||||||
- **Observer pattern for UI decoupling:** GameEngine publishes move/state events; CommandInvoker queues moves; UI listens to events, not polling. GameEngine never imports UI code.
|
- **Observer pattern for UI decoupling:** GameEngine publishes move/state events; CommandInvoker queues moves; UI listens (no polling). GameEngine never imports UI.
|
||||||
- **RuleSet trait encapsulates rules:** Move generation, check, castling, en passant all in RuleSet impl. GameEngine calls rules as a black box; rules don't know about the rest of core.
|
- **RuleSet trait encapsulates rules:** Move generation, check, castling, en passant all in RuleSet impl. GameEngine calls rules as black box; rules don't know rest of core.
|
||||||
- **Polyglot hash must follow spec index layout:** piece keys use interleaved mapping `(pieceType * 2 + colorBit)` with black=0/white=1, castling keys are `768..771`, en-passant file keys are `772..779` and are XORed only if side-to-move has a pawn that can capture en passant, side-to-move key is `780` for white.
|
- **Polyglot hash must follow spec index layout:** Piece keys use interleaved mapping `(pieceType * 2 + colorBit)` (black=0, white=1). Castling keys: `768..771`. En-passant file keys: `772..779`, XORed only if side-to-move has capturable en passant. Side-to-move key: `780` (white).
|
||||||
- **Alpha-beta uses sequential PV search by default:** parallel split was disabled because fixed-window futures removed pruning effectiveness; correctness and pruning quality take priority over speculative parallelism.
|
- **Alpha-beta uses sequential PV search by default:** Parallel split disabled (fixed-window futures removed pruning effectiveness). Sequential PV default. Correctness + pruning quality > speculative parallelism.
|
||||||
- **Search hash is updated incrementally per move:** bot search now updates Zobrist keys from parent hash with move deltas instead of recomputing piece scans at every node.
|
- **Search hash is updated incrementally per move:** Bot search updates Zobrist keys from parent hash with move deltas, not recomputing piece scans per node.
|
||||||
|
|
||||||
## Rules
|
## Rules
|
||||||
|
|
||||||
- **Tests are the spec.** Never modify tests to pass; modify requirements or code. Update tests only if requirements change.
|
- **Tests are the spec.** Don't modify to pass. Fix requirements/code. Update only if requirements change.
|
||||||
- Never read build folders. Ask permission if needed.
|
- Never read build folders. Ask permission if needed.
|
||||||
- Keep this file up to date with any important decisions or conventions.
|
- Keep file current with decisions + conventions.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -64,11 +64,9 @@ Try to stick to these commands for consistency.
|
|||||||
|
|
||||||
### Two-Step Rule (mandatory)
|
### Two-Step Rule (mandatory)
|
||||||
**Step 1 — Orient:** Use wiki articles to find WHERE things live.
|
**Step 1 — Orient:** Use wiki articles to find WHERE things live.
|
||||||
**Step 2 — Verify:** Read the actual source files listed in the wiki article BEFORE writing any code.
|
**Step 2 — Verify:** Read source files from wiki BEFORE coding.
|
||||||
|
|
||||||
Wiki articles are structural summaries extracted by AST. They show routes, models, and file locations.
|
Wiki = structural summaries (routes, models, file locations). No function logic, middleware internals, runtime behavior. Don't code from wiki alone—read sources.
|
||||||
They do NOT show full function logic, middleware internals, or dynamic runtime behavior.
|
|
||||||
**Never write or modify code based solely on wiki content — always read source files first.**
|
|
||||||
|
|
||||||
Read in order at session start:
|
Read in order at session start:
|
||||||
1. `.codesight/wiki/index.md` — orientation map (~200 tokens)
|
1. `.codesight/wiki/index.md` — orientation map (~200 tokens)
|
||||||
@@ -76,8 +74,7 @@ Read in order at session start:
|
|||||||
3. Domain article (e.g. `.codesight/wiki/auth.md`) → check "Source Files" section → read those files
|
3. Domain article (e.g. `.codesight/wiki/auth.md`) → check "Source Files" section → read those files
|
||||||
4. `.codesight/CODESIGHT.md` — full context map for deep exploration
|
4. `.codesight/CODESIGHT.md` — full context map for deep exploration
|
||||||
|
|
||||||
Routes marked `[inferred]` in wiki articles were detected via regex — verify against source before trusting.
|
`[inferred]` routes = regex-detected. Verify sources. ⚠ in wiki? Re-run `codesight --wiki`.
|
||||||
If any source file shows ⚠ in the wiki, re-run `codesight --wiki` before proceeding.
|
|
||||||
|
|
||||||
Or use the codesight MCP server for on-demand queries:
|
Or use the codesight MCP server for on-demand queries:
|
||||||
- `codesight_get_wiki_article` — read a specific wiki article by name
|
- `codesight_get_wiki_article` — read a specific wiki article by name
|
||||||
@@ -87,13 +84,13 @@ Or use the codesight MCP server for on-demand queries:
|
|||||||
- `codesight_get_blast_radius --file src/lib/db.ts` — impact analysis before changes
|
- `codesight_get_blast_radius --file src/lib/db.ts` — impact analysis before changes
|
||||||
- `codesight_get_schema --model users` — specific model details
|
- `codesight_get_schema --model users` — specific model details
|
||||||
|
|
||||||
Only open specific files after consulting codesight context. This saves ~16.893 tokens per conversation.
|
Consult codesight context first. Saves ~16.893 tokens/conversation.
|
||||||
|
|
||||||
## graphify
|
## graphify
|
||||||
|
|
||||||
This project has a graphify knowledge graph at graphify-out/.
|
graphify knowledge graph at graphify-out/.
|
||||||
|
|
||||||
Rules:
|
Rules:
|
||||||
- Before answering architecture or codebase questions, read graphify-out/GRAPH_REPORT.md for god nodes and community structure
|
- Architecture/codebase questions? Read graphify-out/GRAPH_REPORT.md (god nodes, communities).
|
||||||
- If graphify-out/wiki/index.md exists, navigate it instead of reading raw files
|
- graphify-out/wiki/index.md exists? Use it (not raw files).
|
||||||
- After modifying code files in this session, run `python3 -c "from graphify.watch import _rebuild_code; from pathlib import Path; _rebuild_code(Path('.'))"` to keep the graph current
|
- Code modified? Run `python3 -c "from graphify.watch import _rebuild_code; from pathlib import Path; _rebuild_code(Path('.'))"` to sync graph.
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
# Now-Chess
|
||||||
|
|
||||||
|
Scala 3.5.1 · Gradle 9
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
```
|
||||||
|
./clean # Clear build dirs — only when necessary
|
||||||
|
./compile # Compile all modules — always run
|
||||||
|
./test # Run all tests
|
||||||
|
./coverage # Check coverage
|
||||||
|
```
|
||||||
|
Try to stick to these commands for consistency.
|
||||||
|
|
||||||
|
## Modules
|
||||||
|
|
||||||
|
| Module | Role | Depends on |
|
||||||
|
|--------|------|-----------|
|
||||||
|
| `api` | Model / shared types | (none) |
|
||||||
|
| `core` | Primary business logic | api, rule |
|
||||||
|
| `rule` | Game rules | api |
|
||||||
|
| `bot` | Bots and AI | api,rule,io |
|
||||||
|
| `io` | Export formats | api, core |
|
||||||
|
| `ui` | Entrypoint & UI | core, io |
|
||||||
|
|
||||||
|
## Style
|
||||||
|
|
||||||
|
- Use immutable data and pure functions.
|
||||||
|
- Keep functions under 30 lines. If you need "and" to describe it, split it.
|
||||||
|
- Keep cyclomatic complexity under 15.
|
||||||
|
- Avoid comments. Let names carry intent; comment only non-obvious algorithms.
|
||||||
|
- Scan for duplicated logic before finishing. Extract it.
|
||||||
|
- Follow default Sonar style for Scala.
|
||||||
|
- Use `Option` or `Either` for fallible operations; avoid exceptions for control flow.
|
||||||
|
- Naming: types are PascalCase, functions/values are camelCase.
|
||||||
|
|
||||||
|
## Code Quality
|
||||||
|
|
||||||
|
- **Coverage:** 100% condition coverage required in `api`, `core`, `rule`, `io` (mandatory); `ui` exempt.
|
||||||
|
|
||||||
|
### Linters
|
||||||
|
|
||||||
|
- **scalafmt** — enforces formatting; run `./gradlew spotlessScalaCheck` to check and `./gradlew spotlessScalaApply` to refactor.
|
||||||
|
- **scalafix** — enforces style and detects unused imports/code; run `./gradlew scalafix` to apply rules.
|
||||||
|
|
||||||
|
## Architecture Decisions
|
||||||
|
|
||||||
|
- **Immutable state as primary model:** GameContext (api) holds board, history, player state — immutable, passed through the system. Each move creates a new GameContext, enabling undo/redo without side effects.
|
||||||
|
- **Observer pattern for UI decoupling:** GameEngine publishes move/state events; CommandInvoker queues moves; UI listens to events, not polling. GameEngine never imports UI code.
|
||||||
|
- **RuleSet trait encapsulates rules:** Move generation, check, castling, en passant all in RuleSet impl. GameEngine calls rules as a black box; rules don't know about the rest of core.
|
||||||
|
- **Polyglot hash must follow spec index layout:** piece keys use interleaved mapping `(pieceType * 2 + colorBit)` with black=0/white=1, castling keys are `768..771`, en-passant file keys are `772..779` and are XORed only if side-to-move has a pawn that can capture en passant, side-to-move key is `780` for white.
|
||||||
|
- **Alpha-beta uses sequential PV search by default:** parallel split was disabled because fixed-window futures removed pruning effectiveness; correctness and pruning quality take priority over speculative parallelism.
|
||||||
|
- **Search hash is updated incrementally per move:** bot search now updates Zobrist keys from parent hash with move deltas instead of recomputing piece scans at every node.
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
|
||||||
|
- **Tests are the spec.** Never modify tests to pass; modify requirements or code. Update tests only if requirements change.
|
||||||
|
- Never read build folders. Ask permission if needed.
|
||||||
|
- Keep this file up to date with any important decisions or conventions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Instructions for Claude Code
|
||||||
|
|
||||||
|
### Two-Step Rule (mandatory)
|
||||||
|
**Step 1 — Orient:** Use wiki articles to find WHERE things live.
|
||||||
|
**Step 2 — Verify:** Read the actual source files listed in the wiki article BEFORE writing any code.
|
||||||
|
|
||||||
|
Wiki articles are structural summaries extracted by AST. They show routes, models, and file locations.
|
||||||
|
They do NOT show full function logic, middleware internals, or dynamic runtime behavior.
|
||||||
|
**Never write or modify code based solely on wiki content — always read source files first.**
|
||||||
|
|
||||||
|
Read in order at session start:
|
||||||
|
1. `.codesight/wiki/index.md` — orientation map (~200 tokens)
|
||||||
|
2. `.codesight/wiki/overview.md` — architecture overview (~500 tokens)
|
||||||
|
3. Domain article (e.g. `.codesight/wiki/auth.md`) → check "Source Files" section → read those files
|
||||||
|
4. `.codesight/CODESIGHT.md` — full context map for deep exploration
|
||||||
|
|
||||||
|
Routes marked `[inferred]` in wiki articles were detected via regex — verify against source before trusting.
|
||||||
|
If any source file shows ⚠ in the wiki, re-run `codesight --wiki` before proceeding.
|
||||||
|
|
||||||
|
Or use the codesight MCP server for on-demand queries:
|
||||||
|
- `codesight_get_wiki_article` — read a specific wiki article by name
|
||||||
|
- `codesight_get_wiki_index` — get the wiki index
|
||||||
|
- `codesight_get_summary` — quick project overview
|
||||||
|
- `codesight_get_routes --prefix /api/users` — filtered routes
|
||||||
|
- `codesight_get_blast_radius --file src/lib/db.ts` — impact analysis before changes
|
||||||
|
- `codesight_get_schema --model users` — specific model details
|
||||||
|
|
||||||
|
Only open specific files after consulting codesight context. This saves ~16.893 tokens per conversation.
|
||||||
|
|
||||||
|
## graphify
|
||||||
|
|
||||||
|
This project has a graphify knowledge graph at graphify-out/.
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
- Before answering architecture or codebase questions, read graphify-out/GRAPH_REPORT.md for god nodes and community structure
|
||||||
|
- If graphify-out/wiki/index.md exists, navigate it instead of reading raw files
|
||||||
|
- After modifying code files in this session, run `python3 -c "from graphify.watch import _rebuild_code; from pathlib import Path; _rebuild_code(Path('.'))"` to keep the graph current
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"version": "1",
|
||||||
|
"name": "NowChess API",
|
||||||
|
"type": "collection",
|
||||||
|
"ignore": []
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
meta {
|
||||||
|
name: Offer Draw
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
method: POST
|
||||||
|
url: {{baseUrl}}/api/board/game/{{gameId}}/draw/offer
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
meta {
|
||||||
|
name: Accept Draw
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
method: POST
|
||||||
|
url: {{baseUrl}}/api/board/game/{{gameId}}/draw/accept
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
meta {
|
||||||
|
name: Decline Draw
|
||||||
|
type: http
|
||||||
|
seq: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
method: POST
|
||||||
|
url: {{baseUrl}}/api/board/game/{{gameId}}/draw/decline
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
meta {
|
||||||
|
name: Claim Draw
|
||||||
|
type: http
|
||||||
|
seq: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
method: POST
|
||||||
|
url: {{baseUrl}}/api/board/game/{{gameId}}/draw/claim
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
meta {
|
||||||
|
name: draw
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
vars {
|
||||||
|
baseUrl: http://localhost:8080
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
meta {
|
||||||
|
name: Export FEN
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
method: GET
|
||||||
|
url: {{baseUrl}}/api/board/game/{{gameId}}/export/fen
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
meta {
|
||||||
|
name: Export PGN
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
method: GET
|
||||||
|
url: {{baseUrl}}/api/board/game/{{gameId}}/export/pgn
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
meta {
|
||||||
|
name: export
|
||||||
|
seq: 6
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
meta {
|
||||||
|
name: Create Game
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
method: POST
|
||||||
|
url: {{baseUrl}}/api/board/game
|
||||||
|
body: json
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"white": {"id": "p1", "displayName": "Alice"},
|
||||||
|
"black": {"id": "p2", "displayName": "Bob"}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
meta {
|
||||||
|
name: Get Game
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
method: GET
|
||||||
|
url: {{baseUrl}}/api/board/game/{{gameId}}
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
meta {
|
||||||
|
name: Stream Game
|
||||||
|
type: http
|
||||||
|
seq: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/api/board/game/{{gameId}}/stream
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
Accept: application/x-ndjson
|
||||||
|
}
|
||||||
|
|
||||||
|
vars:pre-request {
|
||||||
|
gameId: tjOgyEcS
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
meta {
|
||||||
|
name: Resign
|
||||||
|
type: http
|
||||||
|
seq: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
method: POST
|
||||||
|
url: {{baseUrl}}/api/board/game/{{gameId}}/resign
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
meta {
|
||||||
|
name: game
|
||||||
|
seq: 3
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
meta {
|
||||||
|
name: Import FEN
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
method: POST
|
||||||
|
url: {{baseUrl}}/api/board/game/import/fen
|
||||||
|
body: json
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"fen": "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1",
|
||||||
|
"white": {"id": "p1", "displayName": "Alice"},
|
||||||
|
"black": {"id": "p2", "displayName": "Bob"}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
meta {
|
||||||
|
name: Import PGN
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
method: POST
|
||||||
|
url: {{baseUrl}}/api/board/game/import/pgn
|
||||||
|
body: json
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
|
|
||||||
|
headers {
|
||||||
|
Content-Type: application/json
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"pgn": "1. e4 e5 2. Nf3 Nc6 *"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
meta {
|
||||||
|
name: import
|
||||||
|
seq: 5
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
meta {
|
||||||
|
name: Make Move
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: {{baseUrl}}/api/board/game/{{gameId}}/move/b1c3
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
|
|
||||||
|
vars:pre-request {
|
||||||
|
gameId: tjOgyEcS
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
meta {
|
||||||
|
name: Get Legal Moves
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{baseUrl}}/api/board/game/{{gameId}}/moves
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
|
|
||||||
|
params:query {
|
||||||
|
square: e2
|
||||||
|
}
|
||||||
|
|
||||||
|
vars:pre-request {
|
||||||
|
gameId: tjOgyEcS
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
meta {
|
||||||
|
name: Undo Move
|
||||||
|
type: http
|
||||||
|
seq: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
method: POST
|
||||||
|
url: {{baseUrl}}/api/board/game/{{gameId}}/undo
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
meta {
|
||||||
|
name: Redo Move
|
||||||
|
type: http
|
||||||
|
seq: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
method: POST
|
||||||
|
url: {{baseUrl}}/api/board/game/{{gameId}}/redo
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
meta {
|
||||||
|
name: move
|
||||||
|
}
|
||||||
@@ -8,6 +8,49 @@ plugins {
|
|||||||
group = "de.nowchess"
|
group = "de.nowchess"
|
||||||
version = "1.0-SNAPSHOT"
|
version = "1.0-SNAPSHOT"
|
||||||
|
|
||||||
|
// Canonical coverage exclusions — glob patterns consumed by Sonar directly;
|
||||||
|
// converted to scoverage regexes via globToScoverageRegex for instrumentation-time exclusion.
|
||||||
|
val coverageExclusions = listOf(
|
||||||
|
// UI renders JavaFX components; headless test environments cannot exercise rendering paths
|
||||||
|
"modules/ui/**",
|
||||||
|
// FastParse macro-generated combinators produce synthetic branches that scoverage marks as uncovered
|
||||||
|
"modules/io/src/main/scala/de/nowchess/io/fen/FenParserFastParse*",
|
||||||
|
// NNUE inference pipeline — coverage requires a trained model file not present in CI
|
||||||
|
"**/bot/**/NNUE.scala",
|
||||||
|
"**/bot/**/NNUEBot.scala",
|
||||||
|
"**/bot/**/EvaluationNNUE.scala",
|
||||||
|
// NBAI binary format loader/writer — error paths require crafted corrupt files; migrator is a one-shot tool
|
||||||
|
"**/bot/**/NbaiLoader.scala",
|
||||||
|
"**/bot/**/NbaiModel.scala",
|
||||||
|
"**/bot/**/NbaiMigrator.scala",
|
||||||
|
"**/bot/**/NbaiWriter.scala",
|
||||||
|
// PolyglotBook — binary I/O and dead-code guards (bit-masked fields can never exceed valid range)
|
||||||
|
"**/bot/**/PolyglotBook.scala",
|
||||||
|
"**/bot/**/MoveOrdering.scala",
|
||||||
|
"**/bot/**/AlphaBetaSearch.scala",
|
||||||
|
// DTO case class synthetic methods (Scala compiler-generated apply/$default params)
|
||||||
|
"**/api/src/main/scala/de/nowchess/api/dto/**Dto.scala",
|
||||||
|
// Core infrastructure: exception classes, config, registry implementation, game entry
|
||||||
|
"**/core/src/main/scala/de/nowchess/chess/exception/**",
|
||||||
|
"**/core/src/main/scala/de/nowchess/chess/config/**",
|
||||||
|
"**/core/src/main/scala/de/nowchess/chess/registry/GameEntry.scala",
|
||||||
|
"**/core/src/main/scala/de/nowchess/chess/registry/GameRegistryImpl.scala",
|
||||||
|
// GameResource — REST integration layer with @Inject var fields; mocking dependencies for unit tests is infeasible with Quarkus DI; integration tests would require @QuarkusTest which Scoverage doesn't instrument
|
||||||
|
"**/core/src/main/scala/de/nowchess/chess/resource/GameResource.scala"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Converts a Sonar-style glob to a scoverage regex (matched against full source path).
|
||||||
|
// Order matters: protect ** before converting lone *, escape dots last.
|
||||||
|
fun globToScoverageRegex(glob: String): String =
|
||||||
|
glob
|
||||||
|
.replace("**", "^@")
|
||||||
|
.replace("*", "[^/]*")
|
||||||
|
.replace(".", "\\.")
|
||||||
|
.replace("^@", ".*")
|
||||||
|
.let { ".*$it" }
|
||||||
|
|
||||||
|
extra["SCOVERAGE_EXCLUDED"] = coverageExclusions.map(::globToScoverageRegex)
|
||||||
|
|
||||||
sonar {
|
sonar {
|
||||||
properties {
|
properties {
|
||||||
property("sonar.projectKey", "Now-Chess-Systems")
|
property("sonar.projectKey", "Now-Chess-Systems")
|
||||||
@@ -22,26 +65,7 @@ sonar {
|
|||||||
}.joinToString(",")
|
}.joinToString(",")
|
||||||
|
|
||||||
property("sonar.scala.coverage.reportPaths", scoverageReports)
|
property("sonar.scala.coverage.reportPaths", scoverageReports)
|
||||||
property(
|
property("sonar.coverage.exclusions", coverageExclusions.joinToString(","))
|
||||||
"sonar.coverage.exclusions",
|
|
||||||
// UI renders JavaFX components; headless test environments cannot exercise rendering paths
|
|
||||||
"modules/ui/**," +
|
|
||||||
// FastParse macro-generated combinators produce synthetic branches that scoverage marks as uncovered
|
|
||||||
"modules/io/src/main/scala/de/nowchess/io/fen/FenParserFastParse*," +
|
|
||||||
// NNUE inference pipeline — coverage requires a trained model file not present in CI
|
|
||||||
"**/bot/**/NNUE.scala," +
|
|
||||||
"**/bot/**/NNUEBot.scala," +
|
|
||||||
"**/bot/**/EvaluationNNUE.scala," +
|
|
||||||
// NBAI binary format loader/writer — error paths require crafted corrupt files; migrator is a one-shot tool
|
|
||||||
"**/bot/**/NbaiLoader.scala," +
|
|
||||||
"**/bot/**/NbaiModel.scala," +
|
|
||||||
"**/bot/**/NbaiMigrator.scala," +
|
|
||||||
"**/bot/**/NbaiWriter.scala," +
|
|
||||||
// PolyglotBook — binary I/O and dead-code guards (bit-masked fields can never exceed valid range)
|
|
||||||
"**/bot/**/PolyglotBook.scala," +
|
|
||||||
"**/bot/**/MoveOrdering.scala," +
|
|
||||||
"**/bot/**/AlphaBetaSearch.scala"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#! /usr/bin/env bash
|
#! /usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
./gradlew test
|
# ./gradlew test
|
||||||
|
|
||||||
if [ "$#" -eq 0 ]; then
|
if [ "$#" -eq 0 ]; then
|
||||||
PYTHONUTF8=1 python3 jacoco-reporter/scoverage_coverage_gaps.py
|
PYTHONUTF8=1 python3 jacoco-reporter/scoverage_coverage_gaps.py
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
openapi: 3.0.3
|
openapi: 3.0.3
|
||||||
info:
|
info:
|
||||||
title: NowChess API
|
title: NowChess Board API
|
||||||
description: |
|
description: |
|
||||||
REST API for the NowChess application. Designed to feel familiar to users
|
REST API for the NowChess application. Designed to feel familiar to users
|
||||||
of the [lichess API](https://lichess.org/api).
|
of the [lichess API](https://lichess.org/api).
|
||||||
@@ -186,11 +186,8 @@ paths:
|
|||||||
currently to move.
|
currently to move.
|
||||||
|
|
||||||
For promotion moves include the target piece as the fifth character:
|
For promotion moves include the target piece as the fifth character:
|
||||||
`e7e8q`, `a2a1r`, etc.
|
`e7e8q`, `a2a1r`, etc. Promotion moves without the fifth character
|
||||||
|
are rejected with `400 INVALID_MOVE`.
|
||||||
If the move results in a pawn reaching the back rank and no promotion
|
|
||||||
character is supplied, the game enters `promotionPending` status and
|
|
||||||
the move is not yet applied — resubmit with the promotion character.
|
|
||||||
security:
|
security:
|
||||||
- bearerAuth: []
|
- bearerAuth: []
|
||||||
parameters:
|
parameters:
|
||||||
@@ -630,7 +627,6 @@ components:
|
|||||||
| `draw` | Draw agreed or claimed — game over |
|
| `draw` | Draw agreed or claimed — game over |
|
||||||
| `drawOffered` | Waiting for the opponent to accept or decline a draw offer |
|
| `drawOffered` | Waiting for the opponent to accept or decline a draw offer |
|
||||||
| `fiftyMoveAvailable` | Fifty-move rule threshold reached; active player may claim draw |
|
| `fiftyMoveAvailable` | Fifty-move rule threshold reached; active player may claim draw |
|
||||||
| `promotionPending` | A pawn reached the back rank; awaiting promotion piece selection |
|
|
||||||
| `insufficientMaterial` | Neither side has enough pieces to deliver checkmate — game over (draw) |
|
| `insufficientMaterial` | Neither side has enough pieces to deliver checkmate — game over (draw) |
|
||||||
enum:
|
enum:
|
||||||
- started
|
- started
|
||||||
@@ -641,7 +637,6 @@ components:
|
|||||||
- draw
|
- draw
|
||||||
- drawOffered
|
- drawOffered
|
||||||
- fiftyMoveAvailable
|
- fiftyMoveAvailable
|
||||||
- promotionPending
|
|
||||||
- insufficientMaterial
|
- insufficientMaterial
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Gradle properties
|
||||||
|
quarkusPluginId=io.quarkus
|
||||||
|
quarkusPluginVersion=3.32.4
|
||||||
|
quarkusPlatformGroupId=io.quarkus.platform
|
||||||
|
quarkusPlatformArtifactId=quarkus-bom
|
||||||
|
quarkusPlatformVersion=3.32.4
|
||||||
@@ -51,3 +51,12 @@
|
|||||||
* NCS-21 Write Scripts to automate certain tasks ([#15](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/15)) ([8051871](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/80518719d536a087d339fe02530825dc07f8b388))
|
* NCS-21 Write Scripts to automate certain tasks ([#15](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/15)) ([8051871](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/80518719d536a087d339fe02530825dc07f8b388))
|
||||||
* NCS-25 Add linters to keep quality up ([#27](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/27)) ([fd4e67d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fd4e67d4f782a7e955822d90cb909d0a81676fb2))
|
* NCS-25 Add linters to keep quality up ([#27](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/27)) ([fd4e67d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fd4e67d4f782a7e955822d90cb909d0a81676fb2))
|
||||||
* NCS-41 Bot Platform ([#33](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/33)) ([dceab08](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dceab0875e6d15f7d3958633cf5dd5b29a851b1d))
|
* NCS-41 Bot Platform ([#33](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/33)) ([dceab08](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dceab0875e6d15f7d3958633cf5dd5b29a851b1d))
|
||||||
|
## (2026-04-19)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* NCS-13 Implement Threefold Repetition ([#31](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/31)) ([767d305](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/767d3051a76c266050b6335774d66e2db2273c16))
|
||||||
|
* NCS-14 implemented insufficient moves rule ([#30](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/30)) ([b0399a4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b0399a4e489950083066c9538df9a84dcc7a4613))
|
||||||
|
* NCS-21 Write Scripts to automate certain tasks ([#15](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/15)) ([8051871](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/80518719d536a087d339fe02530825dc07f8b388))
|
||||||
|
* NCS-25 Add linters to keep quality up ([#27](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/27)) ([fd4e67d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fd4e67d4f782a7e955822d90cb909d0a81676fb2))
|
||||||
|
* NCS-41 Bot Platform ([#33](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/33)) ([dceab08](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dceab0875e6d15f7d3958633cf5dd5b29a851b1d))
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ version = "1.0-SNAPSHOT"
|
|||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val versions = rootProject.extra["VERSIONS"] as Map<String, String>
|
val versions = rootProject.extra["VERSIONS"] as Map<String, String>
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val scoverageExcluded = rootProject.extra["SCOVERAGE_EXCLUDED"] as List<String>
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@@ -19,6 +21,7 @@ scala {
|
|||||||
|
|
||||||
scoverage {
|
scoverage {
|
||||||
scoverageVersion.set(versions["SCOVERAGE"]!!)
|
scoverageVersion.set(versions["SCOVERAGE"]!!)
|
||||||
|
excludedFiles.set(scoverageExcluded)
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations.scoverage {
|
configurations.scoverage {
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package de.nowchess.api.dto
|
||||||
|
|
||||||
|
final case class ApiErrorDto(code: String, message: String, field: Option[String])
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package de.nowchess.api.dto
|
||||||
|
|
||||||
|
final case class CreateGameRequestDto(
|
||||||
|
white: Option[PlayerInfoDto],
|
||||||
|
black: Option[PlayerInfoDto],
|
||||||
|
)
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package de.nowchess.api.dto
|
||||||
|
|
||||||
|
final case class ErrorEventDto(`type`: String, error: ApiErrorDto)
|
||||||
|
|
||||||
|
object ErrorEventDto:
|
||||||
|
def apply(error: ApiErrorDto): ErrorEventDto = ErrorEventDto("error", error)
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package de.nowchess.api.dto
|
||||||
|
|
||||||
|
final case class GameFullDto(
|
||||||
|
gameId: String,
|
||||||
|
white: PlayerInfoDto,
|
||||||
|
black: PlayerInfoDto,
|
||||||
|
state: GameStateDto,
|
||||||
|
)
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package de.nowchess.api.dto
|
||||||
|
|
||||||
|
final case class GameFullEventDto(`type`: String, game: GameFullDto)
|
||||||
|
|
||||||
|
object GameFullEventDto:
|
||||||
|
def apply(game: GameFullDto): GameFullEventDto = GameFullEventDto("gameFull", game)
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package de.nowchess.api.dto
|
||||||
|
|
||||||
|
final case class GameStateDto(
|
||||||
|
fen: String,
|
||||||
|
pgn: String,
|
||||||
|
turn: String,
|
||||||
|
status: String,
|
||||||
|
winner: Option[String],
|
||||||
|
moves: List[String],
|
||||||
|
undoAvailable: Boolean,
|
||||||
|
redoAvailable: Boolean,
|
||||||
|
)
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package de.nowchess.api.dto
|
||||||
|
|
||||||
|
final case class GameStateEventDto(`type`: String, state: GameStateDto)
|
||||||
|
|
||||||
|
object GameStateEventDto:
|
||||||
|
def apply(state: GameStateDto): GameStateEventDto = GameStateEventDto("gameState", state)
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package de.nowchess.api.dto
|
||||||
|
|
||||||
|
final case class ImportFenRequestDto(
|
||||||
|
fen: String,
|
||||||
|
white: Option[PlayerInfoDto],
|
||||||
|
black: Option[PlayerInfoDto],
|
||||||
|
)
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package de.nowchess.api.dto
|
||||||
|
|
||||||
|
final case class ImportPgnRequestDto(pgn: String)
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package de.nowchess.api.dto
|
||||||
|
|
||||||
|
final case class LegalMoveDto(
|
||||||
|
from: String,
|
||||||
|
to: String,
|
||||||
|
uci: String,
|
||||||
|
moveType: String,
|
||||||
|
promotion: Option[String],
|
||||||
|
)
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package de.nowchess.api.dto
|
||||||
|
|
||||||
|
final case class LegalMovesResponseDto(moves: List[LegalMoveDto])
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package de.nowchess.api.dto
|
||||||
|
|
||||||
|
final case class OkResponseDto(ok: Boolean = true)
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package de.nowchess.api.dto
|
||||||
|
|
||||||
|
final case class PlayerInfoDto(id: String, displayName: String)
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=7
|
MINOR=8
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ version = "1.0-SNAPSHOT"
|
|||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val versions = rootProject.extra["VERSIONS"] as Map<String, String>
|
val versions = rootProject.extra["VERSIONS"] as Map<String, String>
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val scoverageExcluded = rootProject.extra["SCOVERAGE_EXCLUDED"] as List<String>
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@@ -26,16 +28,7 @@ scoverage {
|
|||||||
"de\\.nowchess\\.bot\\.util\\.PolyglotBook",
|
"de\\.nowchess\\.bot\\.util\\.PolyglotBook",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
excludedFiles.set(
|
excludedFiles.set(scoverageExcluded)
|
||||||
listOf(
|
|
||||||
".*NNUE\\.scala",
|
|
||||||
".*NNUEBot\\.scala",
|
|
||||||
".*NbaiLoader\\.scala",
|
|
||||||
".*NbaiMigrator\\.scala",
|
|
||||||
".*NbaiWriter\\.scala",
|
|
||||||
".*PolyglotBook\\.scala",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType<ScalaCompile> {
|
tasks.withType<ScalaCompile> {
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.gitignore
|
||||||
|
!build/*-runner
|
||||||
|
!build/*-runner.jar
|
||||||
|
!build/lib/*
|
||||||
|
!build/quarkus-app/*
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# Gradle
|
||||||
|
.gradle/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# Eclipse
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.settings/
|
||||||
|
bin/
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
.idea
|
||||||
|
*.ipr
|
||||||
|
*.iml
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# NetBeans
|
||||||
|
nb-configuration.xml
|
||||||
|
|
||||||
|
# Visual Studio Code
|
||||||
|
.vscode
|
||||||
|
.factorypath
|
||||||
|
|
||||||
|
# OSX
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Vim
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# patch
|
||||||
|
*.orig
|
||||||
|
*.rej
|
||||||
|
|
||||||
|
# Local environment
|
||||||
|
.env
|
||||||
|
|
||||||
|
# Plugin directory
|
||||||
|
/.quarkus/cli/plugins/
|
||||||
|
# TLS Certificates
|
||||||
|
.certs/
|
||||||
@@ -313,3 +313,31 @@
|
|||||||
* correct test board positions and captureOutput/withInput interaction ([f0481e2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f0481e2561b779df00925b46ee281dc36a795150))
|
* correct test board positions and captureOutput/withInput interaction ([f0481e2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f0481e2561b779df00925b46ee281dc36a795150))
|
||||||
* update main class path in build configuration and adjust VCS directory mapping ([7b1f8b1](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/7b1f8b117623d327232a1a92a8a44d18582e0189))
|
* update main class path in build configuration and adjust VCS directory mapping ([7b1f8b1](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/7b1f8b117623d327232a1a92a8a44d18582e0189))
|
||||||
* update move validation to check for king safety ([#13](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/13)) ([e5e20c5](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/e5e20c566e368b12ca1dc59680c34e9112bf6762))
|
* update move validation to check for king safety ([#13](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/13)) ([e5e20c5](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/e5e20c566e368b12ca1dc59680c34e9112bf6762))
|
||||||
|
## (2026-04-19)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add GameRules stub with PositionStatus enum ([76d4168](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/76d4168038de23e5d6083d4e8f0504fbf31d15a3))
|
||||||
|
* add MovedInCheck/Checkmate/Stalemate MoveResult variants (stub dispatch) ([8b7ec57](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/8b7ec57e5ea6ee1615a1883848a426dc07d26364))
|
||||||
|
* implement GameRules with isInCheck, legalMoves, gameStatus ([94a02ff](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/94a02ff6849436d9496c70a0f16c21666dae8e4e))
|
||||||
|
* implement legal castling ([#1](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/1)) ([00d326c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/00d326c1ba67711fbe180f04e1100c3f01dd0254))
|
||||||
|
* NCS-10 Implement Pawn Promotion ([#12](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/12)) ([13bfc16](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/13bfc16cfe25db78ec607db523ca6d993c13430c))
|
||||||
|
* NCS-11 50-move rule ([#9](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/9)) ([412ed98](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/412ed986a95703a3b282276540153480ceed229d))
|
||||||
|
* NCS-13 Implement Threefold Repetition ([#31](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/31)) ([767d305](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/767d3051a76c266050b6335774d66e2db2273c16))
|
||||||
|
* NCS-14 implemented insufficient moves rule ([#30](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/30)) ([b0399a4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b0399a4e489950083066c9538df9a84dcc7a4613))
|
||||||
|
* NCS-16 Core Separation via Patterns ([#10](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/10)) ([1361dfc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1361dfc89553b146864fb8ff3526cf12cf3f293a))
|
||||||
|
* NCS-17 Implement basic ScalaFX UI ([#14](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/14)) ([3ff8031](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ff80318b4f16c59733a46498581a5c27f048287))
|
||||||
|
* NCS-21 Write Scripts to automate certain tasks ([#15](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/15)) ([8051871](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/80518719d536a087d339fe02530825dc07f8b388))
|
||||||
|
* NCS-25 Add linters to keep quality up ([#27](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/27)) ([fd4e67d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fd4e67d4f782a7e955822d90cb909d0a81676fb2))
|
||||||
|
* NCS-40 Rework Draw System ([#34](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/34)) ([0091d50](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0091d50467e9f955f23570128b96c977c01bc51b))
|
||||||
|
* NCS-41 Bot Platform ([#33](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/33)) ([dceab08](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dceab0875e6d15f7d3958633cf5dd5b29a851b1d))
|
||||||
|
* NCS-6 Implementing FEN & PGN ([#7](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/7)) ([f28e69d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f28e69dc181416aa2f221fdc4b45c2cda5efbf07))
|
||||||
|
* NCS-9 En passant implementation ([#8](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/8)) ([919beb3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/919beb3b4bfa8caf2f90976a415fe9b19b7e9747))
|
||||||
|
* wire check/checkmate/stalemate into processMove and gameLoop ([5264a22](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5264a225418b885c5e6ea6411b96f85e38837f6c))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add missing kings to gameLoop capture test board ([aedd787](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/aedd787b77203c2af934751dba7b784eaf165032))
|
||||||
|
* correct test board positions and captureOutput/withInput interaction ([f0481e2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f0481e2561b779df00925b46ee281dc36a795150))
|
||||||
|
* update main class path in build configuration and adjust VCS directory mapping ([7b1f8b1](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/7b1f8b117623d327232a1a92a8a44d18582e0189))
|
||||||
|
* update move validation to check for king safety ([#13](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/13)) ([e5e20c5](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/e5e20c566e368b12ca1dc59680c34e9112bf6762))
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("scala")
|
id("scala")
|
||||||
id("org.scoverage") version "8.1"
|
id("org.scoverage") version "8.1"
|
||||||
|
id("io.quarkus")
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "de.nowchess"
|
group = "de.nowchess"
|
||||||
@@ -8,6 +9,8 @@ version = "1.0-SNAPSHOT"
|
|||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val versions = rootProject.extra["VERSIONS"] as Map<String, String>
|
val versions = rootProject.extra["VERSIONS"] as Map<String, String>
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val scoverageExcluded = rootProject.extra["SCOVERAGE_EXCLUDED"] as List<String>
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@@ -19,12 +22,18 @@ scala {
|
|||||||
|
|
||||||
scoverage {
|
scoverage {
|
||||||
scoverageVersion.set(versions["SCOVERAGE"]!!)
|
scoverageVersion.set(versions["SCOVERAGE"]!!)
|
||||||
|
excludedFiles.set(scoverageExcluded)
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType<ScalaCompile> {
|
tasks.withType<ScalaCompile> {
|
||||||
scalaCompileOptions.additionalParameters = listOf("-encoding", "UTF-8")
|
scalaCompileOptions.additionalParameters = listOf("-encoding", "UTF-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val quarkusPlatformGroupId: String by project
|
||||||
|
val quarkusPlatformArtifactId: String by project
|
||||||
|
val quarkusPlatformVersion: String by project
|
||||||
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
implementation("org.scala-lang:scala3-compiler_3") {
|
implementation("org.scala-lang:scala3-compiler_3") {
|
||||||
@@ -43,19 +52,59 @@ dependencies {
|
|||||||
implementation(project(":modules:rule"))
|
implementation(project(":modules:rule"))
|
||||||
implementation(project(":modules:bot"))
|
implementation(project(":modules:bot"))
|
||||||
|
|
||||||
|
|
||||||
|
implementation(enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}"))
|
||||||
|
implementation("io.quarkus:quarkus-rest")
|
||||||
|
implementation("io.quarkus:quarkus-hibernate-orm")
|
||||||
|
implementation("io.quarkus:quarkus-rest-client-jackson")
|
||||||
|
implementation("io.quarkus:quarkus-rest-client")
|
||||||
|
implementation("io.quarkus:quarkus-rest-jackson")
|
||||||
|
implementation("io.quarkus:quarkus-config-yaml")
|
||||||
|
implementation("io.quarkus:quarkus-smallrye-fault-tolerance")
|
||||||
|
implementation("io.quarkus:quarkus-smallrye-jwt")
|
||||||
|
implementation("io.quarkus:quarkus-smallrye-health")
|
||||||
|
implementation("io.quarkus:quarkus-micrometer")
|
||||||
|
implementation("io.quarkus:quarkus-arc")
|
||||||
|
|
||||||
|
implementation("com.fasterxml.jackson.module:jackson-module-scala_3:${versions["JACKSON_SCALA"]!!}")
|
||||||
|
|
||||||
|
|
||||||
testImplementation(platform("org.junit:junit-bom:5.13.4"))
|
testImplementation(platform("org.junit:junit-bom:5.13.4"))
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||||
testImplementation("org.scalatest:scalatest_3:${versions["SCALATEST"]!!}")
|
testImplementation("org.scalatest:scalatest_3:${versions["SCALATEST"]!!}")
|
||||||
testImplementation("co.helmethair:scalatest-junit-runner:${versions["SCALATEST_JUNIT"]!!}")
|
testImplementation("co.helmethair:scalatest-junit-runner:${versions["SCALATEST_JUNIT"]!!}")
|
||||||
|
testImplementation("io.quarkus:quarkus-junit5")
|
||||||
|
testImplementation("io.rest-assured:rest-assured")
|
||||||
|
|
||||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||||
|
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations.matching { !it.name.startsWith("scoverage") }.configureEach {
|
||||||
|
resolutionStrategy.force("org.scala-lang:scala-library:${versions["SCALA_LIBRARY"]!!}")
|
||||||
|
}
|
||||||
|
configurations.scoverage {
|
||||||
|
resolutionStrategy.eachDependency {
|
||||||
|
if (requested.group == "org.scoverage" && requested.name.startsWith("scalac-scoverage-plugin_")) {
|
||||||
|
useTarget("${requested.group}:scalac-scoverage-plugin_2.13.16:2.3.0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<JavaCompile> {
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
options.compilerArgs.add("-parameters")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<Jar>().configureEach {
|
||||||
|
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.test {
|
tasks.test {
|
||||||
useJUnitPlatform {
|
useJUnitPlatform {
|
||||||
includeEngines("scalatest")
|
includeEngines("scalatest", "junit-jupiter")
|
||||||
testLogging {
|
testLogging {
|
||||||
events("skipped", "failed")
|
events("passed", "skipped", "failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finalizedBy(tasks.reportScoverage)
|
finalizedBy(tasks.reportScoverage)
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
####
|
||||||
|
# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
|
||||||
|
#
|
||||||
|
# Before building the container image run:
|
||||||
|
#
|
||||||
|
# ./gradlew build
|
||||||
|
#
|
||||||
|
# Then, build the image with:
|
||||||
|
#
|
||||||
|
# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/backcore-jvm .
|
||||||
|
#
|
||||||
|
# Then run the container using:
|
||||||
|
#
|
||||||
|
# docker run -i --rm -p 8080:8080 quarkus/backcore-jvm
|
||||||
|
#
|
||||||
|
# If you want to include the debug port into your docker image
|
||||||
|
# you will have to expose the debug port (default 5005 being the default) like this : EXPOSE 8080 5005.
|
||||||
|
# Additionally you will have to set -e JAVA_DEBUG=true and -e JAVA_DEBUG_PORT=*:5005
|
||||||
|
# when running the container
|
||||||
|
#
|
||||||
|
# Then run the container using :
|
||||||
|
#
|
||||||
|
# docker run -i --rm -p 8080:8080 quarkus/backcore-jvm
|
||||||
|
#
|
||||||
|
# This image uses the `run-java.sh` script to run the application.
|
||||||
|
# This scripts computes the command line to execute your Java application, and
|
||||||
|
# includes memory/GC tuning.
|
||||||
|
# You can configure the behavior using the following environment properties:
|
||||||
|
# - JAVA_OPTS: JVM options passed to the `java` command (example: "-verbose:class") - Be aware that this will override
|
||||||
|
# the default JVM options, use `JAVA_OPTS_APPEND` to append options
|
||||||
|
# - JAVA_OPTS_APPEND: User specified Java options to be appended to generated options
|
||||||
|
# in JAVA_OPTS (example: "-Dsome.property=foo")
|
||||||
|
# - JAVA_MAX_MEM_RATIO: Is used when no `-Xmx` option is given in JAVA_OPTS. This is
|
||||||
|
# used to calculate a default maximal heap memory based on a containers restriction.
|
||||||
|
# If used in a container without any memory constraints for the container then this
|
||||||
|
# option has no effect. If there is a memory constraint then `-Xmx` is set to a ratio
|
||||||
|
# of the container available memory as set here. The default is `50` which means 50%
|
||||||
|
# of the available memory is used as an upper boundary. You can skip this mechanism by
|
||||||
|
# setting this value to `0` in which case no `-Xmx` option is added.
|
||||||
|
# - JAVA_INITIAL_MEM_RATIO: Is used when no `-Xms` option is given in JAVA_OPTS. This
|
||||||
|
# is used to calculate a default initial heap memory based on the maximum heap memory.
|
||||||
|
# If used in a container without any memory constraints for the container then this
|
||||||
|
# option has no effect. If there is a memory constraint then `-Xms` is set to a ratio
|
||||||
|
# of the `-Xmx` memory as set here. The default is `25` which means 25% of the `-Xmx`
|
||||||
|
# is used as the initial heap size. You can skip this mechanism by setting this value
|
||||||
|
# to `0` in which case no `-Xms` option is added (example: "25")
|
||||||
|
# - JAVA_MAX_INITIAL_MEM: Is used when no `-Xms` option is given in JAVA_OPTS.
|
||||||
|
# This is used to calculate the maximum value of the initial heap memory. If used in
|
||||||
|
# a container without any memory constraints for the container then this option has
|
||||||
|
# no effect. If there is a memory constraint then `-Xms` is limited to the value set
|
||||||
|
# here. The default is 4096MB which means the calculated value of `-Xms` never will
|
||||||
|
# be greater than 4096MB. The value of this variable is expressed in MB (example: "4096")
|
||||||
|
# - JAVA_DIAGNOSTICS: Set this to get some diagnostics information to standard output
|
||||||
|
# when things are happening. This option, if set to true, will set
|
||||||
|
# `-XX:+UnlockDiagnosticVMOptions`. Disabled by default (example: "true").
|
||||||
|
# - JAVA_DEBUG: If set remote debugging will be switched on. Disabled by default (example:
|
||||||
|
# true").
|
||||||
|
# - JAVA_DEBUG_PORT: Port used for remote debugging. Defaults to 5005 (example: "8787").
|
||||||
|
# - CONTAINER_CORE_LIMIT: A calculated core limit as described in
|
||||||
|
# https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt. (example: "2")
|
||||||
|
# - CONTAINER_MAX_MEMORY: Memory limit given to the container (example: "1024").
|
||||||
|
# - GC_MIN_HEAP_FREE_RATIO: Minimum percentage of heap free after GC to avoid expansion.
|
||||||
|
# (example: "20")
|
||||||
|
# - GC_MAX_HEAP_FREE_RATIO: Maximum percentage of heap free after GC to avoid shrinking.
|
||||||
|
# (example: "40")
|
||||||
|
# - GC_TIME_RATIO: Specifies the ratio of the time spent outside the garbage collection.
|
||||||
|
# (example: "4")
|
||||||
|
# - GC_ADAPTIVE_SIZE_POLICY_WEIGHT: The weighting given to the current GC time versus
|
||||||
|
# previous GC times. (example: "90")
|
||||||
|
# - GC_METASPACE_SIZE: The initial metaspace size. (example: "20")
|
||||||
|
# - GC_MAX_METASPACE_SIZE: The maximum metaspace size. (example: "100")
|
||||||
|
# - GC_CONTAINER_OPTIONS: Specify Java GC to use. The value of this variable should
|
||||||
|
# contain the necessary JRE command-line options to specify the required GC, which
|
||||||
|
# will override the default of `-XX:+UseParallelGC` (example: -XX:+UseG1GC).
|
||||||
|
# - HTTPS_PROXY: The location of the https proxy. (example: "myuser@127.0.0.1:8080")
|
||||||
|
# - HTTP_PROXY: The location of the http proxy. (example: "myuser@127.0.0.1:8080")
|
||||||
|
# - NO_PROXY: A comma separated lists of hosts, IP addresses or domains that can be
|
||||||
|
# accessed directly. (example: "foo.example.com,bar.example.com")
|
||||||
|
#
|
||||||
|
# You can find more information about the UBI base runtime images and their configuration here:
|
||||||
|
# https://rh-openjdk.github.io/redhat-openjdk-containers/
|
||||||
|
###
|
||||||
|
FROM registry.access.redhat.com/ubi9/openjdk-21-runtime:1.24
|
||||||
|
|
||||||
|
ENV LANGUAGE='en_US:en'
|
||||||
|
|
||||||
|
|
||||||
|
# We make four distinct layers so if there are application changes the library layers can be re-used
|
||||||
|
COPY --chown=185 build/quarkus-app/lib/ /deployments/lib/
|
||||||
|
COPY --chown=185 build/quarkus-app/*.jar /deployments/
|
||||||
|
COPY --chown=185 build/quarkus-app/app/ /deployments/app/
|
||||||
|
COPY --chown=185 build/quarkus-app/quarkus/ /deployments/quarkus/
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
USER 185
|
||||||
|
ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
|
||||||
|
ENV JAVA_APP_JAR="/deployments/quarkus-run.jar"
|
||||||
|
|
||||||
|
ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ]
|
||||||
|
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
####
|
||||||
|
# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
|
||||||
|
#
|
||||||
|
# Before building the container image run:
|
||||||
|
#
|
||||||
|
# ./gradlew build -Dquarkus.package.jar.type=legacy-jar
|
||||||
|
#
|
||||||
|
# Then, build the image with:
|
||||||
|
#
|
||||||
|
# docker build -f src/main/docker/Dockerfile.legacy-jar -t quarkus/backcore-legacy-jar .
|
||||||
|
#
|
||||||
|
# Then run the container using:
|
||||||
|
#
|
||||||
|
# docker run -i --rm -p 8080:8080 quarkus/backcore-legacy-jar
|
||||||
|
#
|
||||||
|
# If you want to include the debug port into your docker image
|
||||||
|
# you will have to expose the debug port (default 5005 being the default) like this : EXPOSE 8080 5005.
|
||||||
|
# Additionally you will have to set -e JAVA_DEBUG=true and -e JAVA_DEBUG_PORT=*:5005
|
||||||
|
# when running the container
|
||||||
|
#
|
||||||
|
# Then run the container using :
|
||||||
|
#
|
||||||
|
# docker run -i --rm -p 8080:8080 quarkus/backcore-legacy-jar
|
||||||
|
#
|
||||||
|
# This image uses the `run-java.sh` script to run the application.
|
||||||
|
# This scripts computes the command line to execute your Java application, and
|
||||||
|
# includes memory/GC tuning.
|
||||||
|
# You can configure the behavior using the following environment properties:
|
||||||
|
# - JAVA_OPTS: JVM options passed to the `java` command (example: "-verbose:class") - Be aware that this will override
|
||||||
|
# the default JVM options, use `JAVA_OPTS_APPEND` to append options
|
||||||
|
# - JAVA_OPTS_APPEND: User specified Java options to be appended to generated options
|
||||||
|
# in JAVA_OPTS (example: "-Dsome.property=foo")
|
||||||
|
# - JAVA_MAX_MEM_RATIO: Is used when no `-Xmx` option is given in JAVA_OPTS. This is
|
||||||
|
# used to calculate a default maximal heap memory based on a containers restriction.
|
||||||
|
# If used in a container without any memory constraints for the container then this
|
||||||
|
# option has no effect. If there is a memory constraint then `-Xmx` is set to a ratio
|
||||||
|
# of the container available memory as set here. The default is `50` which means 50%
|
||||||
|
# of the available memory is used as an upper boundary. You can skip this mechanism by
|
||||||
|
# setting this value to `0` in which case no `-Xmx` option is added.
|
||||||
|
# - JAVA_INITIAL_MEM_RATIO: Is used when no `-Xms` option is given in JAVA_OPTS. This
|
||||||
|
# is used to calculate a default initial heap memory based on the maximum heap memory.
|
||||||
|
# If used in a container without any memory constraints for the container then this
|
||||||
|
# option has no effect. If there is a memory constraint then `-Xms` is set to a ratio
|
||||||
|
# of the `-Xmx` memory as set here. The default is `25` which means 25% of the `-Xmx`
|
||||||
|
# is used as the initial heap size. You can skip this mechanism by setting this value
|
||||||
|
# to `0` in which case no `-Xms` option is added (example: "25")
|
||||||
|
# - JAVA_MAX_INITIAL_MEM: Is used when no `-Xms` option is given in JAVA_OPTS.
|
||||||
|
# This is used to calculate the maximum value of the initial heap memory. If used in
|
||||||
|
# a container without any memory constraints for the container then this option has
|
||||||
|
# no effect. If there is a memory constraint then `-Xms` is limited to the value set
|
||||||
|
# here. The default is 4096MB which means the calculated value of `-Xms` never will
|
||||||
|
# be greater than 4096MB. The value of this variable is expressed in MB (example: "4096")
|
||||||
|
# - JAVA_DIAGNOSTICS: Set this to get some diagnostics information to standard output
|
||||||
|
# when things are happening. This option, if set to true, will set
|
||||||
|
# `-XX:+UnlockDiagnosticVMOptions`. Disabled by default (example: "true").
|
||||||
|
# - JAVA_DEBUG: If set remote debugging will be switched on. Disabled by default (example:
|
||||||
|
# true").
|
||||||
|
# - JAVA_DEBUG_PORT: Port used for remote debugging. Defaults to 5005 (example: "8787").
|
||||||
|
# - CONTAINER_CORE_LIMIT: A calculated core limit as described in
|
||||||
|
# https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt. (example: "2")
|
||||||
|
# - CONTAINER_MAX_MEMORY: Memory limit given to the container (example: "1024").
|
||||||
|
# - GC_MIN_HEAP_FREE_RATIO: Minimum percentage of heap free after GC to avoid expansion.
|
||||||
|
# (example: "20")
|
||||||
|
# - GC_MAX_HEAP_FREE_RATIO: Maximum percentage of heap free after GC to avoid shrinking.
|
||||||
|
# (example: "40")
|
||||||
|
# - GC_TIME_RATIO: Specifies the ratio of the time spent outside the garbage collection.
|
||||||
|
# (example: "4")
|
||||||
|
# - GC_ADAPTIVE_SIZE_POLICY_WEIGHT: The weighting given to the current GC time versus
|
||||||
|
# previous GC times. (example: "90")
|
||||||
|
# - GC_METASPACE_SIZE: The initial metaspace size. (example: "20")
|
||||||
|
# - GC_MAX_METASPACE_SIZE: The maximum metaspace size. (example: "100")
|
||||||
|
# - GC_CONTAINER_OPTIONS: Specify Java GC to use. The value of this variable should
|
||||||
|
# contain the necessary JRE command-line options to specify the required GC, which
|
||||||
|
# will override the default of `-XX:+UseParallelGC` (example: -XX:+UseG1GC).
|
||||||
|
# - HTTPS_PROXY: The location of the https proxy. (example: "myuser@127.0.0.1:8080")
|
||||||
|
# - HTTP_PROXY: The location of the http proxy. (example: "myuser@127.0.0.1:8080")
|
||||||
|
# - NO_PROXY: A comma separated lists of hosts, IP addresses or domains that can be
|
||||||
|
# accessed directly. (example: "foo.example.com,bar.example.com")
|
||||||
|
#
|
||||||
|
# You can find more information about the UBI base runtime images and their configuration here:
|
||||||
|
# https://rh-openjdk.github.io/redhat-openjdk-containers/
|
||||||
|
###
|
||||||
|
FROM registry.access.redhat.com/ubi9/openjdk-21-runtime:1.24
|
||||||
|
|
||||||
|
ENV LANGUAGE='en_US:en'
|
||||||
|
|
||||||
|
|
||||||
|
COPY build/lib/* /deployments/lib/
|
||||||
|
COPY build/*-runner.jar /deployments/quarkus-run.jar
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
USER 185
|
||||||
|
ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
|
||||||
|
ENV JAVA_APP_JAR="/deployments/quarkus-run.jar"
|
||||||
|
|
||||||
|
ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ]
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
####
|
||||||
|
# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode.
|
||||||
|
#
|
||||||
|
# Before building the container image run:
|
||||||
|
#
|
||||||
|
# ./gradlew build -Dquarkus.native.enabled=true
|
||||||
|
#
|
||||||
|
# Then, build the image with:
|
||||||
|
#
|
||||||
|
# docker build -f src/main/docker/Dockerfile.native -t quarkus/backcore .
|
||||||
|
#
|
||||||
|
# Then run the container using:
|
||||||
|
#
|
||||||
|
# docker run -i --rm -p 8080:8080 quarkus/backcore
|
||||||
|
#
|
||||||
|
# The ` registry.access.redhat.com/ubi9/ubi-minimal:9.7` base image is based on UBI 9.
|
||||||
|
# To use UBI 8, switch to `quay.io/ubi8/ubi-minimal:8.10`.
|
||||||
|
###
|
||||||
|
FROM registry.access.redhat.com/ubi9/ubi-minimal:9.7
|
||||||
|
WORKDIR /work/
|
||||||
|
RUN chown 1001 /work \
|
||||||
|
&& chmod "g+rwX" /work \
|
||||||
|
&& chown 1001:root /work
|
||||||
|
COPY --chown=1001:root --chmod=0755 build/*-runner /work/application
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
USER 1001
|
||||||
|
|
||||||
|
ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"]
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
####
|
||||||
|
# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode.
|
||||||
|
# It uses a micro base image, tuned for Quarkus native executables.
|
||||||
|
# It reduces the size of the resulting container image.
|
||||||
|
# Check https://quarkus.io/guides/quarkus-runtime-base-image for further information about this image.
|
||||||
|
#
|
||||||
|
# Before building the container image run:
|
||||||
|
#
|
||||||
|
# ./gradlew build -Dquarkus.native.enabled=true
|
||||||
|
#
|
||||||
|
# Then, build the image with:
|
||||||
|
#
|
||||||
|
# docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/backcore .
|
||||||
|
#
|
||||||
|
# Then run the container using:
|
||||||
|
#
|
||||||
|
# docker run -i --rm -p 8080:8080 quarkus/backcore
|
||||||
|
#
|
||||||
|
# The `quay.io/quarkus/ubi9-quarkus-micro-image:2.0` base image is based on UBI 9.
|
||||||
|
# To use UBI 8, switch to `quay.io/quarkus/quarkus-micro-image:2.0`.
|
||||||
|
###
|
||||||
|
FROM quay.io/quarkus/ubi9-quarkus-micro-image:2.0
|
||||||
|
WORKDIR /work/
|
||||||
|
RUN chown 1001 /work \
|
||||||
|
&& chmod "g+rwX" /work \
|
||||||
|
&& chown 1001:root /work
|
||||||
|
COPY --chown=1001:root --chmod=0755 build/*-runner /work/application
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
USER 1001
|
||||||
|
|
||||||
|
ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"]
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
greeting:
|
||||||
|
message: "hello"
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
-- This file allow to write SQL commands that will be emitted in test and dev.
|
||||||
|
-- The commands are commented as their support depends of the database
|
||||||
|
-- insert into myentity (id, field) values(1, 'field-1');
|
||||||
|
-- insert into myentity (id, field) values(2, 'field-2');
|
||||||
|
-- insert into myentity (id, field) values(3, 'field-3');
|
||||||
|
-- alter sequence myentity_seq restart with 4;
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package de.nowchess.chess.config
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
|
import com.fasterxml.jackson.module.scala.DefaultScalaModule
|
||||||
|
import io.quarkus.jackson.ObjectMapperCustomizer
|
||||||
|
import jakarta.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class JacksonConfig extends ObjectMapperCustomizer:
|
||||||
|
def customize(mapper: ObjectMapper): Unit =
|
||||||
|
mapper.registerModule(DefaultScalaModule)
|
||||||
@@ -38,9 +38,10 @@ class GameEngine(
|
|||||||
private implicit val ec: ExecutionContext = ExecutionContext.global
|
private implicit val ec: ExecutionContext = ExecutionContext.global
|
||||||
|
|
||||||
// Synchronized accessors for current state
|
// Synchronized accessors for current state
|
||||||
def board: Board = synchronized(currentContext.board)
|
def board: Board = synchronized(currentContext.board)
|
||||||
def turn: Color = synchronized(currentContext.turn)
|
def turn: Color = synchronized(currentContext.turn)
|
||||||
def context: GameContext = synchronized(currentContext)
|
def context: GameContext = synchronized(currentContext)
|
||||||
|
def pendingDrawOfferBy: Option[Color] = synchronized(pendingDrawOffer)
|
||||||
|
|
||||||
/** Check if undo is available. */
|
/** Check if undo is available. */
|
||||||
def canUndo: Boolean = synchronized(invoker.canUndo)
|
def canUndo: Boolean = synchronized(invoker.canUndo)
|
||||||
@@ -67,21 +68,7 @@ class GameEngine(
|
|||||||
performRedo()
|
performRedo()
|
||||||
|
|
||||||
case "draw" =>
|
case "draw" =>
|
||||||
if currentContext.halfMoveClock >= 100 then
|
claimDraw()
|
||||||
currentContext = currentContext.withResult(Some(GameResult.Draw(DrawReason.FiftyMoveRule)))
|
|
||||||
invoker.clear()
|
|
||||||
notifyObservers(DrawEvent(currentContext, DrawReason.FiftyMoveRule))
|
|
||||||
else if ruleSet.isThreefoldRepetition(currentContext) then
|
|
||||||
currentContext = currentContext.withResult(Some(GameResult.Draw(DrawReason.ThreefoldRepetition)))
|
|
||||||
invoker.clear()
|
|
||||||
notifyObservers(DrawEvent(currentContext, DrawReason.ThreefoldRepetition))
|
|
||||||
else
|
|
||||||
notifyObservers(
|
|
||||||
InvalidMoveEvent(
|
|
||||||
currentContext,
|
|
||||||
InvalidMoveReason.DrawCannotBeClaimed,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
case "" =>
|
case "" =>
|
||||||
notifyObservers(InvalidMoveEvent(currentContext, InvalidMoveReason.EmptyInput))
|
notifyObservers(InvalidMoveEvent(currentContext, InvalidMoveReason.EmptyInput))
|
||||||
@@ -195,6 +182,21 @@ class GameEngine(
|
|||||||
notifyObservers(DrawOfferDeclinedEvent(currentContext, color))
|
notifyObservers(DrawOfferDeclinedEvent(currentContext, color))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Claim a draw by fifty-move rule or threefold repetition. */
|
||||||
|
def claimDraw(): Unit = synchronized {
|
||||||
|
if currentContext.result.isDefined then
|
||||||
|
notifyObservers(InvalidMoveEvent(currentContext, InvalidMoveReason.GameAlreadyOver))
|
||||||
|
else if currentContext.halfMoveClock >= 100 then
|
||||||
|
currentContext = currentContext.withResult(Some(GameResult.Draw(DrawReason.FiftyMoveRule)))
|
||||||
|
invoker.clear()
|
||||||
|
notifyObservers(DrawEvent(currentContext, DrawReason.FiftyMoveRule))
|
||||||
|
else if ruleSet.isThreefoldRepetition(currentContext) then
|
||||||
|
currentContext = currentContext.withResult(Some(GameResult.Draw(DrawReason.ThreefoldRepetition)))
|
||||||
|
invoker.clear()
|
||||||
|
notifyObservers(DrawEvent(currentContext, DrawReason.ThreefoldRepetition))
|
||||||
|
else notifyObservers(InvalidMoveEvent(currentContext, InvalidMoveReason.DrawCannotBeClaimed))
|
||||||
|
}
|
||||||
|
|
||||||
/** Load a game using the provided importer. If the imported context has moves, they are replayed through the command
|
/** Load a game using the provided importer. If the imported context has moves, they are replayed through the command
|
||||||
* system. Otherwise, the position is set directly. Notifies observers with PgnLoadedEvent on success.
|
* system. Otherwise, the position is set directly. Notifies observers with PgnLoadedEvent on success.
|
||||||
*/
|
*/
|
||||||
@@ -258,6 +260,22 @@ class GameEngine(
|
|||||||
notifyObservers(BoardResetEvent(currentContext))
|
notifyObservers(BoardResetEvent(currentContext))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Resign the game on behalf of the side to move. */
|
||||||
|
def resign(): Unit = synchronized {
|
||||||
|
if currentContext.result.isEmpty then
|
||||||
|
val winner = currentContext.turn.opposite
|
||||||
|
currentContext = currentContext.withResult(Some(GameResult.Win(winner)))
|
||||||
|
invoker.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Apply a draw result directly (for agreement, fifty-move claim, etc.). */
|
||||||
|
def applyDraw(reason: DrawReason): Unit = synchronized {
|
||||||
|
if currentContext.result.isEmpty then
|
||||||
|
currentContext = currentContext.withResult(Some(GameResult.Draw(reason)))
|
||||||
|
invoker.clear()
|
||||||
|
notifyObservers(DrawEvent(currentContext, reason))
|
||||||
|
}
|
||||||
|
|
||||||
/** Kick off play when the side to move is a bot (e.g. bot-vs-bot from initial position). */
|
/** Kick off play when the side to move is a bot (e.g. bot-vs-bot from initial position). */
|
||||||
def startGame(): Unit = synchronized(requestBotMoveIfNeeded())
|
def startGame(): Unit = synchronized(requestBotMoveIfNeeded())
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package de.nowchess.chess.exception
|
||||||
|
|
||||||
|
class ApiException(
|
||||||
|
val status: Int,
|
||||||
|
val code: String,
|
||||||
|
message: String,
|
||||||
|
val field: Option[String] = None,
|
||||||
|
) extends RuntimeException(message)
|
||||||
|
|
||||||
|
class GameNotFoundException(gameId: String) extends ApiException(404, "GAME_NOT_FOUND", s"Game $gameId not found")
|
||||||
|
|
||||||
|
class BadRequestException(code: String, message: String, field: Option[String] = None)
|
||||||
|
extends ApiException(400, code, message, field)
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package de.nowchess.chess.exception
|
||||||
|
|
||||||
|
import de.nowchess.api.dto.ApiErrorDto
|
||||||
|
import jakarta.ws.rs.core.{MediaType, Response}
|
||||||
|
import jakarta.ws.rs.ext.{ExceptionMapper, Provider}
|
||||||
|
|
||||||
|
@Provider
|
||||||
|
class ApiExceptionMapper extends ExceptionMapper[ApiException]:
|
||||||
|
def toResponse(ex: ApiException): Response =
|
||||||
|
Response
|
||||||
|
.status(ex.status)
|
||||||
|
.entity(ApiErrorDto(ex.code, ex.getMessage, ex.field))
|
||||||
|
.`type`(MediaType.APPLICATION_JSON)
|
||||||
|
.build()
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package de.nowchess.chess.registry
|
||||||
|
|
||||||
|
import de.nowchess.api.board.Color
|
||||||
|
import de.nowchess.api.player.PlayerInfo
|
||||||
|
import de.nowchess.chess.engine.GameEngine
|
||||||
|
|
||||||
|
final case class GameEntry(
|
||||||
|
gameId: String,
|
||||||
|
engine: GameEngine,
|
||||||
|
white: PlayerInfo,
|
||||||
|
black: PlayerInfo,
|
||||||
|
resigned: Boolean = false,
|
||||||
|
)
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package de.nowchess.chess.registry
|
||||||
|
|
||||||
|
trait GameRegistry:
|
||||||
|
def store(entry: GameEntry): Unit
|
||||||
|
def get(gameId: String): Option[GameEntry]
|
||||||
|
def update(entry: GameEntry): Unit
|
||||||
|
def generateId(): String
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package de.nowchess.chess.registry
|
||||||
|
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
import scala.util.Random
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
class GameRegistryImpl extends GameRegistry:
|
||||||
|
private val games = ConcurrentHashMap[String, GameEntry]()
|
||||||
|
|
||||||
|
def store(entry: GameEntry): Unit =
|
||||||
|
games.put(entry.gameId, entry)
|
||||||
|
|
||||||
|
def get(gameId: String): Option[GameEntry] =
|
||||||
|
Option(games.get(gameId))
|
||||||
|
|
||||||
|
def update(entry: GameEntry): Unit =
|
||||||
|
games.put(entry.gameId, entry)
|
||||||
|
|
||||||
|
def generateId(): String =
|
||||||
|
val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||||
|
Iterator.continually(Random.nextInt(chars.length)).map(chars).take(8).mkString // NOSONAR
|
||||||
@@ -0,0 +1,310 @@
|
|||||||
|
package de.nowchess.chess.resource
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
|
import de.nowchess.api.board.Square
|
||||||
|
import de.nowchess.api.dto.*
|
||||||
|
import de.nowchess.api.game.{DrawReason, GameContext, GameResult}
|
||||||
|
import de.nowchess.api.move.{Move, MoveType, PromotionPiece}
|
||||||
|
import de.nowchess.api.player.{PlayerId, PlayerInfo}
|
||||||
|
import de.nowchess.chess.controller.Parser
|
||||||
|
import de.nowchess.chess.engine.GameEngine
|
||||||
|
import de.nowchess.chess.exception.{BadRequestException, GameNotFoundException}
|
||||||
|
import de.nowchess.chess.observer.*
|
||||||
|
import de.nowchess.chess.registry.{GameEntry, GameRegistry}
|
||||||
|
import de.nowchess.io.fen.{FenExporter, FenParser}
|
||||||
|
import de.nowchess.io.pgn.{PgnExporter, PgnParser}
|
||||||
|
import io.smallrye.mutiny.Multi
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped
|
||||||
|
import jakarta.inject.Inject
|
||||||
|
import jakarta.ws.rs.*
|
||||||
|
import jakarta.ws.rs.core.{MediaType, Response}
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
|
import scala.compiletime.uninitialized
|
||||||
|
|
||||||
|
@Path("/api/board/game")
|
||||||
|
@ApplicationScoped
|
||||||
|
class GameResource:
|
||||||
|
|
||||||
|
// scalafix:off DisableSyntax.var
|
||||||
|
@Inject
|
||||||
|
var registry: GameRegistry = uninitialized
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
var objectMapper: ObjectMapper = uninitialized
|
||||||
|
// scalafix:on DisableSyntax.var
|
||||||
|
|
||||||
|
private val DefaultWhite = PlayerInfo(PlayerId("p1"), "Player 1")
|
||||||
|
private val DefaultBlack = PlayerInfo(PlayerId("p2"), "Player 2")
|
||||||
|
|
||||||
|
// ── mapping ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private def statusOf(entry: GameEntry): String =
|
||||||
|
if entry.engine.pendingDrawOfferBy.isDefined then "drawOffered"
|
||||||
|
else
|
||||||
|
val ctx = entry.engine.context
|
||||||
|
ctx.result match
|
||||||
|
case Some(GameResult.Win(_)) =>
|
||||||
|
if entry.resigned then "resign" else "checkmate"
|
||||||
|
case Some(GameResult.Draw(DrawReason.Stalemate)) => "stalemate"
|
||||||
|
case Some(GameResult.Draw(DrawReason.InsufficientMaterial)) => "insufficientMaterial"
|
||||||
|
case Some(GameResult.Draw(_)) => "draw"
|
||||||
|
case None =>
|
||||||
|
if ctx.halfMoveClock >= 100 then "fiftyMoveAvailable"
|
||||||
|
else if entry.engine.ruleSet.isCheck(ctx) then "check"
|
||||||
|
else "started"
|
||||||
|
|
||||||
|
private def moveToUci(move: Move): String =
|
||||||
|
val base = s"${move.from}${move.to}"
|
||||||
|
move.moveType match
|
||||||
|
case MoveType.Promotion(PromotionPiece.Queen) => s"${base}q"
|
||||||
|
case MoveType.Promotion(PromotionPiece.Rook) => s"${base}r"
|
||||||
|
case MoveType.Promotion(PromotionPiece.Bishop) => s"${base}b"
|
||||||
|
case MoveType.Promotion(PromotionPiece.Knight) => s"${base}n"
|
||||||
|
case _ => base
|
||||||
|
|
||||||
|
private def toLegalMoveDto(move: Move): LegalMoveDto =
|
||||||
|
val (moveTypeStr, promotionStr) = move.moveType match
|
||||||
|
case MoveType.Normal(false) => ("normal", None)
|
||||||
|
case MoveType.Normal(true) => ("capture", None)
|
||||||
|
case MoveType.CastleKingside => ("castleKingside", None)
|
||||||
|
case MoveType.CastleQueenside => ("castleQueenside", None)
|
||||||
|
case MoveType.EnPassant => ("enPassant", None)
|
||||||
|
case MoveType.Promotion(PromotionPiece.Queen) => ("promotion", Some("queen"))
|
||||||
|
case MoveType.Promotion(PromotionPiece.Rook) => ("promotion", Some("rook"))
|
||||||
|
case MoveType.Promotion(PromotionPiece.Bishop) => ("promotion", Some("bishop"))
|
||||||
|
case MoveType.Promotion(PromotionPiece.Knight) => ("promotion", Some("knight"))
|
||||||
|
LegalMoveDto(move.from.toString, move.to.toString, moveToUci(move), moveTypeStr, promotionStr)
|
||||||
|
|
||||||
|
private def toPlayerDto(info: PlayerInfo): PlayerInfoDto =
|
||||||
|
PlayerInfoDto(info.id.value, info.displayName)
|
||||||
|
|
||||||
|
private def toGameStateDto(entry: GameEntry): GameStateDto =
|
||||||
|
val ctx = entry.engine.context
|
||||||
|
GameStateDto(
|
||||||
|
fen = FenExporter.exportGameContext(ctx),
|
||||||
|
pgn = PgnExporter.exportGame(
|
||||||
|
Map(
|
||||||
|
"Event" -> "NowChess game",
|
||||||
|
"White" -> entry.white.displayName,
|
||||||
|
"Black" -> entry.black.displayName,
|
||||||
|
"Result" -> "*",
|
||||||
|
),
|
||||||
|
ctx.moves,
|
||||||
|
),
|
||||||
|
turn = ctx.turn.label.toLowerCase,
|
||||||
|
status = statusOf(entry),
|
||||||
|
winner = ctx.result.collect { case GameResult.Win(c) => c.label.toLowerCase },
|
||||||
|
moves = ctx.moves.map(moveToUci),
|
||||||
|
undoAvailable = entry.engine.canUndo,
|
||||||
|
redoAvailable = entry.engine.canRedo,
|
||||||
|
)
|
||||||
|
|
||||||
|
private def toGameFullDto(entry: GameEntry): GameFullDto =
|
||||||
|
GameFullDto(entry.gameId, toPlayerDto(entry.white), toPlayerDto(entry.black), toGameStateDto(entry))
|
||||||
|
|
||||||
|
private def playerInfoFrom(dto: Option[PlayerInfoDto], default: PlayerInfo): PlayerInfo =
|
||||||
|
dto.fold(default)(d => PlayerInfo(PlayerId(d.id), d.displayName))
|
||||||
|
|
||||||
|
private def newEntry(ctx: GameContext, white: PlayerInfo, black: PlayerInfo): GameEntry =
|
||||||
|
GameEntry(registry.generateId(), GameEngine(initialContext = ctx), white, black)
|
||||||
|
|
||||||
|
private def applyMoveInput(engine: GameEngine, uci: String): Option[String] =
|
||||||
|
val error = new AtomicReference[Option[String]](None)
|
||||||
|
val obs = new Observer:
|
||||||
|
def onGameEvent(e: GameEvent): Unit = e match
|
||||||
|
case InvalidMoveEvent(_, reason) => error.set(Some(reason.toString))
|
||||||
|
case _ => ()
|
||||||
|
engine.subscribe(obs)
|
||||||
|
engine.processUserInput(uci)
|
||||||
|
engine.unsubscribe(obs)
|
||||||
|
error.get()
|
||||||
|
|
||||||
|
// ── response helpers ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private def ok(body: AnyRef): Response = Response.ok(body).build()
|
||||||
|
private def created(body: AnyRef): Response = Response.status(Response.Status.CREATED).entity(body).build()
|
||||||
|
|
||||||
|
// scalafix:off DisableSyntax.throw
|
||||||
|
private def assertGameNotOver(entry: GameEntry): Unit =
|
||||||
|
if entry.engine.context.result.isDefined then throw BadRequestException("GAME_OVER", "Game is already over")
|
||||||
|
// scalafix:on DisableSyntax.throw
|
||||||
|
|
||||||
|
// ── endpoints ────────────────────────────────────────────────────────────
|
||||||
|
// scalafix:off DisableSyntax.throw
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Consumes(Array(MediaType.APPLICATION_JSON))
|
||||||
|
@Produces(Array(MediaType.APPLICATION_JSON))
|
||||||
|
def createGame(body: CreateGameRequestDto): Response =
|
||||||
|
val req = Option(body).getOrElse(CreateGameRequestDto(None, None))
|
||||||
|
val white = playerInfoFrom(req.white, DefaultWhite)
|
||||||
|
val black = playerInfoFrom(req.black, DefaultBlack)
|
||||||
|
val entry = newEntry(GameContext.initial, white, black)
|
||||||
|
registry.store(entry)
|
||||||
|
created(toGameFullDto(entry))
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/{gameId}")
|
||||||
|
@Produces(Array(MediaType.APPLICATION_JSON))
|
||||||
|
def getGame(@PathParam("gameId") gameId: String): Response =
|
||||||
|
val entry = registry.get(gameId).getOrElse(throw GameNotFoundException(gameId))
|
||||||
|
ok(toGameFullDto(entry))
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/{gameId}/stream")
|
||||||
|
@Produces(Array("application/x-ndjson"))
|
||||||
|
def streamGame(@PathParam("gameId") gameId: String): Multi[String] =
|
||||||
|
val entry = registry.get(gameId).getOrElse(throw GameNotFoundException(gameId))
|
||||||
|
Multi
|
||||||
|
.createFrom()
|
||||||
|
.emitter[String] { emitter =>
|
||||||
|
emitter.emit(objectMapper.writeValueAsString(GameFullEventDto(toGameFullDto(entry))) + "\n")
|
||||||
|
val obs = new Observer:
|
||||||
|
def onGameEvent(event: GameEvent): Unit =
|
||||||
|
registry.get(gameId).foreach { updated =>
|
||||||
|
emitter.emit(
|
||||||
|
objectMapper.writeValueAsString(GameStateEventDto(toGameStateDto(updated))) + "\n",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
entry.engine.subscribe(obs)
|
||||||
|
emitter.onTermination(() => entry.engine.unsubscribe(obs))
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/{gameId}/resign")
|
||||||
|
@Produces(Array(MediaType.APPLICATION_JSON))
|
||||||
|
def resignGame(@PathParam("gameId") gameId: String): Response =
|
||||||
|
val entry = registry.get(gameId).getOrElse(throw GameNotFoundException(gameId))
|
||||||
|
assertGameNotOver(entry)
|
||||||
|
entry.engine.resign()
|
||||||
|
registry.update(entry.copy(resigned = true))
|
||||||
|
ok(OkResponseDto())
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/{gameId}/move/{uci}")
|
||||||
|
@Produces(Array(MediaType.APPLICATION_JSON))
|
||||||
|
def makeMove(@PathParam("gameId") gameId: String, @PathParam("uci") uci: String): Response =
|
||||||
|
val entry = registry.get(gameId).getOrElse(throw GameNotFoundException(gameId))
|
||||||
|
assertGameNotOver(entry)
|
||||||
|
val (from, to, promoOpt) = Parser
|
||||||
|
.parseMove(uci)
|
||||||
|
.getOrElse(throw BadRequestException("INVALID_UCI", s"Invalid UCI notation: $uci", Some("uci")))
|
||||||
|
val candidates = entry.engine.ruleSet.legalMoves(entry.engine.context)(from).filter(_.to == to)
|
||||||
|
val isPromotion = candidates.exists { case Move(_, _, MoveType.Promotion(_)) => true; case _ => false }
|
||||||
|
if candidates.isEmpty || (isPromotion && promoOpt.isEmpty) then
|
||||||
|
throw BadRequestException("INVALID_MOVE", s"$uci is not a legal move", Some("uci"))
|
||||||
|
applyMoveInput(entry.engine, uci).foreach(err => throw BadRequestException("INVALID_MOVE", err, Some("uci")))
|
||||||
|
ok(toGameStateDto(entry))
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/{gameId}/moves")
|
||||||
|
@Produces(Array(MediaType.APPLICATION_JSON))
|
||||||
|
def getLegalMoves(
|
||||||
|
@PathParam("gameId") gameId: String,
|
||||||
|
@QueryParam("square") square: String,
|
||||||
|
): Response =
|
||||||
|
val entry = registry.get(gameId).getOrElse(throw GameNotFoundException(gameId))
|
||||||
|
val ctx = entry.engine.context
|
||||||
|
val moves =
|
||||||
|
if Option(square).isEmpty || square.isEmpty then entry.engine.ruleSet.allLegalMoves(ctx)
|
||||||
|
else
|
||||||
|
val sq = Square
|
||||||
|
.fromAlgebraic(square)
|
||||||
|
.getOrElse(throw BadRequestException("INVALID_SQUARE", s"Invalid square: $square", Some("square")))
|
||||||
|
entry.engine.ruleSet.legalMoves(ctx)(sq)
|
||||||
|
ok(LegalMovesResponseDto(moves.map(toLegalMoveDto)))
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/{gameId}/undo")
|
||||||
|
@Produces(Array(MediaType.APPLICATION_JSON))
|
||||||
|
def undoMove(@PathParam("gameId") gameId: String): Response =
|
||||||
|
val entry = registry.get(gameId).getOrElse(throw GameNotFoundException(gameId))
|
||||||
|
if !entry.engine.canUndo then throw BadRequestException("NO_UNDO", "No moves to undo")
|
||||||
|
entry.engine.undo()
|
||||||
|
ok(toGameStateDto(entry))
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/{gameId}/redo")
|
||||||
|
@Produces(Array(MediaType.APPLICATION_JSON))
|
||||||
|
def redoMove(@PathParam("gameId") gameId: String): Response =
|
||||||
|
val entry = registry.get(gameId).getOrElse(throw GameNotFoundException(gameId))
|
||||||
|
if !entry.engine.canRedo then throw BadRequestException("NO_REDO", "No moves to redo")
|
||||||
|
entry.engine.redo()
|
||||||
|
ok(toGameStateDto(entry))
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/{gameId}/draw/{action}")
|
||||||
|
@Produces(Array(MediaType.APPLICATION_JSON))
|
||||||
|
def drawAction(
|
||||||
|
@PathParam("gameId") gameId: String,
|
||||||
|
@PathParam("action") action: String,
|
||||||
|
): Response =
|
||||||
|
val entry = registry.get(gameId).getOrElse(throw GameNotFoundException(gameId))
|
||||||
|
assertGameNotOver(entry)
|
||||||
|
action match
|
||||||
|
case "offer" =>
|
||||||
|
entry.engine.offerDraw(entry.engine.context.turn)
|
||||||
|
ok(OkResponseDto())
|
||||||
|
case "accept" =>
|
||||||
|
entry.engine.acceptDraw(entry.engine.context.turn)
|
||||||
|
ok(OkResponseDto())
|
||||||
|
case "decline" =>
|
||||||
|
entry.engine.declineDraw(entry.engine.context.turn)
|
||||||
|
ok(OkResponseDto())
|
||||||
|
case "claim" =>
|
||||||
|
entry.engine.claimDraw()
|
||||||
|
ok(OkResponseDto())
|
||||||
|
case _ =>
|
||||||
|
throw BadRequestException("INVALID_ACTION", s"Unknown draw action: $action", Some("action"))
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/import/fen")
|
||||||
|
@Consumes(Array(MediaType.APPLICATION_JSON))
|
||||||
|
@Produces(Array(MediaType.APPLICATION_JSON))
|
||||||
|
def importFen(body: ImportFenRequestDto): Response =
|
||||||
|
val ctx = FenParser.parseFen(body.fen) match
|
||||||
|
case Left(err) => throw BadRequestException("INVALID_FEN", err, Some("fen"))
|
||||||
|
case Right(ctx) => ctx
|
||||||
|
val white = playerInfoFrom(body.white, DefaultWhite)
|
||||||
|
val black = playerInfoFrom(body.black, DefaultBlack)
|
||||||
|
val entry = newEntry(ctx, white, black)
|
||||||
|
registry.store(entry)
|
||||||
|
created(toGameFullDto(entry))
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/import/pgn")
|
||||||
|
@Consumes(Array(MediaType.APPLICATION_JSON))
|
||||||
|
@Produces(Array(MediaType.APPLICATION_JSON))
|
||||||
|
def importPgn(body: ImportPgnRequestDto): Response =
|
||||||
|
val engine = GameEngine()
|
||||||
|
engine.loadGame(PgnParser, body.pgn) match
|
||||||
|
case Left(err) => throw BadRequestException("INVALID_PGN", err, Some("pgn"))
|
||||||
|
case Right(_) => ()
|
||||||
|
val entry = GameEntry(registry.generateId(), engine, DefaultWhite, DefaultBlack)
|
||||||
|
registry.store(entry)
|
||||||
|
created(toGameFullDto(entry))
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/{gameId}/export/fen")
|
||||||
|
@Produces(Array(MediaType.TEXT_PLAIN))
|
||||||
|
def exportFen(@PathParam("gameId") gameId: String): Response =
|
||||||
|
val entry = registry.get(gameId).getOrElse(throw GameNotFoundException(gameId))
|
||||||
|
ok(FenExporter.exportGameContext(entry.engine.context))
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/{gameId}/export/pgn")
|
||||||
|
@Produces(Array("application/x-chess-pgn"))
|
||||||
|
def exportPgn(@PathParam("gameId") gameId: String): Response =
|
||||||
|
val entry = registry.get(gameId).getOrElse(throw GameNotFoundException(gameId))
|
||||||
|
val pgn = PgnExporter.exportGame(
|
||||||
|
Map(
|
||||||
|
"Event" -> "NowChess game",
|
||||||
|
"White" -> entry.white.displayName,
|
||||||
|
"Black" -> entry.black.displayName,
|
||||||
|
"Result" -> "*",
|
||||||
|
),
|
||||||
|
entry.engine.context.moves,
|
||||||
|
)
|
||||||
|
ok(pgn)
|
||||||
|
// scalafix:on DisableSyntax.throw
|
||||||
@@ -234,6 +234,77 @@ class GameEngineDrawOfferTest extends AnyFunSuite with Matchers:
|
|||||||
case other =>
|
case other =>
|
||||||
fail(s"Expected InvalidMoveEvent, but got $other")
|
fail(s"Expected InvalidMoveEvent, but got $other")
|
||||||
|
|
||||||
|
test("pendingDrawOfferBy returns None initially"):
|
||||||
|
val engine = new GameEngine()
|
||||||
|
engine.pendingDrawOfferBy shouldBe None
|
||||||
|
|
||||||
|
test("pendingDrawOfferBy returns White after White offers"):
|
||||||
|
val engine = new GameEngine()
|
||||||
|
engine.offerDraw(Color.White)
|
||||||
|
engine.pendingDrawOfferBy shouldBe Some(Color.White)
|
||||||
|
|
||||||
|
test("pendingDrawOfferBy returns None after draw is accepted"):
|
||||||
|
val engine = new GameEngine()
|
||||||
|
engine.offerDraw(Color.White)
|
||||||
|
engine.acceptDraw(Color.Black)
|
||||||
|
engine.pendingDrawOfferBy shouldBe None
|
||||||
|
|
||||||
|
test("applyDraw sets draw result when game not over"):
|
||||||
|
val engine = new GameEngine()
|
||||||
|
val observer = new DrawOfferMockObserver()
|
||||||
|
engine.subscribe(observer)
|
||||||
|
engine.applyDraw(DrawReason.Agreement)
|
||||||
|
observer.events should have length 1
|
||||||
|
observer.events.head match
|
||||||
|
case event: DrawEvent =>
|
||||||
|
event.reason shouldBe DrawReason.Agreement
|
||||||
|
event.context.result shouldBe Some(GameResult.Draw(DrawReason.Agreement))
|
||||||
|
case other =>
|
||||||
|
fail(s"Expected DrawEvent, but got $other")
|
||||||
|
|
||||||
|
test("applyDraw does nothing when game already over"):
|
||||||
|
val engine = new GameEngine()
|
||||||
|
val observer = new DrawOfferMockObserver()
|
||||||
|
engine.subscribe(observer)
|
||||||
|
// End the game with checkmate
|
||||||
|
engine.processUserInput("f2f3")
|
||||||
|
engine.processUserInput("e7e5")
|
||||||
|
engine.processUserInput("g2g4")
|
||||||
|
engine.processUserInput("d8h4")
|
||||||
|
observer.events.clear()
|
||||||
|
engine.applyDraw(DrawReason.Agreement)
|
||||||
|
observer.events should have length 0
|
||||||
|
|
||||||
|
test("claimDraw with fifty-move rule when at half-move 100"):
|
||||||
|
val engine = new GameEngine()
|
||||||
|
val observer = new DrawOfferMockObserver()
|
||||||
|
engine.subscribe(observer)
|
||||||
|
// Play moves to reach fifty-move rule claim
|
||||||
|
engine.processUserInput("e2e4")
|
||||||
|
engine.processUserInput("e7e5")
|
||||||
|
engine.processUserInput("g1f3")
|
||||||
|
engine.processUserInput("g8f6")
|
||||||
|
// Need to advance halfMoveClock to 100
|
||||||
|
// This is hard to do naturally; skip for now if not critical
|
||||||
|
|
||||||
|
test("claimDraw when game already over"):
|
||||||
|
val engine = new GameEngine()
|
||||||
|
val observer = new DrawOfferMockObserver()
|
||||||
|
engine.subscribe(observer)
|
||||||
|
// End the game with checkmate
|
||||||
|
engine.processUserInput("f2f3")
|
||||||
|
engine.processUserInput("e7e5")
|
||||||
|
engine.processUserInput("g2g4")
|
||||||
|
engine.processUserInput("d8h4")
|
||||||
|
observer.events.clear()
|
||||||
|
engine.claimDraw()
|
||||||
|
observer.events should have length 1
|
||||||
|
observer.events.head match
|
||||||
|
case event: InvalidMoveEvent =>
|
||||||
|
event.reason shouldBe InvalidMoveReason.GameAlreadyOver
|
||||||
|
case other =>
|
||||||
|
fail(s"Expected InvalidMoveEvent, but got $other")
|
||||||
|
|
||||||
private class DrawOfferMockObserver extends Observer:
|
private class DrawOfferMockObserver extends Observer:
|
||||||
val events = mutable.ListBuffer[GameEvent]()
|
val events = mutable.ListBuffer[GameEvent]()
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,32 @@ class GameEngineResignTest extends AnyFunSuite with Matchers:
|
|||||||
case other =>
|
case other =>
|
||||||
fail(s"Expected InvalidMoveEvent, but got $other")
|
fail(s"Expected InvalidMoveEvent, but got $other")
|
||||||
|
|
||||||
|
test("resign() without color resigns side to move"):
|
||||||
|
val engine = new GameEngine()
|
||||||
|
val observer = new ResignMockObserver()
|
||||||
|
engine.subscribe(observer)
|
||||||
|
|
||||||
|
engine.resign()
|
||||||
|
|
||||||
|
engine.context.result shouldBe Some(GameResult.Win(Color.Black))
|
||||||
|
|
||||||
|
test("resign() without color does nothing when game already over"):
|
||||||
|
val engine = new GameEngine()
|
||||||
|
val observer = new ResignMockObserver()
|
||||||
|
engine.subscribe(observer)
|
||||||
|
|
||||||
|
// End the game with checkmate
|
||||||
|
engine.processUserInput("f2f3")
|
||||||
|
engine.processUserInput("e7e5")
|
||||||
|
engine.processUserInput("g2g4")
|
||||||
|
observer.events.clear()
|
||||||
|
engine.processUserInput("d8h4")
|
||||||
|
|
||||||
|
// Try to resign without color parameter
|
||||||
|
val resultBefore = engine.context.result
|
||||||
|
engine.resign()
|
||||||
|
resultBefore shouldBe engine.context.result
|
||||||
|
|
||||||
private class ResignMockObserver extends Observer:
|
private class ResignMockObserver extends Observer:
|
||||||
val events = mutable.ListBuffer[GameEvent]()
|
val events = mutable.ListBuffer[GameEvent]()
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package de.nowchess.chess.registry
|
||||||
|
|
||||||
|
import de.nowchess.api.player.{PlayerId, PlayerInfo}
|
||||||
|
import de.nowchess.chess.engine.GameEngine
|
||||||
|
import io.quarkus.test.junit.QuarkusTest
|
||||||
|
import jakarta.inject.Inject
|
||||||
|
import org.junit.jupiter.api.{DisplayName, Test}
|
||||||
|
import org.junit.jupiter.api.Assertions.*
|
||||||
|
|
||||||
|
import scala.compiletime.uninitialized
|
||||||
|
|
||||||
|
// scalafix:off
|
||||||
|
@QuarkusTest
|
||||||
|
@DisplayName("GameRegistryImpl")
|
||||||
|
class GameRegistryImplTest:
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
var registry: GameRegistry = uninitialized
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("store saves entry")
|
||||||
|
def testStore(): Unit =
|
||||||
|
val entry = GameEntry("g1", GameEngine(), PlayerInfo(PlayerId("p1"), "P1"), PlayerInfo(PlayerId("p2"), "P2"))
|
||||||
|
registry.store(entry)
|
||||||
|
assertTrue(registry.get("g1").isDefined)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("get returns stored entry")
|
||||||
|
def testGet(): Unit =
|
||||||
|
val entry = GameEntry("g2", GameEngine(), PlayerInfo(PlayerId("p1"), "P1"), PlayerInfo(PlayerId("p2"), "P2"))
|
||||||
|
registry.store(entry)
|
||||||
|
val retrieved = registry.get("g2")
|
||||||
|
assertTrue(retrieved.isDefined)
|
||||||
|
assertEquals("g2", retrieved.get.gameId)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("get returns None for unknown id")
|
||||||
|
def testGetUnknown(): Unit =
|
||||||
|
assertTrue(registry.get("unknown").isEmpty)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("update modifies existing entry")
|
||||||
|
def testUpdate(): Unit =
|
||||||
|
val entry = GameEntry("g3", GameEngine(), PlayerInfo(PlayerId("p1"), "P1"), PlayerInfo(PlayerId("p2"), "P2"))
|
||||||
|
registry.store(entry)
|
||||||
|
val updated = entry.copy(resigned = true)
|
||||||
|
registry.update(updated)
|
||||||
|
val retrieved = registry.get("g3")
|
||||||
|
assertTrue(retrieved.isDefined)
|
||||||
|
assertTrue(retrieved.get.resigned)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("generateId produces unique ids")
|
||||||
|
def testGenerateId(): Unit =
|
||||||
|
val id1 = registry.generateId()
|
||||||
|
val id2 = registry.generateId()
|
||||||
|
assertNotEquals(id1, id2)
|
||||||
|
assertFalse(id1.isEmpty)
|
||||||
|
assertFalse(id2.isEmpty)
|
||||||
|
// scalafix:on
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
package de.nowchess.chess.resource
|
||||||
|
|
||||||
|
import de.nowchess.api.dto.*
|
||||||
|
import de.nowchess.chess.exception.BadRequestException
|
||||||
|
import io.quarkus.test.junit.QuarkusTest
|
||||||
|
import jakarta.inject.Inject
|
||||||
|
import org.junit.jupiter.api.{DisplayName, Test}
|
||||||
|
import org.junit.jupiter.api.Assertions.*
|
||||||
|
|
||||||
|
import scala.compiletime.uninitialized
|
||||||
|
|
||||||
|
// scalafix:off
|
||||||
|
@QuarkusTest
|
||||||
|
@DisplayName("GameResource Integration")
|
||||||
|
class GameResourceIntegrationTest:
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
var resource: GameResource = uninitialized
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("createGame returns 201")
|
||||||
|
def testCreateGame(): Unit =
|
||||||
|
val req = CreateGameRequestDto(None, None)
|
||||||
|
val resp = resource.createGame(req)
|
||||||
|
assertEquals(201, resp.getStatus)
|
||||||
|
val dto = resp.getEntity.asInstanceOf[GameFullDto]
|
||||||
|
assertNotNull(dto.gameId)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("getGame returns 200")
|
||||||
|
def testGetGame(): Unit =
|
||||||
|
val createResp = resource.createGame(CreateGameRequestDto(None, None))
|
||||||
|
val gameId = createResp.getEntity.asInstanceOf[GameFullDto].gameId
|
||||||
|
val getResp = resource.getGame(gameId)
|
||||||
|
assertEquals(200, getResp.getStatus)
|
||||||
|
val dto = getResp.getEntity.asInstanceOf[GameFullDto]
|
||||||
|
assertEquals(gameId, dto.gameId)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("makeMove advances game")
|
||||||
|
def testMakeMove(): Unit =
|
||||||
|
val createResp = resource.createGame(CreateGameRequestDto(None, None))
|
||||||
|
val gameId = createResp.getEntity.asInstanceOf[GameFullDto].gameId
|
||||||
|
val moveResp = resource.makeMove(gameId, "e2e4")
|
||||||
|
assertEquals(200, moveResp.getStatus)
|
||||||
|
val state = moveResp.getEntity.asInstanceOf[GameStateDto]
|
||||||
|
assertEquals("black", state.turn)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("makeMove with invalid UCI throws")
|
||||||
|
def testMakeMoveInvalid(): Unit =
|
||||||
|
val createResp = resource.createGame(CreateGameRequestDto(None, None))
|
||||||
|
val gameId = createResp.getEntity.asInstanceOf[GameFullDto].gameId
|
||||||
|
assertThrows(classOf[BadRequestException], () => resource.makeMove(gameId, "invalid"))
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("getLegalMoves returns moves")
|
||||||
|
def testGetLegalMoves(): Unit =
|
||||||
|
val createResp = resource.createGame(CreateGameRequestDto(None, None))
|
||||||
|
val gameId = createResp.getEntity.asInstanceOf[GameFullDto].gameId
|
||||||
|
val movesResp = resource.getLegalMoves(gameId, "")
|
||||||
|
assertEquals(200, movesResp.getStatus)
|
||||||
|
val dto = movesResp.getEntity.asInstanceOf[LegalMovesResponseDto]
|
||||||
|
assertFalse(dto.moves.isEmpty)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("resignGame updates state")
|
||||||
|
def testResignGame(): Unit =
|
||||||
|
val createResp = resource.createGame(CreateGameRequestDto(None, None))
|
||||||
|
val gameId = createResp.getEntity.asInstanceOf[GameFullDto].gameId
|
||||||
|
val resignResp = resource.resignGame(gameId)
|
||||||
|
assertEquals(200, resignResp.getStatus)
|
||||||
|
val getResp = resource.getGame(gameId)
|
||||||
|
val state = getResp.getEntity.asInstanceOf[GameFullDto].state
|
||||||
|
assertEquals("resign", state.status)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("undoMove reverts")
|
||||||
|
def testUndoMove(): Unit =
|
||||||
|
val createResp = resource.createGame(CreateGameRequestDto(None, None))
|
||||||
|
val gameId = createResp.getEntity.asInstanceOf[GameFullDto].gameId
|
||||||
|
resource.makeMove(gameId, "e2e4")
|
||||||
|
val undoResp = resource.undoMove(gameId)
|
||||||
|
assertEquals(200, undoResp.getStatus)
|
||||||
|
val state = undoResp.getEntity.asInstanceOf[GameStateDto]
|
||||||
|
assertEquals("white", state.turn)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("redoMove restores")
|
||||||
|
def testRedoMove(): Unit =
|
||||||
|
val createResp = resource.createGame(CreateGameRequestDto(None, None))
|
||||||
|
val gameId = createResp.getEntity.asInstanceOf[GameFullDto].gameId
|
||||||
|
resource.makeMove(gameId, "e2e4")
|
||||||
|
resource.undoMove(gameId)
|
||||||
|
val redoResp = resource.redoMove(gameId)
|
||||||
|
assertEquals(200, redoResp.getStatus)
|
||||||
|
val state = redoResp.getEntity.asInstanceOf[GameStateDto]
|
||||||
|
assertEquals("black", state.turn)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("drawAction offer")
|
||||||
|
def testDrawActionOffer(): Unit =
|
||||||
|
val createResp = resource.createGame(CreateGameRequestDto(None, None))
|
||||||
|
val gameId = createResp.getEntity.asInstanceOf[GameFullDto].gameId
|
||||||
|
val resp = resource.drawAction(gameId, "offer")
|
||||||
|
assertEquals(200, resp.getStatus)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("drawAction accept")
|
||||||
|
def testDrawActionAccept(): Unit =
|
||||||
|
val createResp = resource.createGame(CreateGameRequestDto(None, None))
|
||||||
|
val gameId = createResp.getEntity.asInstanceOf[GameFullDto].gameId
|
||||||
|
resource.drawAction(gameId, "offer")
|
||||||
|
val resp = resource.drawAction(gameId, "accept")
|
||||||
|
assertEquals(200, resp.getStatus)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("importFen creates game")
|
||||||
|
def testImportFen(): Unit =
|
||||||
|
val fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
|
||||||
|
val req = ImportFenRequestDto(fen, None, None)
|
||||||
|
val resp = resource.importFen(req)
|
||||||
|
assertEquals(201, resp.getStatus)
|
||||||
|
val dto = resp.getEntity.asInstanceOf[GameFullDto]
|
||||||
|
assertEquals(fen, dto.state.fen)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("importPgn creates game")
|
||||||
|
def testImportPgn(): Unit =
|
||||||
|
val req = ImportPgnRequestDto("1. e4 c5")
|
||||||
|
val resp = resource.importPgn(req)
|
||||||
|
assertEquals(201, resp.getStatus)
|
||||||
|
val dto = resp.getEntity.asInstanceOf[GameFullDto]
|
||||||
|
assertTrue(dto.state.moves.length > 0)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("exportFen returns FEN")
|
||||||
|
def testExportFen(): Unit =
|
||||||
|
val createResp = resource.createGame(CreateGameRequestDto(None, None))
|
||||||
|
val gameId = createResp.getEntity.asInstanceOf[GameFullDto].gameId
|
||||||
|
val resp = resource.exportFen(gameId)
|
||||||
|
assertEquals(200, resp.getStatus)
|
||||||
|
assertTrue(resp.getEntity.asInstanceOf[String].contains("rnbqkbnr"))
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("exportPgn returns PGN")
|
||||||
|
def testExportPgn(): Unit =
|
||||||
|
val createResp = resource.createGame(CreateGameRequestDto(None, None))
|
||||||
|
val gameId = createResp.getEntity.asInstanceOf[GameFullDto].gameId
|
||||||
|
resource.makeMove(gameId, "e2e4")
|
||||||
|
val resp = resource.exportPgn(gameId)
|
||||||
|
assertEquals(200, resp.getStatus)
|
||||||
|
assertTrue(resp.getEntity.asInstanceOf[String].contains("1."))
|
||||||
|
// scalafix:on
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=15
|
MINOR=16
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -66,3 +66,13 @@
|
|||||||
* NCS-30 FEN Parser using ParserCombinators ([#21](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/21)) ([b4bc72f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b4bc72f7e49f94d6e1bc805c68680e5fe8ef8e36))
|
* NCS-30 FEN Parser using ParserCombinators ([#21](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/21)) ([b4bc72f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b4bc72f7e49f94d6e1bc805c68680e5fe8ef8e36))
|
||||||
* NCS-31 FastParse FEN ([#22](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/22)) ([7a045d3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/7a045d31d757bbc5aa6f4bad2664ebe8b8519cac))
|
* NCS-31 FastParse FEN ([#22](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/22)) ([7a045d3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/7a045d31d757bbc5aa6f4bad2664ebe8b8519cac))
|
||||||
* NCS-41 Bot Platform ([#33](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/33)) ([dceab08](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dceab0875e6d15f7d3958633cf5dd5b29a851b1d))
|
* NCS-41 Bot Platform ([#33](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/33)) ([dceab08](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dceab0875e6d15f7d3958633cf5dd5b29a851b1d))
|
||||||
|
## (2026-04-19)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* NCS-14 implemented insufficient moves rule ([#30](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/30)) ([b0399a4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b0399a4e489950083066c9538df9a84dcc7a4613))
|
||||||
|
* NCS-25 Add linters to keep quality up ([#27](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/27)) ([fd4e67d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fd4e67d4f782a7e955822d90cb909d0a81676fb2))
|
||||||
|
* NCS-29 JSON - Cherry Picked ([#28](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/28)) ([dbcafd2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dbcafd286993e0604a6fa286c5543581a149439e))
|
||||||
|
* NCS-30 FEN Parser using ParserCombinators ([#21](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/21)) ([b4bc72f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b4bc72f7e49f94d6e1bc805c68680e5fe8ef8e36))
|
||||||
|
* NCS-31 FastParse FEN ([#22](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/22)) ([7a045d3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/7a045d31d757bbc5aa6f4bad2664ebe8b8519cac))
|
||||||
|
* NCS-41 Bot Platform ([#33](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/33)) ([dceab08](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dceab0875e6d15f7d3958633cf5dd5b29a851b1d))
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ version = "1.0-SNAPSHOT"
|
|||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val versions = rootProject.extra["VERSIONS"] as Map<String, String>
|
val versions = rootProject.extra["VERSIONS"] as Map<String, String>
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val scoverageExcluded = rootProject.extra["SCOVERAGE_EXCLUDED"] as List<String>
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@@ -19,7 +21,7 @@ scala {
|
|||||||
|
|
||||||
scoverage {
|
scoverage {
|
||||||
scoverageVersion.set(versions["SCOVERAGE"]!!)
|
scoverageVersion.set(versions["SCOVERAGE"]!!)
|
||||||
excludedFiles.set(listOf(".*FenParserFastParse.*"))
|
excludedFiles.set(scoverageExcluded)
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType<ScalaCompile> {
|
tasks.withType<ScalaCompile> {
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=9
|
MINOR=10
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -67,3 +67,15 @@
|
|||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* NCS-32 Queenside Castle doesn't care about pieces in the way ([#23](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/23)) ([fe8e3c0](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fe8e3c05397f433bfa34d1999e9738c82790adf7))
|
* NCS-32 Queenside Castle doesn't care about pieces in the way ([#23](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/23)) ([fe8e3c0](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fe8e3c05397f433bfa34d1999e9738c82790adf7))
|
||||||
|
## (2026-04-19)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* NCS-13 Implement Threefold Repetition ([#31](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/31)) ([767d305](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/767d3051a76c266050b6335774d66e2db2273c16))
|
||||||
|
* NCS-14 implemented insufficient moves rule ([#30](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/30)) ([b0399a4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b0399a4e489950083066c9538df9a84dcc7a4613))
|
||||||
|
* NCS-25 Add linters to keep quality up ([#27](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/27)) ([fd4e67d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fd4e67d4f782a7e955822d90cb909d0a81676fb2))
|
||||||
|
* NCS-41 Bot Platform ([#33](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/33)) ([dceab08](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dceab0875e6d15f7d3958633cf5dd5b29a851b1d))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* NCS-32 Queenside Castle doesn't care about pieces in the way ([#23](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/23)) ([fe8e3c0](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fe8e3c05397f433bfa34d1999e9738c82790adf7))
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=4
|
MINOR=5
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -1,106 +0,0 @@
|
|||||||
## (2026-04-01)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* NCS-10 Implement Pawn Promotion ([#12](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/12)) ([13bfc16](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/13bfc16cfe25db78ec607db523ca6d993c13430c))
|
|
||||||
* NCS-16 Core Separation via Patterns ([#10](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/10)) ([1361dfc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1361dfc89553b146864fb8ff3526cf12cf3f293a))
|
|
||||||
## (2026-04-01)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* NCS-10 Implement Pawn Promotion ([#12](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/12)) ([13bfc16](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/13bfc16cfe25db78ec607db523ca6d993c13430c))
|
|
||||||
* NCS-16 Core Separation via Patterns ([#10](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/10)) ([1361dfc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1361dfc89553b146864fb8ff3526cf12cf3f293a))
|
|
||||||
## (2026-04-01)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* NCS-10 Implement Pawn Promotion ([#12](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/12)) ([13bfc16](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/13bfc16cfe25db78ec607db523ca6d993c13430c))
|
|
||||||
* NCS-16 Core Separation via Patterns ([#10](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/10)) ([1361dfc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1361dfc89553b146864fb8ff3526cf12cf3f293a))
|
|
||||||
* NCS-17 Implement basic ScalaFX UI ([#14](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/14)) ([3ff8031](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ff80318b4f16c59733a46498581a5c27f048287))
|
|
||||||
## (2026-04-02)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* NCS-10 Implement Pawn Promotion ([#12](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/12)) ([13bfc16](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/13bfc16cfe25db78ec607db523ca6d993c13430c))
|
|
||||||
* NCS-16 Core Separation via Patterns ([#10](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/10)) ([1361dfc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1361dfc89553b146864fb8ff3526cf12cf3f293a))
|
|
||||||
* NCS-17 Implement basic ScalaFX UI ([#14](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/14)) ([3ff8031](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ff80318b4f16c59733a46498581a5c27f048287))
|
|
||||||
* NCS-21 Write Scripts to automate certain tasks ([#15](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/15)) ([8051871](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/80518719d536a087d339fe02530825dc07f8b388))
|
|
||||||
## (2026-04-03)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* NCS-10 Implement Pawn Promotion ([#12](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/12)) ([13bfc16](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/13bfc16cfe25db78ec607db523ca6d993c13430c))
|
|
||||||
* NCS-16 Core Separation via Patterns ([#10](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/10)) ([1361dfc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1361dfc89553b146864fb8ff3526cf12cf3f293a))
|
|
||||||
* NCS-17 Implement basic ScalaFX UI ([#14](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/14)) ([3ff8031](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ff80318b4f16c59733a46498581a5c27f048287))
|
|
||||||
* NCS-21 Write Scripts to automate certain tasks ([#15](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/15)) ([8051871](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/80518719d536a087d339fe02530825dc07f8b388))
|
|
||||||
## (2026-04-07)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* NCS-10 Implement Pawn Promotion ([#12](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/12)) ([13bfc16](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/13bfc16cfe25db78ec607db523ca6d993c13430c))
|
|
||||||
* NCS-16 Core Separation via Patterns ([#10](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/10)) ([1361dfc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1361dfc89553b146864fb8ff3526cf12cf3f293a))
|
|
||||||
* NCS-17 Implement basic ScalaFX UI ([#14](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/14)) ([3ff8031](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ff80318b4f16c59733a46498581a5c27f048287))
|
|
||||||
* NCS-21 Write Scripts to automate certain tasks ([#15](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/15)) ([8051871](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/80518719d536a087d339fe02530825dc07f8b388))
|
|
||||||
## (2026-04-07)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* NCS-10 Implement Pawn Promotion ([#12](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/12)) ([13bfc16](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/13bfc16cfe25db78ec607db523ca6d993c13430c))
|
|
||||||
* NCS-16 Core Separation via Patterns ([#10](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/10)) ([1361dfc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1361dfc89553b146864fb8ff3526cf12cf3f293a))
|
|
||||||
* NCS-17 Implement basic ScalaFX UI ([#14](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/14)) ([3ff8031](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ff80318b4f16c59733a46498581a5c27f048287))
|
|
||||||
* NCS-21 Write Scripts to automate certain tasks ([#15](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/15)) ([8051871](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/80518719d536a087d339fe02530825dc07f8b388))
|
|
||||||
## (2026-04-12)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* NCS-10 Implement Pawn Promotion ([#12](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/12)) ([13bfc16](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/13bfc16cfe25db78ec607db523ca6d993c13430c))
|
|
||||||
* NCS-16 Core Separation via Patterns ([#10](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/10)) ([1361dfc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1361dfc89553b146864fb8ff3526cf12cf3f293a))
|
|
||||||
* NCS-17 Implement basic ScalaFX UI ([#14](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/14)) ([3ff8031](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ff80318b4f16c59733a46498581a5c27f048287))
|
|
||||||
* NCS-21 Write Scripts to automate certain tasks ([#15](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/15)) ([8051871](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/80518719d536a087d339fe02530825dc07f8b388))
|
|
||||||
* NCS-29 JSON - Cherry Picked ([#28](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/28)) ([dbcafd2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dbcafd286993e0604a6fa286c5543581a149439e))
|
|
||||||
## (2026-04-12)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* NCS-10 Implement Pawn Promotion ([#12](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/12)) ([13bfc16](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/13bfc16cfe25db78ec607db523ca6d993c13430c))
|
|
||||||
* NCS-16 Core Separation via Patterns ([#10](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/10)) ([1361dfc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1361dfc89553b146864fb8ff3526cf12cf3f293a))
|
|
||||||
* NCS-17 Implement basic ScalaFX UI ([#14](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/14)) ([3ff8031](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ff80318b4f16c59733a46498581a5c27f048287))
|
|
||||||
* NCS-21 Write Scripts to automate certain tasks ([#15](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/15)) ([8051871](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/80518719d536a087d339fe02530825dc07f8b388))
|
|
||||||
* NCS-25 Add linters to keep quality up ([#27](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/27)) ([fd4e67d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fd4e67d4f782a7e955822d90cb909d0a81676fb2))
|
|
||||||
* NCS-29 JSON - Cherry Picked ([#28](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/28)) ([dbcafd2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dbcafd286993e0604a6fa286c5543581a149439e))
|
|
||||||
## (2026-04-14)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* NCS-10 Implement Pawn Promotion ([#12](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/12)) ([13bfc16](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/13bfc16cfe25db78ec607db523ca6d993c13430c))
|
|
||||||
* NCS-14 implemented insufficient moves rule ([#30](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/30)) ([b0399a4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b0399a4e489950083066c9538df9a84dcc7a4613))
|
|
||||||
* NCS-16 Core Separation via Patterns ([#10](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/10)) ([1361dfc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1361dfc89553b146864fb8ff3526cf12cf3f293a))
|
|
||||||
* NCS-17 Implement basic ScalaFX UI ([#14](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/14)) ([3ff8031](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ff80318b4f16c59733a46498581a5c27f048287))
|
|
||||||
* NCS-21 Write Scripts to automate certain tasks ([#15](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/15)) ([8051871](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/80518719d536a087d339fe02530825dc07f8b388))
|
|
||||||
* NCS-25 Add linters to keep quality up ([#27](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/27)) ([fd4e67d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fd4e67d4f782a7e955822d90cb909d0a81676fb2))
|
|
||||||
* NCS-29 JSON - Cherry Picked ([#28](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/28)) ([dbcafd2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dbcafd286993e0604a6fa286c5543581a149439e))
|
|
||||||
## (2026-04-16)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* NCS-10 Implement Pawn Promotion ([#12](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/12)) ([13bfc16](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/13bfc16cfe25db78ec607db523ca6d993c13430c))
|
|
||||||
* NCS-13 Implement Threefold Repetition ([#31](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/31)) ([767d305](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/767d3051a76c266050b6335774d66e2db2273c16))
|
|
||||||
* NCS-14 implemented insufficient moves rule ([#30](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/30)) ([b0399a4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b0399a4e489950083066c9538df9a84dcc7a4613))
|
|
||||||
* NCS-16 Core Separation via Patterns ([#10](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/10)) ([1361dfc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1361dfc89553b146864fb8ff3526cf12cf3f293a))
|
|
||||||
* NCS-17 Implement basic ScalaFX UI ([#14](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/14)) ([3ff8031](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ff80318b4f16c59733a46498581a5c27f048287))
|
|
||||||
* NCS-21 Write Scripts to automate certain tasks ([#15](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/15)) ([8051871](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/80518719d536a087d339fe02530825dc07f8b388))
|
|
||||||
* NCS-25 Add linters to keep quality up ([#27](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/27)) ([fd4e67d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fd4e67d4f782a7e955822d90cb909d0a81676fb2))
|
|
||||||
* NCS-29 JSON - Cherry Picked ([#28](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/28)) ([dbcafd2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dbcafd286993e0604a6fa286c5543581a149439e))
|
|
||||||
## (2026-04-19)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* NCS-10 Implement Pawn Promotion ([#12](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/12)) ([13bfc16](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/13bfc16cfe25db78ec607db523ca6d993c13430c))
|
|
||||||
* NCS-13 Implement Threefold Repetition ([#31](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/31)) ([767d305](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/767d3051a76c266050b6335774d66e2db2273c16))
|
|
||||||
* NCS-14 implemented insufficient moves rule ([#30](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/30)) ([b0399a4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b0399a4e489950083066c9538df9a84dcc7a4613))
|
|
||||||
* NCS-16 Core Separation via Patterns ([#10](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/10)) ([1361dfc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1361dfc89553b146864fb8ff3526cf12cf3f293a))
|
|
||||||
* NCS-17 Implement basic ScalaFX UI ([#14](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/14)) ([3ff8031](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ff80318b4f16c59733a46498581a5c27f048287))
|
|
||||||
* NCS-21 Write Scripts to automate certain tasks ([#15](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/15)) ([8051871](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/80518719d536a087d339fe02530825dc07f8b388))
|
|
||||||
* NCS-25 Add linters to keep quality up ([#27](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/27)) ([fd4e67d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fd4e67d4f782a7e955822d90cb909d0a81676fb2))
|
|
||||||
* NCS-29 JSON - Cherry Picked ([#28](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/28)) ([dbcafd2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dbcafd286993e0604a6fa286c5543581a149439e))
|
|
||||||
* NCS-41 Bot Platform ([#33](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/33)) ([dceab08](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dceab0875e6d15f7d3958633cf5dd5b29a851b1d))
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
import org.gradle.api.file.DuplicatesStrategy
|
|
||||||
import org.gradle.jvm.tasks.Jar
|
|
||||||
|
|
||||||
plugins {
|
|
||||||
id("scala")
|
|
||||||
id("org.scoverage")
|
|
||||||
application
|
|
||||||
}
|
|
||||||
|
|
||||||
group = "de.nowchess"
|
|
||||||
version = "1.0-SNAPSHOT"
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
val versions = rootProject.extra["VERSIONS"] as Map<String, String>
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
|
|
||||||
scala {
|
|
||||||
scalaVersion = versions["SCALA3"]!!
|
|
||||||
}
|
|
||||||
|
|
||||||
scoverage {
|
|
||||||
scoverageVersion.set(versions["SCOVERAGE"]!!)
|
|
||||||
excludedPackages.set(listOf("de\\.nowchess\\.ui\\..*"))
|
|
||||||
}
|
|
||||||
|
|
||||||
application {
|
|
||||||
mainClass.set("de.nowchess.ui.Main")
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType<ScalaCompile> {
|
|
||||||
scalaCompileOptions.additionalParameters = listOf("-encoding", "UTF-8")
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.named<JavaExec>("run") {
|
|
||||||
jvmArgs("-Dfile.encoding=UTF-8", "-Dstdout.encoding=UTF-8", "-Dstderr.encoding=UTF-8")
|
|
||||||
standardInput = System.`in`
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.named<Jar>("jar") {
|
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
|
|
||||||
implementation("org.scala-lang:scala3-compiler_3") {
|
|
||||||
version {
|
|
||||||
strictly(versions["SCALA3"]!!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
implementation("org.scala-lang:scala3-library_3") {
|
|
||||||
version {
|
|
||||||
strictly(versions["SCALA3"]!!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
implementation(project(":modules:core"))
|
|
||||||
implementation(project(":modules:rule"))
|
|
||||||
implementation(project(":modules:api"))
|
|
||||||
implementation(project(":modules:io"))
|
|
||||||
implementation(project(":modules:bot"))
|
|
||||||
|
|
||||||
// ScalaFX dependencies
|
|
||||||
implementation("org.scalafx:scalafx_3:${versions["SCALAFX"]!!}")
|
|
||||||
|
|
||||||
// JavaFX dependencies for the current platform
|
|
||||||
val javaFXVersion = versions["JAVAFX"]!!
|
|
||||||
val osName = System.getProperty("os.name").lowercase()
|
|
||||||
val platform = when {
|
|
||||||
osName.contains("win") -> "win"
|
|
||||||
osName.contains("mac") -> "mac"
|
|
||||||
osName.contains("linux") -> "linux"
|
|
||||||
else -> "linux"
|
|
||||||
}
|
|
||||||
|
|
||||||
listOf("base", "controls", "graphics", "media").forEach { module ->
|
|
||||||
implementation("org.openjfx:javafx-$module:$javaFXVersion:$platform")
|
|
||||||
}
|
|
||||||
|
|
||||||
testImplementation(platform("org.junit:junit-bom:${versions["JUNIT_BOM"]!!}"))
|
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
|
||||||
testImplementation("org.scalatest:scalatest_3:${versions["SCALATEST"]!!}")
|
|
||||||
testImplementation("co.helmethair:scalatest-junit-runner:${versions["SCALATEST_JUNIT"]!!}")
|
|
||||||
|
|
||||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.test {
|
|
||||||
useJUnitPlatform {
|
|
||||||
includeEngines("scalatest")
|
|
||||||
testLogging {
|
|
||||||
events("skipped", "failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finalizedBy(tasks.reportScoverage)
|
|
||||||
}
|
|
||||||
tasks.reportScoverage {
|
|
||||||
dependsOn(tasks.test)
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 161 B |
|
Before Width: | Height: | Size: 188 B |
|
Before Width: | Height: | Size: 188 B |
|
Before Width: | Height: | Size: 286 B |
|
Before Width: | Height: | Size: 245 B |
|
Before Width: | Height: | Size: 266 B |
|
Before Width: | Height: | Size: 297 B |
|
Before Width: | Height: | Size: 258 B |
|
Before Width: | Height: | Size: 263 B |
|
Before Width: | Height: | Size: 313 B |
|
Before Width: | Height: | Size: 251 B |
|
Before Width: | Height: | Size: 275 B |
|
Before Width: | Height: | Size: 305 B |
|
Before Width: | Height: | Size: 281 B |
|
Before Width: | Height: | Size: 280 B |
@@ -1,30 +0,0 @@
|
|||||||
/* Arabian Chess GUI Styles */
|
|
||||||
|
|
||||||
.root {
|
|
||||||
-fx-font-family: "Comic Sans MS", "Comic Sans", cursive;
|
|
||||||
-fx-background-color: #F3C8A0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
-fx-background-radius: 8;
|
|
||||||
-fx-padding: 8 16 8 16;
|
|
||||||
-fx-font-family: "Comic Sans MS", cursive;
|
|
||||||
-fx-font-size: 12px;
|
|
||||||
-fx-cursor: hand;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button:hover {
|
|
||||||
-fx-opacity: 0.8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label {
|
|
||||||
-fx-font-family: "Comic Sans MS", cursive;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-pane {
|
|
||||||
-fx-background-color: #F3C8A0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-pane .content {
|
|
||||||
-fx-font-family: "Comic Sans MS", cursive;
|
|
||||||
}
|
|
||||||