Compare commits
48 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3efebd5ed0 | |||
| 0229147f4d | |||
| 3a0cb92256 | |||
| 39c9e492ce | |||
| 2404e6164c | |||
| 6a143a462a | |||
| 5399c9bffb | |||
| 6113432a14 | |||
| 952cf00413 | |||
| 34b9933046 | |||
| e5fe7d07a5 | |||
| c987d8e258 | |||
| 3f2d2bb4c9 | |||
| 04a3ad721c | |||
| 590924254e | |||
| 67511fc649 | |||
| 093134d36c | |||
| ffeb3ce338 | |||
| 52b171c7af | |||
| a386f57c21 | |||
| 3ca2afbb4b | |||
| b5a2966ada | |||
| 74a4fce0ca | |||
| 8fc97bde02 | |||
| 2d75b2e80e | |||
| f088c4e9ff | |||
| 8a1cf909d4 | |||
| 33e785d22a | |||
| d16cec176b | |||
| 8744bee2dd | |||
| 5f4d33f3ca | |||
| 767d3051a7 | |||
| b2e62dc60c | |||
| b0399a4e48 | |||
| ec2ab2f365 | |||
| fd4e67d4f7 | |||
| 3cb3160731 | |||
| dbcafd2869 | |||
| 3ecb2c9d66 | |||
| 9ad11fb97a | |||
| e158b0a7f0 | |||
| f1c9df16b6 | |||
| 9d11d25b99 | |||
| 7a045d31d7 | |||
| b518c704fa | |||
| fe8e3c0539 | |||
| 1b16adcc72 | |||
| b4bc72f7e4 |
@@ -0,0 +1,669 @@
|
||||
# NowChessSystems — AI Context Map
|
||||
|
||||
> **Stack:** raw-http | none | unknown | scala
|
||||
|
||||
> 0 routes + 40 rpc | 0 models | 0 components | 146 lib files | 1 env vars | 1 middleware
|
||||
> **Token savings:** this file is ~0 tokens. Without it, AI exploration would cost ~0 tokens. **Saves ~0 tokens per conversation.**
|
||||
|
||||
---
|
||||
|
||||
# Routes
|
||||
|
||||
## gRPC
|
||||
|
||||
- `/CoordinatorService/BatchResubscribeGames` (BatchResubscribeRequest) → BatchResubscribeResponse
|
||||
- `/CoordinatorService/UnsubscribeGames` (UnsubscribeGamesRequest) → UnsubscribeGamesResponse
|
||||
- `/CoordinatorService/EvictGames` (EvictGamesRequest) → EvictGamesResponse
|
||||
- `/CoordinatorService/DrainInstance` (DrainInstanceRequest) → DrainInstanceResponse
|
||||
- `/CoordinatorService/BatchResubscribeGames` (BatchResubscribeRequest) → BatchResubscribeResponse
|
||||
- `/CoordinatorService/UnsubscribeGames` (UnsubscribeGamesRequest) → UnsubscribeGamesResponse
|
||||
- `/CoordinatorService/EvictGames` (EvictGamesRequest) → EvictGamesResponse
|
||||
- `/CoordinatorService/DrainInstance` (DrainInstanceRequest) → DrainInstanceResponse
|
||||
- `/IoService/ImportFen` (ProtoImportFenRequest) → ProtoGameContext
|
||||
- `/IoService/ImportPgn` (ProtoImportPgnRequest) → ProtoGameContext
|
||||
- `/IoService/ExportCombined` (ProtoGameContext) → ProtoCombinedExport
|
||||
- `/IoService/ExportFen` (ProtoGameContext) → ProtoStringResult
|
||||
- `/IoService/ExportPgn` (ProtoGameContext) → ProtoStringResult
|
||||
- `/RuleService/CandidateMoves` (ProtoSquareRequest) → ProtoMoveList
|
||||
- `/RuleService/LegalMoves` (ProtoSquareRequest) → ProtoMoveList
|
||||
- `/RuleService/AllLegalMoves` (ProtoGameContext) → ProtoMoveList
|
||||
- `/RuleService/IsCheck` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsCheckmate` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsStalemate` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsInsufficientMaterial` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsFiftyMoveRule` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsThreefoldRepetition` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/ApplyMove` (ProtoMoveRequest) → ProtoGameContext
|
||||
- `/RuleService/PostMoveStatus` (ProtoGameContext) → ProtoPostMoveStatus
|
||||
- `/IoService/ImportFen` (ProtoImportFenRequest) → ProtoGameContext
|
||||
- `/IoService/ImportPgn` (ProtoImportPgnRequest) → ProtoGameContext
|
||||
- `/IoService/ExportCombined` (ProtoGameContext) → ProtoCombinedExport
|
||||
- `/IoService/ExportFen` (ProtoGameContext) → ProtoStringResult
|
||||
- `/IoService/ExportPgn` (ProtoGameContext) → ProtoStringResult
|
||||
- `/RuleService/CandidateMoves` (ProtoSquareRequest) → ProtoMoveList
|
||||
- `/RuleService/LegalMoves` (ProtoSquareRequest) → ProtoMoveList
|
||||
- `/RuleService/AllLegalMoves` (ProtoGameContext) → ProtoMoveList
|
||||
- `/RuleService/IsCheck` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsCheckmate` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsStalemate` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsInsufficientMaterial` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsFiftyMoveRule` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsThreefoldRepetition` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/ApplyMove` (ProtoMoveRequest) → ProtoGameContext
|
||||
- `/RuleService/PostMoveStatus` (ProtoGameContext) → ProtoPostMoveStatus
|
||||
|
||||
---
|
||||
|
||||
# Libraries
|
||||
|
||||
- `jacoco-reporter/scoverage_coverage_gaps.py`
|
||||
- function parse_scoverage_xml: (xml_path) -> tuple[dict, list[ClassGap]]
|
||||
- function format_agent: (project_stats, classes) -> str
|
||||
- function format_json: (project_stats, classes) -> str
|
||||
- function format_markdown: (project_stats, classes) -> str
|
||||
- function format_module_gaps: (module_name, classes, stmt_pct) -> str
|
||||
- function run_scan_modules: (modules_dir, package_filter, min_coverage) -> None
|
||||
- _...4 more_
|
||||
- `jacoco-reporter/test_gaps.py`
|
||||
- function parse_suite_xml: (xml_path) -> SuiteResult
|
||||
- function load_module: (module_dir, results_subdir) -> Optional[ModuleResult]
|
||||
- function format_module: (mod) -> str
|
||||
- function run: (modules_dir, results_subdir, module_filter) -> None
|
||||
- function main: () -> None
|
||||
- class TestCase
|
||||
- _...2 more_
|
||||
- `modules/account/src/main/scala/de/nowchess/account/client/CoreGameClient.scala` — class CoreGameClient, function createGame
|
||||
- `modules/account/src/main/scala/de/nowchess/account/config/JacksonConfig.scala` — class JacksonConfig, function customize
|
||||
- `modules/account/src/main/scala/de/nowchess/account/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
|
||||
- `modules/account/src/main/scala/de/nowchess/account/domain/Challenge.scala`
|
||||
- class Challenge
|
||||
- function gameIdOpt
|
||||
- function declineReasonOpt
|
||||
- function timeControlLimitOpt
|
||||
- function timeControlIncrementOpt
|
||||
- `modules/account/src/main/scala/de/nowchess/account/domain/ChallengeColorConverter.scala` — class ChallengeColorConverter
|
||||
- `modules/account/src/main/scala/de/nowchess/account/domain/ChallengeStatusConverter.scala` — class ChallengeStatusConverter
|
||||
- `modules/account/src/main/scala/de/nowchess/account/domain/DeclineReasonConverter.scala` — class DeclineReasonConverter
|
||||
- `modules/account/src/main/scala/de/nowchess/account/domain/TimeControl.scala` — class TimeControl
|
||||
- `modules/account/src/main/scala/de/nowchess/account/domain/UserAccount.scala`
|
||||
- class UserAccount
|
||||
- function getBotAccounts
|
||||
- class BotAccount
|
||||
- class OfficialBotAccount
|
||||
- `modules/account/src/main/scala/de/nowchess/account/error/AccountError.scala` — function message
|
||||
- `modules/account/src/main/scala/de/nowchess/account/error/ChallengeError.scala` — function message
|
||||
- `modules/account/src/main/scala/de/nowchess/account/filter/AlreadyLoggedInFilter.scala` — class AlreadyLoggedInFilter
|
||||
- `modules/account/src/main/scala/de/nowchess/account/repository/AccountRepository.scala`
|
||||
- class UserAccountRepository
|
||||
- function findByUsername
|
||||
- function findById
|
||||
- function persist
|
||||
- function findByEmail
|
||||
- function findAll
|
||||
- _...12 more_
|
||||
- `modules/account/src/main/scala/de/nowchess/account/repository/ChallengeRepository.scala`
|
||||
- class ChallengeRepository
|
||||
- function findActiveByChallengerId
|
||||
- function findActiveByDestUserId
|
||||
- function findDuplicateChallenge
|
||||
- function findById
|
||||
- function persist
|
||||
- _...1 more_
|
||||
- `modules/account/src/main/scala/de/nowchess/account/resource/AccountResource.scala`
|
||||
- class AccountResource
|
||||
- function register
|
||||
- function login
|
||||
- function me
|
||||
- function publicProfile
|
||||
- function banUser
|
||||
- _...10 more_
|
||||
- `modules/account/src/main/scala/de/nowchess/account/resource/ChallengeResource.scala`
|
||||
- class ChallengeResource
|
||||
- function create
|
||||
- function list
|
||||
- function accept
|
||||
- function decline
|
||||
- function cancel
|
||||
- `modules/account/src/main/scala/de/nowchess/account/service/AccountService.scala`
|
||||
- class AccountService
|
||||
- function register
|
||||
- function login
|
||||
- function findByUsername
|
||||
- function findById
|
||||
- function createBotAccount
|
||||
- _...11 more_
|
||||
- `modules/account/src/main/scala/de/nowchess/account/service/ChallengeService.scala`
|
||||
- class ChallengeService
|
||||
- function create
|
||||
- function accept
|
||||
- function decline
|
||||
- function cancel
|
||||
- function listForUser
|
||||
- _...1 more_
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Board.scala`
|
||||
- class Board
|
||||
- function apply
|
||||
- function pieceAt
|
||||
- function updated
|
||||
- function removed
|
||||
- function withMove
|
||||
- _...2 more_
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/CastlingRights.scala`
|
||||
- function hasAnyRights
|
||||
- function hasRights
|
||||
- function revokeColor
|
||||
- function revokeKingSide
|
||||
- function revokeQueenSide
|
||||
- class CastlingRights
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Color.scala` — function opposite, function label
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Piece.scala` — class Piece
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/PieceType.scala` — function label
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Square.scala`
|
||||
- class Square
|
||||
- function fromAlgebraic
|
||||
- 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/error/GameError.scala` — function message
|
||||
- `modules/api/src/main/scala/de/nowchess/api/game/ClockState.scala`
|
||||
- function activeColor
|
||||
- function afterMove
|
||||
- function remainingMs
|
||||
- function remainingMs
|
||||
- function afterMove
|
||||
- function remainingMs
|
||||
- _...3 more_
|
||||
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`
|
||||
- function kingSquare
|
||||
- function withBoard
|
||||
- function withTurn
|
||||
- function withCastlingRights
|
||||
- function withEnPassantSquare
|
||||
- function withHalfMoveClock
|
||||
- _...4 more_
|
||||
- `modules/api/src/main/scala/de/nowchess/api/io/GameContextExport.scala` — class GameContextExport, function exportGameContext
|
||||
- `modules/api/src/main/scala/de/nowchess/api/io/GameContextImport.scala` — class GameContextImport, function importGameContext
|
||||
- `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`
|
||||
- class ApiResponse
|
||||
- function error
|
||||
- function totalPages
|
||||
- `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala`
|
||||
- class RuleSet
|
||||
- function candidateMoves
|
||||
- function legalMoves
|
||||
- function allLegalMoves
|
||||
- function isCheck
|
||||
- function isCheckmate
|
||||
- _...6 more_
|
||||
- `modules/bot/python/nnue.py`
|
||||
- function get_weights_dir: ()
|
||||
- function get_data_dir: ()
|
||||
- function list_checkpoints: ()
|
||||
- function migrate_legacy_data: ()
|
||||
- function show_header: ()
|
||||
- function show_checkpoints_table: ()
|
||||
- _...10 more_
|
||||
- `modules/bot/python/src/dataset.py`
|
||||
- function get_datasets_dir: () -> Path
|
||||
- function next_dataset_version: () -> int
|
||||
- function list_datasets: () -> List[Tuple[int, Dict]]
|
||||
- function load_dataset_metadata: (version) -> Optional[Dict]
|
||||
- function save_dataset_metadata: (version, metadata) -> None
|
||||
- function create_dataset: (version, labeled_jsonl_path, sources, stockfish_depth) -> Path
|
||||
- _...4 more_
|
||||
- `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/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`
|
||||
- function download_and_extract_puzzle_db: (url, output_dir)
|
||||
- function extract_puzzle_positions: (puzzle_csv, max_puzzles) -> Set[str]
|
||||
- function load_positions_from_file: (file_path) -> Set[str]
|
||||
- function merge_positions: (tactical, other, output_file)
|
||||
- function extract_tactical_only: (puzzle_csv, output_file, max_puzzles) -> int
|
||||
- function interactive_merge_positions: (puzzle_csv, output_file, max_puzzles)
|
||||
- `modules/bot/python/src/train.py`
|
||||
- function fen_to_features: (fen)
|
||||
- function find_next_version: (base_name)
|
||||
- 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, 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, hidden_sizes)
|
||||
- class NNUEDataset
|
||||
- _...1 more_
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/BotController.scala`
|
||||
- class BotController
|
||||
- function getBot
|
||||
- function listBots
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/BotMoveRepetition.scala`
|
||||
- class BotMoveRepetition
|
||||
- function blockedMoves
|
||||
- function repeatedMove
|
||||
- function filterAllowed
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/Config.scala` — class Config
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/ai/Evaluation.scala`
|
||||
- class Evaluation
|
||||
- class CHECKMATE_SCORE
|
||||
- class DRAW_SCORE
|
||||
- function evaluate
|
||||
- function initAccumulator
|
||||
- function copyAccumulator
|
||||
- _...2 more_
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/bots/classic/EvaluationClassic.scala`
|
||||
- class EvaluationClassic
|
||||
- function evaluate
|
||||
- function countRay
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala` — class EvaluationNNUE, function evaluate
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NNUE.scala`
|
||||
- class NNUE
|
||||
- function initAccumulator
|
||||
- function pushAccumulator
|
||||
- function copyAccumulator
|
||||
- function recomputeAccumulator
|
||||
- function validateAccumulator
|
||||
- _...4 more_
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiLoader.scala`
|
||||
- class NbaiLoader
|
||||
- function load
|
||||
- function loadDefault
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiMigrator.scala` — class NbaiMigrator, function migrateFromBin
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiModel.scala`
|
||||
- function toJson
|
||||
- class NbaiMetadata
|
||||
- function fromJson
|
||||
- function str
|
||||
- function num
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiWriter.scala` — class NbaiWriter, function write
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/logic/AlphaBetaSearch.scala`
|
||||
- function bestMove
|
||||
- function bestMove
|
||||
- function bestMoveWithTime
|
||||
- function bestMoveWithTime
|
||||
- function loop
|
||||
- function loop
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/logic/MoveOrdering.scala`
|
||||
- class MoveOrdering
|
||||
- class OrderingContext
|
||||
- function addKillerMove
|
||||
- function getKillerMoves
|
||||
- function addHistory
|
||||
- function getHistory
|
||||
- _...3 more_
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/logic/TranspositionTable.scala`
|
||||
- function advance
|
||||
- function probe
|
||||
- function store
|
||||
- function clear
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/util/PolyglotBook.scala` — function probe, function select
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/util/PolyglotHash.scala` — class PolyglotHash, function hash
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/util/ZobristHash.scala`
|
||||
- class ZobristHash
|
||||
- function hash
|
||||
- function nextHash
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/CoordinatorApp.scala` — class CoordinatorApp
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/config/BeansProducer.scala`
|
||||
- class BeansProducer
|
||||
- function redissonClient
|
||||
- function kubernetesClient
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/config/CoordinatorConfig.scala`
|
||||
- class CoordinatorConfig
|
||||
- function maxGamesPerCore
|
||||
- function maxDeviationPercent
|
||||
- function rebalanceInterval
|
||||
- function rebalanceMinInterval
|
||||
- function heartbeatTtl
|
||||
- _...11 more_
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/config/JacksonConfig.scala` — class JacksonConfig, function customize
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/grpc/CoordinatorGrpcServer.scala` — class CoordinatorGrpcServer
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/grpc/CoreGrpcClient.scala`
|
||||
- class CoreGrpcClient
|
||||
- function shutdown
|
||||
- function batchResubscribeGames
|
||||
- function unsubscribeGames
|
||||
- function evictGames
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/resource/CoordinatorResource.scala`
|
||||
- class CoordinatorResource
|
||||
- function listInstances
|
||||
- function getMetrics
|
||||
- function triggerRebalance
|
||||
- function triggerFailover
|
||||
- function triggerScaleUp
|
||||
- _...1 more_
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/AutoScaler.scala`
|
||||
- class AutoScaler
|
||||
- function checkAndScale
|
||||
- function scaleUp
|
||||
- function scaleDown
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/CacheEvictionManager.scala`
|
||||
- class CacheEvictionManager
|
||||
- function setRedisPrefix
|
||||
- function evictStaleGames
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/FailoverService.scala`
|
||||
- class FailoverService
|
||||
- function setRedisPrefix
|
||||
- function onInstanceStreamDropped
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/HealthMonitor.scala`
|
||||
- class HealthMonitor
|
||||
- function setRedisPrefix
|
||||
- function checkInstanceHealth
|
||||
- function watchK8sPods
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/InstanceRegistry.scala`
|
||||
- class InstanceRegistry
|
||||
- function setRedisPrefix
|
||||
- function getInstance
|
||||
- function getAllInstances
|
||||
- function updateInstanceFromRedis
|
||||
- function markInstanceDead
|
||||
- _...1 more_
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/LoadBalancer.scala`
|
||||
- class LoadBalancer
|
||||
- function setRedisPrefix
|
||||
- function shouldRebalance
|
||||
- function rebalance
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/adapter/RuleSetRestAdapter.scala`
|
||||
- class RuleSetRestAdapter
|
||||
- function candidateMoves
|
||||
- function legalMoves
|
||||
- function allLegalMoves
|
||||
- function isCheck
|
||||
- function isCheckmate
|
||||
- _...5 more_
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/client/IoServiceClient.scala`
|
||||
- class IoServiceClient
|
||||
- function importFen
|
||||
- function importPgn
|
||||
- function exportFen
|
||||
- function exportPgn
|
||||
- function exportCombined
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/client/RuleServiceClient.scala`
|
||||
- class RuleServiceClient
|
||||
- function candidateMoves
|
||||
- function legalMoves
|
||||
- function allLegalMoves
|
||||
- function isCheck
|
||||
- function isCheckmate
|
||||
- _...6 more_
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/client/StoreServiceClient.scala` — class StoreServiceClient, function getGame
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/config/JacksonConfig.scala` — class JacksonConfig, function customize
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/config/RedisConfig.scala` — class RedisConfig
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/config/RedissonProducer.scala`
|
||||
- class RedissonProducer
|
||||
- function produceRedissonClient
|
||||
- function shutdown
|
||||
- `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`
|
||||
- class GameEngine
|
||||
- function board
|
||||
- function turn
|
||||
- function context
|
||||
- function pendingDrawOfferBy
|
||||
- function currentClockState
|
||||
- _...22 more_
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/exception/ApiException.scala`
|
||||
- class ApiException
|
||||
- class GameNotFoundException
|
||||
- class BadRequestException
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/exception/ApiExceptionMapper.scala` — class ApiExceptionMapper, function toResponse
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/grpc/CoordinatorServiceHandler.scala` — class CoordinatorServiceHandler
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/grpc/CoreProtoMapper.scala`
|
||||
- class CoreProtoMapper
|
||||
- function toProtoColor
|
||||
- function fromProtoColor
|
||||
- function toProtoPieceType
|
||||
- function fromProtoPieceType
|
||||
- function toProtoMoveKind
|
||||
- _...9 more_
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/grpc/IoGrpcClientWrapper.scala`
|
||||
- class IoGrpcClientWrapper
|
||||
- function exportCombined
|
||||
- function importFen
|
||||
- function importPgn
|
||||
- function exportFen
|
||||
- function exportPgn
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/grpc/RuleSetGrpcAdapter.scala`
|
||||
- class RuleSetGrpcAdapter
|
||||
- function candidateMoves
|
||||
- function legalMoves
|
||||
- function allLegalMoves
|
||||
- function isCheck
|
||||
- function isCheckmate
|
||||
- _...5 more_
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/observer/Observer.scala`
|
||||
- function context
|
||||
- class Observer
|
||||
- function onGameEvent
|
||||
- class Observable
|
||||
- function subscribe
|
||||
- function unsubscribe
|
||||
- _...1 more_
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/redis/C2sMessage.scala` — class C2sMessage
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/redis/GameRedisPublisher.scala` — class GameRedisPublisher, function onGameEvent
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/redis/GameRedisSubscriberManager.scala`
|
||||
- class GameRedisSubscriberManager
|
||||
- function subscribeGame
|
||||
- function onMessage
|
||||
- function unsubscribeGame
|
||||
- function batchResubscribeGames
|
||||
- function unsubscribeGames
|
||||
- _...3 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/RedisGameRegistry.scala`
|
||||
- class RedisGameRegistry
|
||||
- function generateId
|
||||
- function store
|
||||
- function get
|
||||
- function update
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/resource/GameDtoMapper.scala`
|
||||
- class GameDtoMapper
|
||||
- function statusOf
|
||||
- function moveToUci
|
||||
- function toPlayerDto
|
||||
- function toClockDto
|
||||
- function toGameStateDto
|
||||
- _...1 more_
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/resource/GameResource.scala`
|
||||
- class GameResource
|
||||
- function onGameEvent
|
||||
- function createGame
|
||||
- function getGame
|
||||
- function resignGame
|
||||
- function makeMove
|
||||
- _...9 more_
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/service/InstanceHeartbeatService.scala`
|
||||
- class InstanceHeartbeatService
|
||||
- function onStart
|
||||
- function onShutdown
|
||||
- function setRedisPrefix
|
||||
- function setSubscriptionCount
|
||||
- function setLocalCacheSize
|
||||
- _...2 more_
|
||||
- `modules/io/src/main/scala/de/nowchess/io/GameFileService.scala`
|
||||
- class GameFileService
|
||||
- function saveGameToFile
|
||||
- function loadGameFromFile
|
||||
- class FileSystemGameService
|
||||
- function saveGameToFile
|
||||
- function loadGameFromFile
|
||||
- `modules/io/src/main/scala/de/nowchess/io/fen/FenExporter.scala`
|
||||
- class FenExporter
|
||||
- function boardToFen
|
||||
- function gameContextToFen
|
||||
- function exportGameContext
|
||||
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParser.scala`
|
||||
- class FenParser
|
||||
- function parseFen
|
||||
- function importGameContext
|
||||
- function parseBoard
|
||||
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParserCombinators.scala`
|
||||
- class FenParserCombinators
|
||||
- function parseFen
|
||||
- function parseBoard
|
||||
- function importGameContext
|
||||
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParserFastParse.scala`
|
||||
- class FenParserFastParse
|
||||
- function parseFen
|
||||
- function parseBoard
|
||||
- function importGameContext
|
||||
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParserSupport.scala` — function buildSquares
|
||||
- `modules/io/src/main/scala/de/nowchess/io/grpc/IoGrpcService.scala` — class IoGrpcService
|
||||
- `modules/io/src/main/scala/de/nowchess/io/grpc/IoProtoMapper.scala`
|
||||
- class IoProtoMapper
|
||||
- function toProtoColor
|
||||
- function fromProtoColor
|
||||
- function toProtoPieceType
|
||||
- function fromProtoPieceType
|
||||
- function toProtoMoveKind
|
||||
- _...9 more_
|
||||
- `modules/io/src/main/scala/de/nowchess/io/json/JsonExporter.scala` — class JsonExporter, function exportGameContext
|
||||
- `modules/io/src/main/scala/de/nowchess/io/json/JsonParser.scala` — class JsonParser, function importGameContext
|
||||
- `modules/io/src/main/scala/de/nowchess/io/pgn/PgnExporter.scala`
|
||||
- class PgnExporter
|
||||
- function exportGameContext
|
||||
- function exportGame
|
||||
- `modules/io/src/main/scala/de/nowchess/io/pgn/PgnParser.scala`
|
||||
- class PgnParser
|
||||
- function validatePgn
|
||||
- function importGameContext
|
||||
- function parsePgn
|
||||
- function parseAlgebraicMove
|
||||
- `modules/io/src/main/scala/de/nowchess/io/service/config/JacksonConfig.scala` — class JacksonConfig, function customize
|
||||
- `modules/io/src/main/scala/de/nowchess/io/service/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
|
||||
- `modules/io/src/main/scala/de/nowchess/io/service/resource/IoResource.scala`
|
||||
- class IoResource
|
||||
- function importFen
|
||||
- function importPgn
|
||||
- function exportFen
|
||||
- function exportPgn
|
||||
- function exportCombined
|
||||
- `modules/json/src/main/scala/de/nowchess/json/ChessJacksonModule.scala` — class ChessJacksonModule
|
||||
- `modules/json/src/main/scala/de/nowchess/json/GameResultDeserializer.scala` — class GameResultDeserializer
|
||||
- `modules/json/src/main/scala/de/nowchess/json/GameResultSerializer.scala` — class GameResultSerializer
|
||||
- `modules/json/src/main/scala/de/nowchess/json/MoveTypeDeserializer.scala` — class MoveTypeDeserializer
|
||||
- `modules/json/src/main/scala/de/nowchess/json/MoveTypeSerializer.scala` — class MoveTypeSerializer
|
||||
- `modules/json/src/main/scala/de/nowchess/json/SquareDeserializer.scala` — class SquareDeserializer
|
||||
- `modules/json/src/main/scala/de/nowchess/json/SquareKeyDeserializer.scala` — class SquareKeyDeserializer
|
||||
- `modules/json/src/main/scala/de/nowchess/json/SquareKeySerializer.scala` — class SquareKeySerializer
|
||||
- `modules/json/src/main/scala/de/nowchess/json/SquareSerializer.scala` — class SquareSerializer
|
||||
- `modules/rule/src/main/scala/de/nowchess/rules/config/JacksonConfig.scala` — class JacksonConfig, function customize
|
||||
- `modules/rule/src/main/scala/de/nowchess/rules/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
|
||||
- `modules/rule/src/main/scala/de/nowchess/rules/grpc/ProtoMapper.scala`
|
||||
- class ProtoMapper
|
||||
- function toProtoColor
|
||||
- function fromProtoColor
|
||||
- function toProtoPieceType
|
||||
- function fromProtoPieceType
|
||||
- function toProtoMoveKind
|
||||
- _...9 more_
|
||||
- `modules/rule/src/main/scala/de/nowchess/rules/grpc/RuleGrpcService.scala` — class RuleGrpcService
|
||||
- `modules/rule/src/main/scala/de/nowchess/rules/resource/RuleSetResource.scala`
|
||||
- class RuleSetResource
|
||||
- function candidateMoves
|
||||
- function legalMoves
|
||||
- function allLegalMoves
|
||||
- function isCheck
|
||||
- function isCheckmate
|
||||
- _...6 more_
|
||||
- `modules/rule/src/main/scala/de/nowchess/rules/sets/DefaultRules.scala` — class DefaultRules, function positionOf
|
||||
- `modules/store/src/main/scala/de/nowchess/store/config/JacksonConfig.scala` — class JacksonConfig, function customize
|
||||
- `modules/store/src/main/scala/de/nowchess/store/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
|
||||
- `modules/store/src/main/scala/de/nowchess/store/config/RedisConfig.scala` — class RedisConfig
|
||||
- `modules/store/src/main/scala/de/nowchess/store/config/RedissonProducer.scala`
|
||||
- class RedissonProducer
|
||||
- function redissonClient
|
||||
- function close
|
||||
- `modules/store/src/main/scala/de/nowchess/store/domain/GameRecord.scala` — class GameRecord
|
||||
- `modules/store/src/main/scala/de/nowchess/store/redis/GameWritebackStreamListener.scala`
|
||||
- class GameWritebackStreamListener
|
||||
- function startListening
|
||||
- function onMessage
|
||||
- `modules/store/src/main/scala/de/nowchess/store/repository/GameRecordRepository.scala`
|
||||
- class GameRecordRepository
|
||||
- function findByGameId
|
||||
- function persist
|
||||
- function merge
|
||||
- `modules/store/src/main/scala/de/nowchess/store/resource/StoreGameResource.scala` — class StoreGameResource, function getGame
|
||||
- `modules/store/src/main/scala/de/nowchess/store/service/GameWritebackService.scala` — class GameWritebackService, function writeBack
|
||||
- `modules/ws/src/main/scala/de/nowchess/ws/config/JacksonConfig.scala` — class JacksonConfig, function customize
|
||||
- `modules/ws/src/main/scala/de/nowchess/ws/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
|
||||
- `modules/ws/src/main/scala/de/nowchess/ws/config/RedisConfig.scala` — class RedisConfig
|
||||
- `modules/ws/src/main/scala/de/nowchess/ws/config/RedissonProducer.scala`
|
||||
- class RedissonProducer
|
||||
- function produceRedissonClient
|
||||
- function shutdown
|
||||
- `modules/ws/src/main/scala/de/nowchess/ws/resource/GameWebSocketResource.scala`
|
||||
- class GameWebSocketResource
|
||||
- function onOpen
|
||||
- function onMessage
|
||||
- function onTextMessage
|
||||
- function onClose
|
||||
|
||||
---
|
||||
|
||||
# Config
|
||||
|
||||
## Environment Variables
|
||||
|
||||
- `STOCKFISH_PATH` **required** — modules/bot/python/nnue.py
|
||||
|
||||
---
|
||||
|
||||
# Middleware
|
||||
|
||||
## custom
|
||||
- generate — `modules/bot/python/src/generate.py`
|
||||
|
||||
---
|
||||
|
||||
# Dependency Graph
|
||||
|
||||
## Most Imported Files (change these carefully)
|
||||
|
||||
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala` — imported by **76** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Square.scala` — imported by **57** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/move/Move.scala` — imported by **55** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Color.scala` — imported by **47** files
|
||||
- `modules/rule/src/main/scala/de/nowchess/rules/sets/DefaultRules.scala` — imported by **28** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Board.scala` — imported by **20** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/PieceType.scala` — imported by **20** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Piece.scala` — imported by **20** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/game/DrawReason.scala` — imported by **18** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/game/GameResult.scala` — imported by **18** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala` — imported by **14** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/CastlingRights.scala` — imported by **13** files
|
||||
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParser.scala` — imported by **11** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/player/PlayerInfo.scala` — imported by **9** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/error/GameError.scala` — imported by **9** files
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/observer/Observer.scala` — imported by **9** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/io/GameContextImport.scala` — imported by **8** files
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/grpc/IoGrpcClientWrapper.scala` — imported by **7** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/game/GameMode.scala` — imported by **6** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala` — imported by **6** files
|
||||
|
||||
## Import Map (who imports what)
|
||||
|
||||
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala` ← `modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala`, `modules/api/src/main/scala/de/nowchess/api/io/GameContextExport.scala`, `modules/api/src/main/scala/de/nowchess/api/io/GameContextImport.scala`, `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala`, `modules/bot/src/main/scala/de/nowchess/bot/BotMoveRepetition.scala` +71 more
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Square.scala` ← `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/main/scala/de/nowchess/api/move/Move.scala`, `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/api/src/test/scala/de/nowchess/api/move/MoveTest.scala` +52 more
|
||||
- `modules/api/src/main/scala/de/nowchess/api/move/Move.scala` ← `modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala`, `modules/api/src/test/scala/de/nowchess/api/board/BoardTest.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala` +50 more
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Color.scala` ← `modules/api/src/main/scala/de/nowchess/api/game/ClockState.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameResult.scala`, `modules/api/src/test/scala/de/nowchess/api/game/ClockStateTest.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala` +42 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` +23 more
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Board.scala` ← `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NNUE.scala`, `modules/bot/src/main/scala/de/nowchess/bot/logic/MoveOrdering.scala`, `modules/bot/src/test/scala/de/nowchess/bot/AlphaBetaSearchTest.scala` +15 more
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/PieceType.scala` ← `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/classic/EvaluationClassic.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NNUE.scala`, `modules/bot/src/main/scala/de/nowchess/bot/logic/AlphaBetaSearch.scala`, `modules/bot/src/main/scala/de/nowchess/bot/logic/MoveOrdering.scala` +15 more
|
||||
- `modules/api/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` +15 more
|
||||
- `modules/api/src/main/scala/de/nowchess/api/game/DrawReason.scala` ← `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/core/src/main/scala/de/nowchess/chess/config/NativeReflectionConfig.scala`, `modules/core/src/main/scala/de/nowchess/chess/engine/GameEngine.scala`, `modules/core/src/main/scala/de/nowchess/chess/grpc/CoreProtoMapper.scala`, `modules/core/src/main/scala/de/nowchess/chess/observer/Observer.scala` +13 more
|
||||
- `modules/api/src/main/scala/de/nowchess/api/game/GameResult.scala` ← `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/core/src/main/scala/de/nowchess/chess/config/NativeReflectionConfig.scala`, `modules/core/src/main/scala/de/nowchess/chess/engine/GameEngine.scala`, `modules/core/src/main/scala/de/nowchess/chess/grpc/CoreProtoMapper.scala`, `modules/core/src/main/scala/de/nowchess/chess/resource/GameDtoMapper.scala` +13 more
|
||||
|
||||
---
|
||||
|
||||
_Generated by [codesight](https://github.com/Houseofmvps/codesight) — see your codebase clearly_
|
||||
@@ -0,0 +1,5 @@
|
||||
# Config
|
||||
|
||||
## Environment Variables
|
||||
|
||||
- `STOCKFISH_PATH` **required** — modules/bot/python/nnue.py
|
||||
@@ -0,0 +1,37 @@
|
||||
# Dependency Graph
|
||||
|
||||
## Most Imported Files (change these carefully)
|
||||
|
||||
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala` — imported by **76** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Square.scala` — imported by **57** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/move/Move.scala` — imported by **55** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Color.scala` — imported by **47** files
|
||||
- `modules/rule/src/main/scala/de/nowchess/rules/sets/DefaultRules.scala` — imported by **28** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Board.scala` — imported by **20** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/PieceType.scala` — imported by **20** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Piece.scala` — imported by **20** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/game/DrawReason.scala` — imported by **18** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/game/GameResult.scala` — imported by **18** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala` — imported by **14** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/CastlingRights.scala` — imported by **13** files
|
||||
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParser.scala` — imported by **11** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/player/PlayerInfo.scala` — imported by **9** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/error/GameError.scala` — imported by **9** files
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/observer/Observer.scala` — imported by **9** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/io/GameContextImport.scala` — imported by **8** files
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/grpc/IoGrpcClientWrapper.scala` — imported by **7** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/game/GameMode.scala` — imported by **6** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala` — imported by **6** files
|
||||
|
||||
## Import Map (who imports what)
|
||||
|
||||
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala` ← `modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala`, `modules/api/src/main/scala/de/nowchess/api/io/GameContextExport.scala`, `modules/api/src/main/scala/de/nowchess/api/io/GameContextImport.scala`, `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala`, `modules/bot/src/main/scala/de/nowchess/bot/BotMoveRepetition.scala` +71 more
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Square.scala` ← `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/main/scala/de/nowchess/api/move/Move.scala`, `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/api/src/test/scala/de/nowchess/api/move/MoveTest.scala` +52 more
|
||||
- `modules/api/src/main/scala/de/nowchess/api/move/Move.scala` ← `modules/api/src/main/scala/de/nowchess/api/bot/Bot.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala`, `modules/api/src/test/scala/de/nowchess/api/board/BoardTest.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala` +50 more
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Color.scala` ← `modules/api/src/main/scala/de/nowchess/api/game/ClockState.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/main/scala/de/nowchess/api/game/GameResult.scala`, `modules/api/src/test/scala/de/nowchess/api/game/ClockStateTest.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala` +42 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` +23 more
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Board.scala` ← `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NNUE.scala`, `modules/bot/src/main/scala/de/nowchess/bot/logic/MoveOrdering.scala`, `modules/bot/src/test/scala/de/nowchess/bot/AlphaBetaSearchTest.scala` +15 more
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/PieceType.scala` ← `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/classic/EvaluationClassic.scala`, `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NNUE.scala`, `modules/bot/src/main/scala/de/nowchess/bot/logic/AlphaBetaSearch.scala`, `modules/bot/src/main/scala/de/nowchess/bot/logic/MoveOrdering.scala` +15 more
|
||||
- `modules/api/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` +15 more
|
||||
- `modules/api/src/main/scala/de/nowchess/api/game/DrawReason.scala` ← `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/core/src/main/scala/de/nowchess/chess/config/NativeReflectionConfig.scala`, `modules/core/src/main/scala/de/nowchess/chess/engine/GameEngine.scala`, `modules/core/src/main/scala/de/nowchess/chess/grpc/CoreProtoMapper.scala`, `modules/core/src/main/scala/de/nowchess/chess/observer/Observer.scala` +13 more
|
||||
- `modules/api/src/main/scala/de/nowchess/api/game/GameResult.scala` ← `modules/api/src/test/scala/de/nowchess/api/game/GameContextTest.scala`, `modules/core/src/main/scala/de/nowchess/chess/config/NativeReflectionConfig.scala`, `modules/core/src/main/scala/de/nowchess/chess/engine/GameEngine.scala`, `modules/core/src/main/scala/de/nowchess/chess/grpc/CoreProtoMapper.scala`, `modules/core/src/main/scala/de/nowchess/chess/resource/GameDtoMapper.scala` +13 more
|
||||
@@ -0,0 +1,554 @@
|
||||
# Libraries
|
||||
|
||||
- `jacoco-reporter/scoverage_coverage_gaps.py`
|
||||
- function parse_scoverage_xml: (xml_path) -> tuple[dict, list[ClassGap]]
|
||||
- function format_agent: (project_stats, classes) -> str
|
||||
- function format_json: (project_stats, classes) -> str
|
||||
- function format_markdown: (project_stats, classes) -> str
|
||||
- function format_module_gaps: (module_name, classes, stmt_pct) -> str
|
||||
- function run_scan_modules: (modules_dir, package_filter, min_coverage) -> None
|
||||
- _...4 more_
|
||||
- `jacoco-reporter/test_gaps.py`
|
||||
- function parse_suite_xml: (xml_path) -> SuiteResult
|
||||
- function load_module: (module_dir, results_subdir) -> Optional[ModuleResult]
|
||||
- function format_module: (mod) -> str
|
||||
- function run: (modules_dir, results_subdir, module_filter) -> None
|
||||
- function main: () -> None
|
||||
- class TestCase
|
||||
- _...2 more_
|
||||
- `modules/account/src/main/scala/de/nowchess/account/client/CoreGameClient.scala` — class CoreGameClient, function createGame
|
||||
- `modules/account/src/main/scala/de/nowchess/account/config/JacksonConfig.scala` — class JacksonConfig, function customize
|
||||
- `modules/account/src/main/scala/de/nowchess/account/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
|
||||
- `modules/account/src/main/scala/de/nowchess/account/domain/Challenge.scala`
|
||||
- class Challenge
|
||||
- function gameIdOpt
|
||||
- function declineReasonOpt
|
||||
- function timeControlLimitOpt
|
||||
- function timeControlIncrementOpt
|
||||
- `modules/account/src/main/scala/de/nowchess/account/domain/ChallengeColorConverter.scala` — class ChallengeColorConverter
|
||||
- `modules/account/src/main/scala/de/nowchess/account/domain/ChallengeStatusConverter.scala` — class ChallengeStatusConverter
|
||||
- `modules/account/src/main/scala/de/nowchess/account/domain/DeclineReasonConverter.scala` — class DeclineReasonConverter
|
||||
- `modules/account/src/main/scala/de/nowchess/account/domain/TimeControl.scala` — class TimeControl
|
||||
- `modules/account/src/main/scala/de/nowchess/account/domain/UserAccount.scala`
|
||||
- class UserAccount
|
||||
- function getBotAccounts
|
||||
- class BotAccount
|
||||
- class OfficialBotAccount
|
||||
- `modules/account/src/main/scala/de/nowchess/account/error/AccountError.scala` — function message
|
||||
- `modules/account/src/main/scala/de/nowchess/account/error/ChallengeError.scala` — function message
|
||||
- `modules/account/src/main/scala/de/nowchess/account/filter/AlreadyLoggedInFilter.scala` — class AlreadyLoggedInFilter
|
||||
- `modules/account/src/main/scala/de/nowchess/account/repository/AccountRepository.scala`
|
||||
- class UserAccountRepository
|
||||
- function findByUsername
|
||||
- function findById
|
||||
- function persist
|
||||
- function findByEmail
|
||||
- function findAll
|
||||
- _...12 more_
|
||||
- `modules/account/src/main/scala/de/nowchess/account/repository/ChallengeRepository.scala`
|
||||
- class ChallengeRepository
|
||||
- function findActiveByChallengerId
|
||||
- function findActiveByDestUserId
|
||||
- function findDuplicateChallenge
|
||||
- function findById
|
||||
- function persist
|
||||
- _...1 more_
|
||||
- `modules/account/src/main/scala/de/nowchess/account/resource/AccountResource.scala`
|
||||
- class AccountResource
|
||||
- function register
|
||||
- function login
|
||||
- function me
|
||||
- function publicProfile
|
||||
- function banUser
|
||||
- _...10 more_
|
||||
- `modules/account/src/main/scala/de/nowchess/account/resource/ChallengeResource.scala`
|
||||
- class ChallengeResource
|
||||
- function create
|
||||
- function list
|
||||
- function accept
|
||||
- function decline
|
||||
- function cancel
|
||||
- `modules/account/src/main/scala/de/nowchess/account/service/AccountService.scala`
|
||||
- class AccountService
|
||||
- function register
|
||||
- function login
|
||||
- function findByUsername
|
||||
- function findById
|
||||
- function createBotAccount
|
||||
- _...11 more_
|
||||
- `modules/account/src/main/scala/de/nowchess/account/service/ChallengeService.scala`
|
||||
- class ChallengeService
|
||||
- function create
|
||||
- function accept
|
||||
- function decline
|
||||
- function cancel
|
||||
- function listForUser
|
||||
- _...1 more_
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Board.scala`
|
||||
- class Board
|
||||
- function apply
|
||||
- function pieceAt
|
||||
- function updated
|
||||
- function removed
|
||||
- function withMove
|
||||
- _...2 more_
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/CastlingRights.scala`
|
||||
- function hasAnyRights
|
||||
- function hasRights
|
||||
- function revokeColor
|
||||
- function revokeKingSide
|
||||
- function revokeQueenSide
|
||||
- class CastlingRights
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Color.scala` — function opposite, function label
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Piece.scala` — class Piece
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/PieceType.scala` — function label
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Square.scala`
|
||||
- class Square
|
||||
- function fromAlgebraic
|
||||
- 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/error/GameError.scala` — function message
|
||||
- `modules/api/src/main/scala/de/nowchess/api/game/ClockState.scala`
|
||||
- function activeColor
|
||||
- function afterMove
|
||||
- function remainingMs
|
||||
- function remainingMs
|
||||
- function afterMove
|
||||
- function remainingMs
|
||||
- _...3 more_
|
||||
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala`
|
||||
- function kingSquare
|
||||
- function withBoard
|
||||
- function withTurn
|
||||
- function withCastlingRights
|
||||
- function withEnPassantSquare
|
||||
- function withHalfMoveClock
|
||||
- _...4 more_
|
||||
- `modules/api/src/main/scala/de/nowchess/api/io/GameContextExport.scala` — class GameContextExport, function exportGameContext
|
||||
- `modules/api/src/main/scala/de/nowchess/api/io/GameContextImport.scala` — class GameContextImport, function importGameContext
|
||||
- `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`
|
||||
- class ApiResponse
|
||||
- function error
|
||||
- function totalPages
|
||||
- `modules/api/src/main/scala/de/nowchess/api/rules/RuleSet.scala`
|
||||
- class RuleSet
|
||||
- function candidateMoves
|
||||
- function legalMoves
|
||||
- function allLegalMoves
|
||||
- function isCheck
|
||||
- function isCheckmate
|
||||
- _...6 more_
|
||||
- `modules/bot/python/nnue.py`
|
||||
- function get_weights_dir: ()
|
||||
- function get_data_dir: ()
|
||||
- function list_checkpoints: ()
|
||||
- function migrate_legacy_data: ()
|
||||
- function show_header: ()
|
||||
- function show_checkpoints_table: ()
|
||||
- _...10 more_
|
||||
- `modules/bot/python/src/dataset.py`
|
||||
- function get_datasets_dir: () -> Path
|
||||
- function next_dataset_version: () -> int
|
||||
- function list_datasets: () -> List[Tuple[int, Dict]]
|
||||
- function load_dataset_metadata: (version) -> Optional[Dict]
|
||||
- function save_dataset_metadata: (version, metadata) -> None
|
||||
- function create_dataset: (version, labeled_jsonl_path, sources, stockfish_depth) -> Path
|
||||
- _...4 more_
|
||||
- `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/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`
|
||||
- function download_and_extract_puzzle_db: (url, output_dir)
|
||||
- function extract_puzzle_positions: (puzzle_csv, max_puzzles) -> Set[str]
|
||||
- function load_positions_from_file: (file_path) -> Set[str]
|
||||
- function merge_positions: (tactical, other, output_file)
|
||||
- function extract_tactical_only: (puzzle_csv, output_file, max_puzzles) -> int
|
||||
- function interactive_merge_positions: (puzzle_csv, output_file, max_puzzles)
|
||||
- `modules/bot/python/src/train.py`
|
||||
- function fen_to_features: (fen)
|
||||
- function find_next_version: (base_name)
|
||||
- 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, 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, hidden_sizes)
|
||||
- class NNUEDataset
|
||||
- _...1 more_
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/BotController.scala`
|
||||
- class BotController
|
||||
- function getBot
|
||||
- function listBots
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/BotMoveRepetition.scala`
|
||||
- class BotMoveRepetition
|
||||
- function blockedMoves
|
||||
- function repeatedMove
|
||||
- function filterAllowed
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/Config.scala` — class Config
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/ai/Evaluation.scala`
|
||||
- class Evaluation
|
||||
- class CHECKMATE_SCORE
|
||||
- class DRAW_SCORE
|
||||
- function evaluate
|
||||
- function initAccumulator
|
||||
- function copyAccumulator
|
||||
- _...2 more_
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/bots/classic/EvaluationClassic.scala`
|
||||
- class EvaluationClassic
|
||||
- function evaluate
|
||||
- function countRay
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/EvaluationNNUE.scala` — class EvaluationNNUE, function evaluate
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NNUE.scala`
|
||||
- class NNUE
|
||||
- function initAccumulator
|
||||
- function pushAccumulator
|
||||
- function copyAccumulator
|
||||
- function recomputeAccumulator
|
||||
- function validateAccumulator
|
||||
- _...4 more_
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiLoader.scala`
|
||||
- class NbaiLoader
|
||||
- function load
|
||||
- function loadDefault
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiMigrator.scala` — class NbaiMigrator, function migrateFromBin
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiModel.scala`
|
||||
- function toJson
|
||||
- class NbaiMetadata
|
||||
- function fromJson
|
||||
- function str
|
||||
- function num
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NbaiWriter.scala` — class NbaiWriter, function write
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/logic/AlphaBetaSearch.scala`
|
||||
- function bestMove
|
||||
- function bestMove
|
||||
- function bestMoveWithTime
|
||||
- function bestMoveWithTime
|
||||
- function loop
|
||||
- function loop
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/logic/MoveOrdering.scala`
|
||||
- class MoveOrdering
|
||||
- class OrderingContext
|
||||
- function addKillerMove
|
||||
- function getKillerMoves
|
||||
- function addHistory
|
||||
- function getHistory
|
||||
- _...3 more_
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/logic/TranspositionTable.scala`
|
||||
- function advance
|
||||
- function probe
|
||||
- function store
|
||||
- function clear
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/util/PolyglotBook.scala` — function probe, function select
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/util/PolyglotHash.scala` — class PolyglotHash, function hash
|
||||
- `modules/bot/src/main/scala/de/nowchess/bot/util/ZobristHash.scala`
|
||||
- class ZobristHash
|
||||
- function hash
|
||||
- function nextHash
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/CoordinatorApp.scala` — class CoordinatorApp
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/config/BeansProducer.scala`
|
||||
- class BeansProducer
|
||||
- function redissonClient
|
||||
- function kubernetesClient
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/config/CoordinatorConfig.scala`
|
||||
- class CoordinatorConfig
|
||||
- function maxGamesPerCore
|
||||
- function maxDeviationPercent
|
||||
- function rebalanceInterval
|
||||
- function rebalanceMinInterval
|
||||
- function heartbeatTtl
|
||||
- _...11 more_
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/config/JacksonConfig.scala` — class JacksonConfig, function customize
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/grpc/CoordinatorGrpcServer.scala` — class CoordinatorGrpcServer
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/grpc/CoreGrpcClient.scala`
|
||||
- class CoreGrpcClient
|
||||
- function shutdown
|
||||
- function batchResubscribeGames
|
||||
- function unsubscribeGames
|
||||
- function evictGames
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/resource/CoordinatorResource.scala`
|
||||
- class CoordinatorResource
|
||||
- function listInstances
|
||||
- function getMetrics
|
||||
- function triggerRebalance
|
||||
- function triggerFailover
|
||||
- function triggerScaleUp
|
||||
- _...1 more_
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/AutoScaler.scala`
|
||||
- class AutoScaler
|
||||
- function checkAndScale
|
||||
- function scaleUp
|
||||
- function scaleDown
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/CacheEvictionManager.scala`
|
||||
- class CacheEvictionManager
|
||||
- function setRedisPrefix
|
||||
- function evictStaleGames
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/FailoverService.scala`
|
||||
- class FailoverService
|
||||
- function setRedisPrefix
|
||||
- function onInstanceStreamDropped
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/HealthMonitor.scala`
|
||||
- class HealthMonitor
|
||||
- function setRedisPrefix
|
||||
- function checkInstanceHealth
|
||||
- function watchK8sPods
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/InstanceRegistry.scala`
|
||||
- class InstanceRegistry
|
||||
- function setRedisPrefix
|
||||
- function getInstance
|
||||
- function getAllInstances
|
||||
- function updateInstanceFromRedis
|
||||
- function markInstanceDead
|
||||
- _...1 more_
|
||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/LoadBalancer.scala`
|
||||
- class LoadBalancer
|
||||
- function setRedisPrefix
|
||||
- function shouldRebalance
|
||||
- function rebalance
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/adapter/RuleSetRestAdapter.scala`
|
||||
- class RuleSetRestAdapter
|
||||
- function candidateMoves
|
||||
- function legalMoves
|
||||
- function allLegalMoves
|
||||
- function isCheck
|
||||
- function isCheckmate
|
||||
- _...5 more_
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/client/IoServiceClient.scala`
|
||||
- class IoServiceClient
|
||||
- function importFen
|
||||
- function importPgn
|
||||
- function exportFen
|
||||
- function exportPgn
|
||||
- function exportCombined
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/client/RuleServiceClient.scala`
|
||||
- class RuleServiceClient
|
||||
- function candidateMoves
|
||||
- function legalMoves
|
||||
- function allLegalMoves
|
||||
- function isCheck
|
||||
- function isCheckmate
|
||||
- _...6 more_
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/client/StoreServiceClient.scala` — class StoreServiceClient, function getGame
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/config/JacksonConfig.scala` — class JacksonConfig, function customize
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/config/RedisConfig.scala` — class RedisConfig
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/config/RedissonProducer.scala`
|
||||
- class RedissonProducer
|
||||
- function produceRedissonClient
|
||||
- function shutdown
|
||||
- `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`
|
||||
- class GameEngine
|
||||
- function board
|
||||
- function turn
|
||||
- function context
|
||||
- function pendingDrawOfferBy
|
||||
- function currentClockState
|
||||
- _...22 more_
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/exception/ApiException.scala`
|
||||
- class ApiException
|
||||
- class GameNotFoundException
|
||||
- class BadRequestException
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/exception/ApiExceptionMapper.scala` — class ApiExceptionMapper, function toResponse
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/grpc/CoordinatorServiceHandler.scala` — class CoordinatorServiceHandler
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/grpc/CoreProtoMapper.scala`
|
||||
- class CoreProtoMapper
|
||||
- function toProtoColor
|
||||
- function fromProtoColor
|
||||
- function toProtoPieceType
|
||||
- function fromProtoPieceType
|
||||
- function toProtoMoveKind
|
||||
- _...9 more_
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/grpc/IoGrpcClientWrapper.scala`
|
||||
- class IoGrpcClientWrapper
|
||||
- function exportCombined
|
||||
- function importFen
|
||||
- function importPgn
|
||||
- function exportFen
|
||||
- function exportPgn
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/grpc/RuleSetGrpcAdapter.scala`
|
||||
- class RuleSetGrpcAdapter
|
||||
- function candidateMoves
|
||||
- function legalMoves
|
||||
- function allLegalMoves
|
||||
- function isCheck
|
||||
- function isCheckmate
|
||||
- _...5 more_
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/observer/Observer.scala`
|
||||
- function context
|
||||
- class Observer
|
||||
- function onGameEvent
|
||||
- class Observable
|
||||
- function subscribe
|
||||
- function unsubscribe
|
||||
- _...1 more_
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/redis/C2sMessage.scala` — class C2sMessage
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/redis/GameRedisPublisher.scala` — class GameRedisPublisher, function onGameEvent
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/redis/GameRedisSubscriberManager.scala`
|
||||
- class GameRedisSubscriberManager
|
||||
- function subscribeGame
|
||||
- function onMessage
|
||||
- function unsubscribeGame
|
||||
- function batchResubscribeGames
|
||||
- function unsubscribeGames
|
||||
- _...3 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/RedisGameRegistry.scala`
|
||||
- class RedisGameRegistry
|
||||
- function generateId
|
||||
- function store
|
||||
- function get
|
||||
- function update
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/resource/GameDtoMapper.scala`
|
||||
- class GameDtoMapper
|
||||
- function statusOf
|
||||
- function moveToUci
|
||||
- function toPlayerDto
|
||||
- function toClockDto
|
||||
- function toGameStateDto
|
||||
- _...1 more_
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/resource/GameResource.scala`
|
||||
- class GameResource
|
||||
- function onGameEvent
|
||||
- function createGame
|
||||
- function getGame
|
||||
- function resignGame
|
||||
- function makeMove
|
||||
- _...9 more_
|
||||
- `modules/core/src/main/scala/de/nowchess/chess/service/InstanceHeartbeatService.scala`
|
||||
- class InstanceHeartbeatService
|
||||
- function onStart
|
||||
- function onShutdown
|
||||
- function setRedisPrefix
|
||||
- function setSubscriptionCount
|
||||
- function setLocalCacheSize
|
||||
- _...2 more_
|
||||
- `modules/io/src/main/scala/de/nowchess/io/GameFileService.scala`
|
||||
- class GameFileService
|
||||
- function saveGameToFile
|
||||
- function loadGameFromFile
|
||||
- class FileSystemGameService
|
||||
- function saveGameToFile
|
||||
- function loadGameFromFile
|
||||
- `modules/io/src/main/scala/de/nowchess/io/fen/FenExporter.scala`
|
||||
- class FenExporter
|
||||
- function boardToFen
|
||||
- function gameContextToFen
|
||||
- function exportGameContext
|
||||
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParser.scala`
|
||||
- class FenParser
|
||||
- function parseFen
|
||||
- function importGameContext
|
||||
- function parseBoard
|
||||
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParserCombinators.scala`
|
||||
- class FenParserCombinators
|
||||
- function parseFen
|
||||
- function parseBoard
|
||||
- function importGameContext
|
||||
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParserFastParse.scala`
|
||||
- class FenParserFastParse
|
||||
- function parseFen
|
||||
- function parseBoard
|
||||
- function importGameContext
|
||||
- `modules/io/src/main/scala/de/nowchess/io/fen/FenParserSupport.scala` — function buildSquares
|
||||
- `modules/io/src/main/scala/de/nowchess/io/grpc/IoGrpcService.scala` — class IoGrpcService
|
||||
- `modules/io/src/main/scala/de/nowchess/io/grpc/IoProtoMapper.scala`
|
||||
- class IoProtoMapper
|
||||
- function toProtoColor
|
||||
- function fromProtoColor
|
||||
- function toProtoPieceType
|
||||
- function fromProtoPieceType
|
||||
- function toProtoMoveKind
|
||||
- _...9 more_
|
||||
- `modules/io/src/main/scala/de/nowchess/io/json/JsonExporter.scala` — class JsonExporter, function exportGameContext
|
||||
- `modules/io/src/main/scala/de/nowchess/io/json/JsonParser.scala` — class JsonParser, function importGameContext
|
||||
- `modules/io/src/main/scala/de/nowchess/io/pgn/PgnExporter.scala`
|
||||
- class PgnExporter
|
||||
- function exportGameContext
|
||||
- function exportGame
|
||||
- `modules/io/src/main/scala/de/nowchess/io/pgn/PgnParser.scala`
|
||||
- class PgnParser
|
||||
- function validatePgn
|
||||
- function importGameContext
|
||||
- function parsePgn
|
||||
- function parseAlgebraicMove
|
||||
- `modules/io/src/main/scala/de/nowchess/io/service/config/JacksonConfig.scala` — class JacksonConfig, function customize
|
||||
- `modules/io/src/main/scala/de/nowchess/io/service/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
|
||||
- `modules/io/src/main/scala/de/nowchess/io/service/resource/IoResource.scala`
|
||||
- class IoResource
|
||||
- function importFen
|
||||
- function importPgn
|
||||
- function exportFen
|
||||
- function exportPgn
|
||||
- function exportCombined
|
||||
- `modules/json/src/main/scala/de/nowchess/json/ChessJacksonModule.scala` — class ChessJacksonModule
|
||||
- `modules/json/src/main/scala/de/nowchess/json/GameResultDeserializer.scala` — class GameResultDeserializer
|
||||
- `modules/json/src/main/scala/de/nowchess/json/GameResultSerializer.scala` — class GameResultSerializer
|
||||
- `modules/json/src/main/scala/de/nowchess/json/MoveTypeDeserializer.scala` — class MoveTypeDeserializer
|
||||
- `modules/json/src/main/scala/de/nowchess/json/MoveTypeSerializer.scala` — class MoveTypeSerializer
|
||||
- `modules/json/src/main/scala/de/nowchess/json/SquareDeserializer.scala` — class SquareDeserializer
|
||||
- `modules/json/src/main/scala/de/nowchess/json/SquareKeyDeserializer.scala` — class SquareKeyDeserializer
|
||||
- `modules/json/src/main/scala/de/nowchess/json/SquareKeySerializer.scala` — class SquareKeySerializer
|
||||
- `modules/json/src/main/scala/de/nowchess/json/SquareSerializer.scala` — class SquareSerializer
|
||||
- `modules/rule/src/main/scala/de/nowchess/rules/config/JacksonConfig.scala` — class JacksonConfig, function customize
|
||||
- `modules/rule/src/main/scala/de/nowchess/rules/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
|
||||
- `modules/rule/src/main/scala/de/nowchess/rules/grpc/ProtoMapper.scala`
|
||||
- class ProtoMapper
|
||||
- function toProtoColor
|
||||
- function fromProtoColor
|
||||
- function toProtoPieceType
|
||||
- function fromProtoPieceType
|
||||
- function toProtoMoveKind
|
||||
- _...9 more_
|
||||
- `modules/rule/src/main/scala/de/nowchess/rules/grpc/RuleGrpcService.scala` — class RuleGrpcService
|
||||
- `modules/rule/src/main/scala/de/nowchess/rules/resource/RuleSetResource.scala`
|
||||
- class RuleSetResource
|
||||
- function candidateMoves
|
||||
- function legalMoves
|
||||
- function allLegalMoves
|
||||
- function isCheck
|
||||
- function isCheckmate
|
||||
- _...6 more_
|
||||
- `modules/rule/src/main/scala/de/nowchess/rules/sets/DefaultRules.scala` — class DefaultRules, function positionOf
|
||||
- `modules/store/src/main/scala/de/nowchess/store/config/JacksonConfig.scala` — class JacksonConfig, function customize
|
||||
- `modules/store/src/main/scala/de/nowchess/store/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
|
||||
- `modules/store/src/main/scala/de/nowchess/store/config/RedisConfig.scala` — class RedisConfig
|
||||
- `modules/store/src/main/scala/de/nowchess/store/config/RedissonProducer.scala`
|
||||
- class RedissonProducer
|
||||
- function redissonClient
|
||||
- function close
|
||||
- `modules/store/src/main/scala/de/nowchess/store/domain/GameRecord.scala` — class GameRecord
|
||||
- `modules/store/src/main/scala/de/nowchess/store/redis/GameWritebackStreamListener.scala`
|
||||
- class GameWritebackStreamListener
|
||||
- function startListening
|
||||
- function onMessage
|
||||
- `modules/store/src/main/scala/de/nowchess/store/repository/GameRecordRepository.scala`
|
||||
- class GameRecordRepository
|
||||
- function findByGameId
|
||||
- function persist
|
||||
- function merge
|
||||
- `modules/store/src/main/scala/de/nowchess/store/resource/StoreGameResource.scala` — class StoreGameResource, function getGame
|
||||
- `modules/store/src/main/scala/de/nowchess/store/service/GameWritebackService.scala` — class GameWritebackService, function writeBack
|
||||
- `modules/ws/src/main/scala/de/nowchess/ws/config/JacksonConfig.scala` — class JacksonConfig, function customize
|
||||
- `modules/ws/src/main/scala/de/nowchess/ws/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
|
||||
- `modules/ws/src/main/scala/de/nowchess/ws/config/RedisConfig.scala` — class RedisConfig
|
||||
- `modules/ws/src/main/scala/de/nowchess/ws/config/RedissonProducer.scala`
|
||||
- class RedissonProducer
|
||||
- function produceRedissonClient
|
||||
- function shutdown
|
||||
- `modules/ws/src/main/scala/de/nowchess/ws/resource/GameWebSocketResource.scala`
|
||||
- class GameWebSocketResource
|
||||
- function onOpen
|
||||
- function onMessage
|
||||
- function onTextMessage
|
||||
- function onClose
|
||||
@@ -0,0 +1,4 @@
|
||||
# Middleware
|
||||
|
||||
## custom
|
||||
- generate — `modules/bot/python/src/generate.py`
|
||||
@@ -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>
|
||||
@@ -0,0 +1,44 @@
|
||||
# Routes
|
||||
|
||||
## gRPC
|
||||
|
||||
- `/CoordinatorService/BatchResubscribeGames` (BatchResubscribeRequest) → BatchResubscribeResponse
|
||||
- `/CoordinatorService/UnsubscribeGames` (UnsubscribeGamesRequest) → UnsubscribeGamesResponse
|
||||
- `/CoordinatorService/EvictGames` (EvictGamesRequest) → EvictGamesResponse
|
||||
- `/CoordinatorService/DrainInstance` (DrainInstanceRequest) → DrainInstanceResponse
|
||||
- `/CoordinatorService/BatchResubscribeGames` (BatchResubscribeRequest) → BatchResubscribeResponse
|
||||
- `/CoordinatorService/UnsubscribeGames` (UnsubscribeGamesRequest) → UnsubscribeGamesResponse
|
||||
- `/CoordinatorService/EvictGames` (EvictGamesRequest) → EvictGamesResponse
|
||||
- `/CoordinatorService/DrainInstance` (DrainInstanceRequest) → DrainInstanceResponse
|
||||
- `/IoService/ImportFen` (ProtoImportFenRequest) → ProtoGameContext
|
||||
- `/IoService/ImportPgn` (ProtoImportPgnRequest) → ProtoGameContext
|
||||
- `/IoService/ExportCombined` (ProtoGameContext) → ProtoCombinedExport
|
||||
- `/IoService/ExportFen` (ProtoGameContext) → ProtoStringResult
|
||||
- `/IoService/ExportPgn` (ProtoGameContext) → ProtoStringResult
|
||||
- `/RuleService/CandidateMoves` (ProtoSquareRequest) → ProtoMoveList
|
||||
- `/RuleService/LegalMoves` (ProtoSquareRequest) → ProtoMoveList
|
||||
- `/RuleService/AllLegalMoves` (ProtoGameContext) → ProtoMoveList
|
||||
- `/RuleService/IsCheck` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsCheckmate` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsStalemate` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsInsufficientMaterial` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsFiftyMoveRule` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsThreefoldRepetition` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/ApplyMove` (ProtoMoveRequest) → ProtoGameContext
|
||||
- `/RuleService/PostMoveStatus` (ProtoGameContext) → ProtoPostMoveStatus
|
||||
- `/IoService/ImportFen` (ProtoImportFenRequest) → ProtoGameContext
|
||||
- `/IoService/ImportPgn` (ProtoImportPgnRequest) → ProtoGameContext
|
||||
- `/IoService/ExportCombined` (ProtoGameContext) → ProtoCombinedExport
|
||||
- `/IoService/ExportFen` (ProtoGameContext) → ProtoStringResult
|
||||
- `/IoService/ExportPgn` (ProtoGameContext) → ProtoStringResult
|
||||
- `/RuleService/CandidateMoves` (ProtoSquareRequest) → ProtoMoveList
|
||||
- `/RuleService/LegalMoves` (ProtoSquareRequest) → ProtoMoveList
|
||||
- `/RuleService/AllLegalMoves` (ProtoGameContext) → ProtoMoveList
|
||||
- `/RuleService/IsCheck` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsCheckmate` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsStalemate` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsInsufficientMaterial` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsFiftyMoveRule` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/IsThreefoldRepetition` (ProtoGameContext) → ProtoBoolResult
|
||||
- `/RuleService/ApplyMove` (ProtoMoveRequest) → ProtoGameContext
|
||||
- `/RuleService/PostMoveStatus` (ProtoGameContext) → ProtoPostMoveStatus
|
||||
@@ -0,0 +1,44 @@
|
||||
# NowChessSystems — Wiki
|
||||
|
||||
_Generated 2026-04-23 — re-run `npx codesight --wiki` if the codebase has changed._
|
||||
|
||||
Structural map compiled from source code via AST. No LLM — deterministic, 200ms.
|
||||
|
||||
> **How to use safely:** These articles tell you WHERE things live and WHAT exists. They do not show full implementation logic. Always read the actual source files before implementing new features or making changes. Never infer how a function works from the wiki alone.
|
||||
|
||||
## Articles
|
||||
|
||||
- [Overview](./overview.md)
|
||||
|
||||
## Quick Stats
|
||||
|
||||
- Routes: **0**
|
||||
- Models: **0**
|
||||
- Components: **0**
|
||||
- Env vars: **1** required, **0** with defaults
|
||||
|
||||
## How to Use
|
||||
|
||||
- **New session:** read `index.md` (this file) for orientation — WHERE things are
|
||||
- **Architecture question:** read `overview.md` (~500 tokens)
|
||||
- **Domain question:** read the relevant article, then **read those source files**
|
||||
- **Database question:** read `database.md`, then read the actual schema files
|
||||
- **Before implementing anything:** read the source files listed in the article
|
||||
- **Full source context:** read `.codesight/CODESIGHT.md`
|
||||
|
||||
## What the Wiki Does Not Cover
|
||||
|
||||
These exist in your codebase but are **not** reflected in wiki articles:
|
||||
- Routes registered dynamically at runtime (loops, plugin factories, `app.use(dynamicRouter)`)
|
||||
- Internal routes from npm packages (e.g. Better Auth's built-in `/api/auth/*` endpoints)
|
||||
- WebSocket and SSE handlers
|
||||
- Raw SQL tables not declared through an ORM
|
||||
- Computed or virtual fields absent from schema declarations
|
||||
- TypeScript types that are not actual database columns
|
||||
- Routes marked `[inferred]` were detected via regex and may have lower precision
|
||||
- gRPC, tRPC, and GraphQL resolvers may be partially captured
|
||||
|
||||
When in doubt, search the source. The wiki is a starting point, not a complete inventory.
|
||||
|
||||
---
|
||||
_Last compiled: 2026-04-23 · 2 articles · [codesight](https://github.com/Houseofmvps/codesight)_
|
||||
@@ -0,0 +1,7 @@
|
||||
# Wiki Log
|
||||
|
||||
History of `npx codesight --wiki` runs. Capped at 20 entries.
|
||||
|
||||
## [2026-04-12 14:34:19] scan | 0 routes, 0 models, 0 components → 2 articles
|
||||
|
||||
## [2026-04-23 11:41:43] scan | 0 routes, 0 models, 0 components → 2 articles
|
||||
@@ -0,0 +1,27 @@
|
||||
# NowChessSystems — Overview
|
||||
|
||||
> **Navigation aid.** This article shows WHERE things live (routes, models, files). Read actual source files before implementing new features or making changes.
|
||||
|
||||
**NowChessSystems** is a scala project built with raw-http.
|
||||
|
||||
## Scale
|
||||
|
||||
1 middleware layers · 1 environment variables
|
||||
|
||||
## High-Impact Files
|
||||
|
||||
Changes to these files have the widest blast radius across the codebase:
|
||||
|
||||
- `modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala` — imported by **74** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Square.scala` — imported by **66** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/move/Move.scala` — imported by **52** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Color.scala` — imported by **42** files
|
||||
- `modules/rule/src/main/scala/de/nowchess/rules/sets/DefaultRules.scala` — imported by **27** files
|
||||
- `modules/api/src/main/scala/de/nowchess/api/board/Piece.scala` — imported by **21** files
|
||||
|
||||
## Required Environment Variables
|
||||
|
||||
- `STOCKFISH_PATH` — `modules/bot/python/nnue.py`
|
||||
|
||||
---
|
||||
_Back to [index.md](./index.md) · Generated 2026-04-23_
|
||||
@@ -0,0 +1,12 @@
|
||||
FROM mcr.microsoft.com/devcontainers/java:21-bookworm
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
postgresql-client \
|
||||
redis-tools \
|
||||
stockfish \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN mkdir -p /home/vscode/.gradle/wrapper/dists \
|
||||
&& chown -R vscode:vscode /home/vscode/.gradle
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Devcontainer
|
||||
|
||||
Dieses Setup startet den NowChess-Workspace zusammen mit Redis und PostgreSQL.
|
||||
|
||||
## Enthaltene Services
|
||||
- `workspace` – Scala/Gradle-Entwicklungscontainer
|
||||
- `redis` – Redis 7.4
|
||||
- `postgres` – PostgreSQL 16
|
||||
|
||||
## Wichtige Ports
|
||||
- App-Services: `8080`, `8081`, `8082`, `8083`, `8084`, `8085`, `8086`, `9086`
|
||||
- Redis auf dem Host: `16379`
|
||||
- PostgreSQL auf dem Host: `15432`
|
||||
|
||||
## Einstieg
|
||||
- VS Code: Ordner in einem Dev Container öffnen
|
||||
- IntelliJ: Dev Container / Docker-Compose-Workspace öffnen und den `workspace`-Dienst nutzen
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "NowChessSystems",
|
||||
"dockerComposeFile": ["docker-compose.yml"],
|
||||
"service": "workspace",
|
||||
"workspaceFolder": "/workspaces/NowChessSystems",
|
||||
"shutdownAction": "stopCompose",
|
||||
"overrideCommand": false,
|
||||
"remoteUser": "vscode",
|
||||
"forwardPorts": [8080, 8081, 8082, 8083, 8084, 8085, 8086, 9086],
|
||||
"portsAttributes": {
|
||||
"8080": {"label": "NowChess Core", "onAutoForward": "notify"},
|
||||
"8081": {"label": "NowChess Io", "onAutoForward": "notify"},
|
||||
"8082": {"label": "NowChess Rule", "onAutoForward": "notify"},
|
||||
"8083": {"label": "NowChess Account", "onAutoForward": "notify"},
|
||||
"8084": {"label": "NowChess WebSocket", "onAutoForward": "notify"},
|
||||
"8085": {"label": "NowChess Store", "onAutoForward": "notify"},
|
||||
"8086": {"label": "NowChess Coordinator HTTP", "onAutoForward": "notify"},
|
||||
"9086": {"label": "NowChess Coordinator gRPC", "onAutoForward": "notify"}
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"settings": {
|
||||
"java.configuration.updateBuildConfiguration": "automatic",
|
||||
"java.import.gradle.wrapper.enabled": true,
|
||||
"files.watcherExclude": {
|
||||
"**/build/**": true,
|
||||
"**/.gradle/**": true
|
||||
}
|
||||
},
|
||||
"extensions": [
|
||||
"scala-lang.scala",
|
||||
"redhat.java",
|
||||
"vscjava.vscode-java-pack"
|
||||
]
|
||||
}
|
||||
},
|
||||
"postCreateCommand": "bash -lc './gradlew --no-daemon help >/dev/null'"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
services:
|
||||
workspace:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: .devcontainer/Dockerfile
|
||||
command: sleep infinity
|
||||
init: true
|
||||
volumes:
|
||||
- gradle-cache:/home/vscode/.gradle
|
||||
environment:
|
||||
REDIS_HOST: redis
|
||||
REDIS_PORT: 6379
|
||||
REDIS_PREFIX: nowchess
|
||||
DB_URL: jdbc:postgresql://postgres:5432/nowchess
|
||||
DB_USER: nowchess
|
||||
DB_PASSWORD: nowchess
|
||||
CORE_SERVICE_URL: http://localhost:8080
|
||||
INTERNAL_SECRET: dev-internal-secret
|
||||
STOCKFISH_PATH: /usr/games/stockfish
|
||||
NOWCHESS_COORDINATOR_ENABLED: "true"
|
||||
dns:
|
||||
- 8.8.8.8
|
||||
- 1.1.1.1
|
||||
depends_on:
|
||||
redis:
|
||||
condition: service_healthy
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
|
||||
redis:
|
||||
image: docker.io/redis:7.4-alpine
|
||||
command: ["redis-server", "--appendonly", "yes", "--save", "60", "1"]
|
||||
ports:
|
||||
- "16379:6379"
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 20
|
||||
start_period: 5s
|
||||
|
||||
postgres:
|
||||
image: docker.io/postgres:16-alpine
|
||||
environment:
|
||||
POSTGRES_DB: nowchess
|
||||
POSTGRES_USER: nowchess
|
||||
POSTGRES_PASSWORD: nowchess
|
||||
ports:
|
||||
- "15432:5432"
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 20
|
||||
start_period: 10s
|
||||
|
||||
volumes:
|
||||
gradle-cache:
|
||||
redis-data:
|
||||
postgres-data:
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# Normalize text files in the repo
|
||||
* text=auto eol=lf
|
||||
|
||||
# Keep Windows command scripts in CRLF
|
||||
*.bat text eol=crlf
|
||||
*.cmd text eol=crlf
|
||||
|
||||
# Keep Unix shell scripts in LF
|
||||
*.sh text eol=lf
|
||||
|
||||
# Binary assets (no EOL normalization / textual diff)
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.jpeg binary
|
||||
*.gif binary
|
||||
*.webp binary
|
||||
*.bmp binary
|
||||
*.ico binary
|
||||
|
||||
# ML / model / numeric artifacts
|
||||
*.bin binary
|
||||
*.pt binary
|
||||
*.pth binary
|
||||
*.onnx binary
|
||||
*.h5 binary
|
||||
*.hdf5 binary
|
||||
*.pb binary
|
||||
*.tflite binary
|
||||
*.npy binary
|
||||
*.npz binary
|
||||
*.safetensors binary
|
||||
|
||||
# Firmware / hex-like artifacts
|
||||
*.hex binary
|
||||
|
||||
# Packaged binaries
|
||||
*.jar binary
|
||||
*.zip binary
|
||||
*.7z binary
|
||||
*.gz binary
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
name: Build & Push Native Image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
check-actor:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
allowed: ${{ steps.check.outputs.allowed }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- id: check
|
||||
run: |
|
||||
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
||||
echo "allowed=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
COMMIT_AUTHOR=$(git log -1 --format='%an')
|
||||
if [[ "$COMMIT_AUTHOR" == "TeamCity" ]]; then
|
||||
echo "allowed=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "allowed=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
fi
|
||||
|
||||
build-and-push:
|
||||
needs: check-actor
|
||||
if: needs.check-actor.outputs.allowed == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
module:
|
||||
- account
|
||||
- bot-platform
|
||||
- coordinator
|
||||
- core
|
||||
- io
|
||||
- official-bots
|
||||
- rule
|
||||
- store
|
||||
- ws
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up GraalVM
|
||||
uses: graalvm/setup-graalvm@v1
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'graalvm-community'
|
||||
native-image-job-reports: 'true'
|
||||
|
||||
- name: Cache Gradle packages
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: gradle-${{ runner.os }}-
|
||||
|
||||
- name: Read version from versions.env
|
||||
id: version
|
||||
run: |
|
||||
if [ -f "modules/${{ matrix.module }}/versions.env" ]; then
|
||||
source modules/${{ matrix.module }}/versions.env
|
||||
VERSION="${MAJOR}.${MINOR}.${PATCH}"
|
||||
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "version=latest" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Build native binary
|
||||
run: ./gradlew :modules:${{ matrix.module }}:build -x test -Dquarkus.native.enabled=true -Dquarkus.package.jar.enabled=false -Dquarkus.profile=deployed --no-daemon
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ghcr.io/now-chess/now-chess-systems/${{ matrix.module }}
|
||||
tags: |
|
||||
type=raw,value=${{ steps.version.outputs.version }}
|
||||
type=raw,value=latest
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: modules/${{ matrix.module }}/src/main/docker/Dockerfile.native
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha,scope=${{ matrix.module }}
|
||||
cache-to: type=gha,mode=max,scope=${{ matrix.module }}
|
||||
@@ -38,6 +38,11 @@ bin/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
graphify-out/
|
||||
.graphify_*.json
|
||||
|
||||
### Keys ###
|
||||
**/keys/private.pem
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
|
||||
Generated
+2
@@ -8,3 +8,5 @@
|
||||
/dataSources.local.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
|
||||
sonarlint.xml
|
||||
|
||||
Generated
+133
@@ -0,0 +1,133 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<AndroidXmlCodeStyleSettings>
|
||||
<option name="USE_CUSTOM_SETTINGS" value="true" />
|
||||
</AndroidXmlCodeStyleSettings>
|
||||
<JetCodeStyleSettings>
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
<ScalaCodeStyleSettings>
|
||||
<option name="FORMATTER" value="1" />
|
||||
</ScalaCodeStyleSettings>
|
||||
<XML>
|
||||
<option name="XML_KEEP_LINE_BREAKS" value="false" />
|
||||
<option name="XML_ALIGN_ATTRIBUTES" value="false" />
|
||||
<option name="XML_SPACE_INSIDE_EMPTY_TAG" value="true" />
|
||||
</XML>
|
||||
<codeStyleSettings language="XML">
|
||||
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
<arrangement>
|
||||
<rules>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:android</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:id</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:name</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>name</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>style</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
</rules>
|
||||
</arrangement>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
Generated
+1
-1
@@ -1,5 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
||||
Generated
+18
File diff suppressed because one or more lines are too long
Generated
+9
-2
@@ -5,16 +5,23 @@
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="corretto-21" />
|
||||
<option name="gradleJvm" value="ms-21" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/modules" />
|
||||
<option value="$PROJECT_DIR$/modules/account" />
|
||||
<option value="$PROJECT_DIR$/modules/api" />
|
||||
<option value="$PROJECT_DIR$/modules/bot-platform" />
|
||||
<option value="$PROJECT_DIR$/modules/coordinator" />
|
||||
<option value="$PROJECT_DIR$/modules/core" />
|
||||
<option value="$PROJECT_DIR$/modules/io" />
|
||||
<option value="$PROJECT_DIR$/modules/json" />
|
||||
<option value="$PROJECT_DIR$/modules/official-bots" />
|
||||
<option value="$PROJECT_DIR$/modules/rule" />
|
||||
<option value="$PROJECT_DIR$/modules/ui" />
|
||||
<option value="$PROJECT_DIR$/modules/security" />
|
||||
<option value="$PROJECT_DIR$/modules/store" />
|
||||
<option value="$PROJECT_DIR$/modules/ws" />
|
||||
</set>
|
||||
</option>
|
||||
</GradleProjectSettings>
|
||||
|
||||
Generated
+2
-1
@@ -1,9 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="FrameworkDetectionExcludesConfiguration">
|
||||
<file type="web" url="file://$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="corretto-21" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="ms-21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -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>
|
||||
Generated
+1
-1
@@ -5,7 +5,7 @@
|
||||
<option name="deprecationWarnings" value="true" />
|
||||
<option name="uncheckedWarnings" value="true" />
|
||||
</profile>
|
||||
<profile name="Gradle 2" modules="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.account.integrationTest,NowChessSystems.modules.account.main,NowChessSystems.modules.account.native-test,NowChessSystems.modules.account.quarkus-generated-sources,NowChessSystems.modules.account.quarkus-test-generated-sources,NowChessSystems.modules.account.scoverage,NowChessSystems.modules.account.test,NowChessSystems.modules.bot-platform.integrationTest,NowChessSystems.modules.bot-platform.main,NowChessSystems.modules.bot-platform.native-test,NowChessSystems.modules.bot-platform.quarkus-generated-sources,NowChessSystems.modules.bot-platform.quarkus-test-generated-sources,NowChessSystems.modules.bot-platform.scoverage,NowChessSystems.modules.bot-platform.test,NowChessSystems.modules.bot.main,NowChessSystems.modules.bot.scoverage,NowChessSystems.modules.bot.test,NowChessSystems.modules.coordinator.integrationTest,NowChessSystems.modules.coordinator.main,NowChessSystems.modules.coordinator.native-test,NowChessSystems.modules.coordinator.quarkus-generated-sources,NowChessSystems.modules.coordinator.quarkus-test-generated-sources,NowChessSystems.modules.coordinator.scoverage,NowChessSystems.modules.coordinator.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.integrationTest,NowChessSystems.modules.io.main,NowChessSystems.modules.io.native-test,NowChessSystems.modules.io.quarkus-generated-sources,NowChessSystems.modules.io.quarkus-test-generated-sources,NowChessSystems.modules.io.scoverage,NowChessSystems.modules.io.test,NowChessSystems.modules.json.main,NowChessSystems.modules.json.scoverage,NowChessSystems.modules.json.test,NowChessSystems.modules.official-bots.integrationTest,NowChessSystems.modules.official-bots.main,NowChessSystems.modules.official-bots.native-test,NowChessSystems.modules.official-bots.quarkus-generated-sources,NowChessSystems.modules.official-bots.quarkus-test-generated-sources,NowChessSystems.modules.official-bots.scoverage,NowChessSystems.modules.official-bots.test,NowChessSystems.modules.rule.integrationTest,NowChessSystems.modules.rule.main,NowChessSystems.modules.rule.native-test,NowChessSystems.modules.rule.quarkus-generated-sources,NowChessSystems.modules.rule.quarkus-test-generated-sources,NowChessSystems.modules.rule.scoverage,NowChessSystems.modules.rule.test,NowChessSystems.modules.security.main,NowChessSystems.modules.security.scoverage,NowChessSystems.modules.security.test,NowChessSystems.modules.store.integrationTest,NowChessSystems.modules.store.main,NowChessSystems.modules.store.native-test,NowChessSystems.modules.store.quarkus-generated-sources,NowChessSystems.modules.store.quarkus-test-generated-sources,NowChessSystems.modules.store.scoverage,NowChessSystems.modules.store.test,NowChessSystems.modules.ui.main,NowChessSystems.modules.ui.scoverage,NowChessSystems.modules.ui.test,NowChessSystems.modules.ws.integrationTest,NowChessSystems.modules.ws.main,NowChessSystems.modules.ws.native-test,NowChessSystems.modules.ws.quarkus-generated-sources,NowChessSystems.modules.ws.quarkus-test-generated-sources,NowChessSystems.modules.ws.scoverage,NowChessSystems.modules.ws.test">
|
||||
<option name="deprecationWarnings" value="true" />
|
||||
<option name="uncheckedWarnings" value="true" />
|
||||
<parameters>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
rules = [
|
||||
DisableSyntax,
|
||||
LeakingImplicitClassVal,
|
||||
NoValInForComprehension,
|
||||
ProcedureSyntax,
|
||||
]
|
||||
|
||||
DisableSyntax.noVars = true
|
||||
DisableSyntax.noThrows = true
|
||||
DisableSyntax.noNulls = true
|
||||
DisableSyntax.noReturns = true
|
||||
DisableSyntax.noAsInstanceOf = true
|
||||
DisableSyntax.noIsInstanceOf = true
|
||||
DisableSyntax.noXml = true
|
||||
DisableSyntax.noFinalize = true
|
||||
@@ -0,0 +1,8 @@
|
||||
version = 3.8.1
|
||||
runner.dialect = scala3
|
||||
maxColumn = 120
|
||||
indent.main = 2
|
||||
align.preset = more
|
||||
trailingCommas = always
|
||||
rewrite.rules = [SortImports, RedundantBraces]
|
||||
rewrite.scala3.convertToNewSyntax = true
|
||||
@@ -0,0 +1,21 @@
|
||||
# Project Context
|
||||
|
||||
This is a scala project using raw-http.
|
||||
|
||||
Middleware includes: custom.
|
||||
|
||||
High-impact files (most imported, changes here affect many other files):
|
||||
- modules/api/src/main/scala/de/nowchess/api/game/GameContext.scala (imported by 50 files)
|
||||
- modules/api/src/main/scala/de/nowchess/api/board/Square.scala (imported by 33 files)
|
||||
- modules/api/src/main/scala/de/nowchess/api/board/Color.scala (imported by 30 files)
|
||||
- modules/api/src/main/scala/de/nowchess/api/move/Move.scala (imported by 29 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 18 files)
|
||||
- modules/rule/src/main/scala/de/nowchess/rules/sets/DefaultRules.scala (imported by 17 files)
|
||||
- modules/api/src/main/scala/de/nowchess/api/board/Piece.scala (imported by 15 files)
|
||||
|
||||
Required environment variables (no defaults):
|
||||
- STOCKFISH_PATH (modules/bot/python/nnue.py)
|
||||
|
||||
Read .codesight/wiki/index.md for orientation (WHERE things live). Then read actual source files before implementing. Wiki articles are navigation aids, not implementation guides.
|
||||
Read .codesight/CODESIGHT.md for the complete AI context map including all routes, schema, components, libraries, config, middleware, and dependency graph.
|
||||
@@ -1,7 +1,7 @@
|
||||
YOU CAN:
|
||||
- Edit and use the asset in any commercial or non commercial project
|
||||
- Use the asset in any commercial or non commercial project
|
||||
|
||||
YOU CAN'T:
|
||||
- Resell or distribute the asset to others
|
||||
YOU CAN:
|
||||
- Edit and use the asset in any commercial or non commercial project
|
||||
- Use the asset in any commercial or non commercial project
|
||||
|
||||
YOU CAN'T:
|
||||
- Resell or distribute the asset to others
|
||||
- Edit and resell the asset to others - - Credits required using This link: https://fatman200.itch.io/
|
||||
@@ -9,8 +9,9 @@ Scala 3.5.1 · Gradle 9
|
||||
./compile # Compile all modules — always run
|
||||
./test # Run all tests
|
||||
./coverage # Check coverage
|
||||
./lint # Run linters
|
||||
```
|
||||
Try to stick to these commands for consistency.
|
||||
Use consistently.
|
||||
|
||||
## Modules
|
||||
|
||||
@@ -19,32 +20,77 @@ Try to stick to these commands for consistency.
|
||||
| `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.
|
||||
- Immutable data, pure functions.
|
||||
- Functions under 30 lines. Need "and"? Split it.
|
||||
- Cyclomatic complexity under 15.
|
||||
- No comments. Names carry intent. Comment non-obvious algorithms only.
|
||||
- Scan duplicated logic. Extract.
|
||||
- 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.
|
||||
- `Option`/`Either` for fallible ops. Skip exceptions for control flow.
|
||||
- Naming: types PascalCase, functions/values camelCase.
|
||||
|
||||
## Code Quality
|
||||
|
||||
- **Coverage:** 100% condition coverage required in `api`, `core`, `rule`, `io` (mandatory); `ui` exempt.
|
||||
|
||||
### Linters
|
||||
|
||||
- **scalafmt** — Enforces formatting. Check: `./gradlew spotlessScalaCheck`. Refactor: `./gradlew spotlessScalaApply`.
|
||||
- **scalafix** — Enforces style, detects unused imports/code. Run: `./gradlew scalafix`.
|
||||
|
||||
## 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.
|
||||
- **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 (no polling). GameEngine never imports UI.
|
||||
- **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)` (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 disabled (fixed-window futures removed pruning effectiveness). Sequential PV default. Correctness + pruning quality > speculative parallelism.
|
||||
- **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
|
||||
|
||||
- **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.
|
||||
- Keep this file up to date with any important decisions or conventions.
|
||||
- Keep file current with decisions + conventions.
|
||||
|
||||
---
|
||||
|
||||
## Instructions for Claude Code
|
||||
|
||||
### Two-Step Rule (mandatory)
|
||||
**Step 1 — Orient:** Use wiki articles to find WHERE things live.
|
||||
**Step 2 — Verify:** Read source files from wiki BEFORE coding.
|
||||
|
||||
Wiki = structural summaries (routes, models, file locations). No function logic, middleware internals, runtime behavior. Don't code from wiki alone—read sources.
|
||||
|
||||
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
|
||||
|
||||
`[inferred]` routes = regex-detected. Verify sources. ⚠ in wiki? Re-run `codesight --wiki`.
|
||||
|
||||
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
|
||||
|
||||
Consult codesight context first. Saves ~16.893 tokens/conversation.
|
||||
|
||||
## graphify
|
||||
|
||||
graphify knowledge graph at graphify-out/.
|
||||
|
||||
Rules:
|
||||
- Architecture/codebase questions? Read graphify-out/GRAPH_REPORT.md (god nodes, communities).
|
||||
- graphify-out/wiki/index.md exists? Use it (not raw files).
|
||||
- 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
|
||||
./lint # Run linters
|
||||
```
|
||||
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 |
|
||||
|
||||
## 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,334 @@
|
||||
# Plan: Add Coordinator Microservice
|
||||
|
||||
## Context
|
||||
NowChess scales `core` horizontally via shared Redis but lacks:
|
||||
- **Instance visibility**: no way to list running cores or their load
|
||||
- **Load balancing**: games land randomly on cores; no rebalancing
|
||||
- **Failover**: dead cores orphan subscriptions; bullet chess requires <1s recovery
|
||||
- **Auto-scaling**: manual ops to add/remove cores
|
||||
- **Cache management**: no eviction of stale games from core memory
|
||||
|
||||
Bullet chess games run on move timings of <3s. 30s failover = game lost on clock. Target: **<300ms failover**.
|
||||
|
||||
---
|
||||
|
||||
## Architecture: Sub-1s Failover
|
||||
|
||||
### Why Not Polling/TTL
|
||||
- TTL expiry: minimum 10-30s detection
|
||||
- HTTP polling 3x failure: 30s minimum
|
||||
- **gRPC streaming TCP drop: 50-200ms** — use this as primary
|
||||
|
||||
### Primary: gRPC Bidirectional Streaming
|
||||
- Core opens a **persistent bidirectional stream** (`CoreHeartbeatStream`) to coordinator on startup
|
||||
- Core sends heartbeat frames every **200ms**
|
||||
- Core crash = TCP RST/FIN → coordinator stream error in **~50-200ms**
|
||||
- Stream also carries metadata updates (subscription count changes) in real-time
|
||||
|
||||
### Fallback: Redis Heartbeat + K8s Watch
|
||||
- Redis heartbeat key `{prefix}:instances:{instanceId}` with **5s TTL**, refreshed every **2s**
|
||||
- K8s pod watch via Kubernetes Java client (event-driven; handles pod eviction/OOMKill)
|
||||
- Fallback covers: network partition (TCP stays up but core is zombie), coordinator restart gap
|
||||
|
||||
---
|
||||
|
||||
## Design
|
||||
|
||||
### 1. Module: `modules/coordinator`
|
||||
**Language**: Scala 3.5.1, Quarkus REST + gRPC
|
||||
**Ports**: HTTP 8086, gRPC 9086
|
||||
**Dependencies**: Redisson, Kubernetes Java client, Quarkus gRPC
|
||||
**Persistence**: None (all state in Redis)
|
||||
|
||||
---
|
||||
|
||||
### 2. Instance Registry
|
||||
|
||||
**Redis schema**:
|
||||
```
|
||||
{prefix}:instances:{instanceId}
|
||||
- TTL: 5s (refreshed by core every 2s via background task)
|
||||
- Value: JSON
|
||||
{
|
||||
"instanceId": "core-abc123",
|
||||
"hostname": "core-pod-3",
|
||||
"httpPort": 8080,
|
||||
"grpcPort": 9080,
|
||||
"subscriptionCount": 147,
|
||||
"localCacheSize": 147,
|
||||
"lastHeartbeat": "2026-04-26T10:15:30.123Z"
|
||||
}
|
||||
|
||||
{prefix}:instance:{instanceId}:games
|
||||
- Type: Redis Set (no TTL — managed explicitly)
|
||||
- Members: all gameIds currently subscribed on this instance
|
||||
```
|
||||
|
||||
**Core changes** (new `InstanceHeartbeatService` bean in `modules/core`):
|
||||
- `@PostConstruct`: generate stable `instanceId` (hostname + random suffix); open gRPC stream to coordinator; publish Redis heartbeat; register in `{prefix}:instances:{instanceId}`
|
||||
- Every 200ms: send heartbeat frame on gRPC stream (carries `subscriptionCount`)
|
||||
- Every 2s: refresh Redis heartbeat bucket TTL
|
||||
- `subscribeGame(gameId)`: `SADD {prefix}:instance:{instanceId}:games gameId`
|
||||
- `unsubscribeGame(gameId)` / `evictGame(gameId)`: `SREM {prefix}:instance:{instanceId}:games gameId`
|
||||
- `@PreDestroy`: delete Redis key + games set; close gRPC stream (clean shutdown)
|
||||
|
||||
---
|
||||
|
||||
### 3. Health Monitoring (3 signals, primary fast)
|
||||
|
||||
| Signal | Mechanism | Detection time | Role |
|
||||
|--------|-----------|---------------|------|
|
||||
| **gRPC stream drop** | TCP RST/FIN on bidirectional stream | 50–200ms | Primary |
|
||||
| **Redis heartbeat expiry** | `{prefix}:instances:{instanceId}` TTL=5s | 5–7s | Fallback |
|
||||
| **K8s pod watch** | `CoreV1Api.listNamespacedPod` watch stream | ~instant (pod events) | Fallback |
|
||||
|
||||
**Dead decision**:
|
||||
- gRPC stream drops → **immediate failover** (no confirmation needed; games must recover fast)
|
||||
- Redis heartbeat expires (gRPC still up) → verify with single HTTP `/q/health` call → if fail: failover
|
||||
- K8s pod NotReady (gRPC still up) → failover
|
||||
|
||||
---
|
||||
|
||||
### 4. Failover Protocol (<300ms target)
|
||||
|
||||
```
|
||||
T+0ms Core JVM crashes / network drops
|
||||
T+50ms Coordinator: gRPC stream error received
|
||||
T+52ms SMEMBERS {prefix}:instance:{instanceId}:games → list of orphaned gameIds
|
||||
T+55ms Distribute gameIds across healthy cores (least-loaded first)
|
||||
T+60ms BatchResubscribeGames gRPC call(s) fire to healthy core(s)
|
||||
T+150ms Healthy cores resubscribed; Redis s2c topics live again
|
||||
T+200ms WebSocket clients reconnect; receive GameFullEventDto on CONNECTED
|
||||
```
|
||||
|
||||
**Failover steps** (coordinator `FailoverService`):
|
||||
1. On stream drop for `instanceId`:
|
||||
a. Mark instance DEAD in local map
|
||||
b. `SMEMBERS {prefix}:instance:{instanceId}:games`
|
||||
c. Group gameIds into batches per target core (round-robin by load)
|
||||
d. For each target core: call `BatchResubscribeGames(gameIds)`
|
||||
e. Each target core: calls `subscribeGame(gameId)` for each (loads from Redis if not in local cache)
|
||||
f. `DEL {prefix}:instance:{instanceId}:games` (cleanup)
|
||||
2. Log failover event with count of games migrated + latency
|
||||
|
||||
---
|
||||
|
||||
### 5. Load Rebalancing
|
||||
|
||||
**Thresholds** (both must be evaluated):
|
||||
1. **Absolute**: any core > 500 games → rebalance
|
||||
2. **Relative**: max load > mean × 1.2 AND max - min > 50 games → rebalance
|
||||
|
||||
**Algorithm** (runs every 30s, min 60s between actual rebalances):
|
||||
1. Read all `{prefix}:instances:*` keys → load map
|
||||
2. Identify overloaded cores (exceed either threshold)
|
||||
3. For each overloaded core: pick `excess = load - targetLoad` games
|
||||
4. Assign excess games to underloaded cores
|
||||
5. Call `UnsubscribeGames(gameIds)` on overloaded core
|
||||
6. Call `BatchResubscribeGames(gameIds)` on target core
|
||||
7. Overloaded core: `SREM` each game from its set
|
||||
8. Target core: `SADD` each game to its set on subscribe
|
||||
|
||||
---
|
||||
|
||||
### 6. Auto-Scaling
|
||||
|
||||
**Metric**: avg `subscriptionCount` across all cores
|
||||
|
||||
**Actions**:
|
||||
- avg > `scale-up-threshold` (80% of max): patch `nowchess-core` Argo Rollout `spec.replicas += 1`
|
||||
- avg < `scale-down-threshold` (30% of max) AND `replicas > min-replicas`: drain one core then scale down
|
||||
- Backoff: min 2-minute interval between scale events
|
||||
|
||||
**Argo Rollouts API**:
|
||||
- CRD: `argoproj.io/v1alpha1`, Kind: `Rollout`, resource: `rollouts`
|
||||
- Scale via Fabric8 `GenericKubernetesResource` patch on `spec.replicas`
|
||||
- No StatefulSet — Argo Rollout owns pod lifecycle (canary/blue-green strategies respected)
|
||||
- Pod watch filter: label selector `app=nowchess-core` (Rollout sets this; `rollouts-pod-template-hash` is Argo's equivalent of `pod-template-hash`)
|
||||
|
||||
**Drain before scale-down**:
|
||||
1. Pick least-loaded core
|
||||
2. Migrate all its games to other cores via `BatchResubscribeGames`
|
||||
3. Call `DrainInstance(instanceId)` on that core (sets it to reject new subscriptions)
|
||||
4. After drain confirmed: patch Rollout `spec.replicas -= 1`
|
||||
|
||||
---
|
||||
|
||||
### 7. Cache Eviction
|
||||
|
||||
**Trigger**: coordinator scans `{prefix}:game:entry:*` every 10 minutes
|
||||
**Policy**: if `now - lastUpdated > 45min` AND `gameId` in any instance's games set → call `EvictGame`
|
||||
**Effect**: core removes game from `localEngines` and `unsubscribeGame`, `SREM` from instance set
|
||||
|
||||
---
|
||||
|
||||
### 8. Proto: `coordinator_service.proto`
|
||||
|
||||
```proto
|
||||
syntax = "proto3";
|
||||
package de.nowchess.coordinator;
|
||||
|
||||
service CoordinatorService {
|
||||
// Core → Coordinator: bidirectional stream for liveness
|
||||
rpc HeartbeatStream(stream HeartbeatFrame) returns (stream CoordinatorCommand);
|
||||
|
||||
// Coordinator → Core: batch resubscribe after failover or rebalance
|
||||
rpc BatchResubscribeGames(BatchResubscribeRequest) returns (BatchResubscribeResponse);
|
||||
|
||||
// Coordinator → Core: unsubscribe games (rebalance source)
|
||||
rpc UnsubscribeGames(UnsubscribeGamesRequest) returns (UnsubscribeGamesResponse);
|
||||
|
||||
// Coordinator → Core: evict idle games from local cache
|
||||
rpc EvictGames(EvictGamesRequest) returns (EvictGamesResponse);
|
||||
|
||||
// Coordinator → Core: drain instance before scale-down
|
||||
rpc DrainInstance(DrainInstanceRequest) returns (DrainInstanceResponse);
|
||||
}
|
||||
|
||||
message HeartbeatFrame {
|
||||
string instanceId = 1;
|
||||
string hostname = 2;
|
||||
int32 httpPort = 3;
|
||||
int32 grpcPort = 4;
|
||||
int32 subscriptionCount = 5;
|
||||
int32 localCacheSize = 6;
|
||||
int64 timestampMillis = 7;
|
||||
}
|
||||
|
||||
message CoordinatorCommand {
|
||||
// Future: coordinator can push commands back (e.g., "start draining")
|
||||
string type = 1;
|
||||
string payload = 2;
|
||||
}
|
||||
|
||||
message BatchResubscribeRequest {
|
||||
repeated string gameIds = 1;
|
||||
}
|
||||
|
||||
message BatchResubscribeResponse {
|
||||
int32 subscribedCount = 1;
|
||||
repeated string failedGameIds = 2;
|
||||
}
|
||||
|
||||
message UnsubscribeGamesRequest {
|
||||
repeated string gameIds = 1;
|
||||
}
|
||||
|
||||
message UnsubscribeGamesResponse {
|
||||
int32 unsubscribedCount = 1;
|
||||
}
|
||||
|
||||
message EvictGamesRequest {
|
||||
repeated string gameIds = 1;
|
||||
}
|
||||
|
||||
message EvictGamesResponse {
|
||||
int32 evictedCount = 1;
|
||||
}
|
||||
|
||||
message DrainInstanceRequest {}
|
||||
|
||||
message DrainInstanceResponse {
|
||||
int32 gamesMigrated = 0;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 9. Coordinator REST API (internal)
|
||||
|
||||
- `GET /api/coordinator/instances` — all cores with load, health state
|
||||
- `GET /api/coordinator/metrics` — load distribution, rebalance history
|
||||
- `POST /api/coordinator/rebalance` — manual rebalance trigger
|
||||
- `POST /api/coordinator/failover/{instanceId}` — manual failover
|
||||
- `POST /api/coordinator/scale-up` / `scale-down` — manual scaling
|
||||
|
||||
---
|
||||
|
||||
### 10. Configuration
|
||||
|
||||
**`modules/coordinator/src/main/resources/application.yml`**:
|
||||
```yaml
|
||||
quarkus.application.name: nowchess-coordinator
|
||||
quarkus.http.port: 8086
|
||||
quarkus.grpc.server.port: 9086
|
||||
|
||||
nowchess.coordinator.max-games-per-core: 500
|
||||
nowchess.coordinator.max-deviation-percent: 20
|
||||
nowchess.coordinator.rebalance-interval: 30s
|
||||
nowchess.coordinator.rebalance-min-interval: 60s
|
||||
nowchess.coordinator.heartbeat-ttl: 5s
|
||||
nowchess.coordinator.stream-heartbeat-interval: 200ms
|
||||
nowchess.coordinator.cache-eviction-interval: 10m
|
||||
nowchess.coordinator.game-idle-threshold: 45m
|
||||
nowchess.coordinator.auto-scale-enabled: false
|
||||
nowchess.coordinator.scale-up-threshold: 0.8
|
||||
nowchess.coordinator.scale-down-threshold: 0.3
|
||||
nowchess.coordinator.scale-min-replicas: 2
|
||||
nowchess.coordinator.scale-max-replicas: 10
|
||||
nowchess.coordinator.k8s-namespace: default
|
||||
nowchess.coordinator.k8s-rollout-name: nowchess-core
|
||||
nowchess.coordinator.k8s-rollout-label-selector: app=nowchess-core
|
||||
|
||||
quarkus.kubernetes-client.trust-certs: true
|
||||
```
|
||||
|
||||
**Core `application.yml` additions**:
|
||||
```yaml
|
||||
nowchess.coordinator.host: localhost
|
||||
nowchess.coordinator.grpc-port: 9086
|
||||
nowchess.coordinator.stream-heartbeat-interval: 200ms
|
||||
nowchess.coordinator.redis-heartbeat-interval: 2s
|
||||
nowchess.coordinator.instance-id: ${HOSTNAME:local}-${quarkus.uuid}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 11. Files to Create / Modify
|
||||
|
||||
**New — `modules/coordinator/`**:
|
||||
```
|
||||
build.gradle.kts
|
||||
src/main/proto/coordinator_service.proto
|
||||
src/main/resources/application.yml
|
||||
src/main/scala/de/nowchess/coordinator/
|
||||
resource/CoordinatorResource.scala # REST endpoints
|
||||
service/InstanceRegistry.scala # Redis instance list + in-memory map
|
||||
service/HealthMonitor.scala # gRPC stream watcher + Redis TTL + k8s watch
|
||||
service/FailoverService.scala # dead core → BatchResubscribe
|
||||
service/LoadBalancer.scala # rebalance logic
|
||||
service/AutoScaler.scala # k8s StatefulSet scaling
|
||||
service/CacheEvictionManager.scala # idle game eviction
|
||||
grpc/CoordinatorGrpcServer.scala # CoordinatorService gRPC impl (for HeartbeatStream)
|
||||
```
|
||||
|
||||
**Modify — `modules/core/`**:
|
||||
- `build.gradle.kts` — add `coordinator_service.proto` stub, keep grpc dep
|
||||
- `src/main/proto/coordinator_service.proto` — copy (or symlink) proto for stub generation
|
||||
- `src/main/scala/de/nowchess/chess/redis/GameRedisSubscriberManager.scala` — `SADD`/`SREM` on subscribe/unsubscribe + implement `BatchResubscribeGames`, `UnsubscribeGames`, `EvictGames`, `DrainInstance` gRPC handlers
|
||||
- `src/main/scala/de/nowchess/chess/` — new `InstanceHeartbeatService.scala` (startup, gRPC stream, Redis TTL refresh)
|
||||
- `src/main/resources/application.yml` — coordinator connection config
|
||||
|
||||
**Modify — root**:
|
||||
- `settings.gradle.kts` — add `include("modules/coordinator")`
|
||||
|
||||
---
|
||||
|
||||
## Verification
|
||||
|
||||
1. `./compile` — coordinator and core compile cleanly
|
||||
2. **Stream detection**: start core + coordinator; kill core JVM (`kill -9`); coordinator logs failover within 300ms
|
||||
3. **Game continuity**: active game on killed core; WebSocket client reconnects and receives game state
|
||||
4. **Rebalance**: create 600 games on core-1 (2-core setup); coordinator rebalances ~100 to core-2
|
||||
5. **Fallback**: disconnect gRPC stream manually but keep core alive; Redis TTL fallback triggers within 7s
|
||||
6. **Cache eviction**: create idle game; coordinator calls `EvictGames` after 45min idle
|
||||
7. **REST metrics**: `curl localhost:8086/api/coordinator/metrics` returns per-core load + health
|
||||
8. **Restart recovery**: restart coordinator; gRPC streams re-establish from cores; state rebuilt from Redis
|
||||
|
||||
---
|
||||
|
||||
## Dependencies (new)
|
||||
|
||||
- `io.fabric8:kubernetes-client:6.13.0` (Fabric8 k8s client — handles Argo `Rollout` CRD via `GenericKubernetesResource`; no Argo Java SDK needed)
|
||||
- Redisson — already in core, reuse via shared config
|
||||
- Quarkus gRPC — already in core, reuse
|
||||
@@ -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,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,27 @@
|
||||
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"},
|
||||
"timeControl": {
|
||||
"limitSeconds": 300,
|
||||
"incrementSeconds": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
meta {
|
||||
name: Get Game
|
||||
type: http
|
||||
seq: 2
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{baseUrl}}/api/board/game/{{gameId}}
|
||||
body: none
|
||||
auth: none
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
gameId: j0nPtcjl
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
meta {
|
||||
name: Stream Game
|
||||
type: ws
|
||||
seq: 3
|
||||
}
|
||||
|
||||
ws {
|
||||
url: {{wsBaseUrl}}/api/board/game/{{gameId}}/ws
|
||||
body: ws
|
||||
auth: none
|
||||
}
|
||||
|
||||
body:ws {
|
||||
name: move
|
||||
content: '''
|
||||
{
|
||||
"type": "MOVE",
|
||||
"uci": "b1c3"
|
||||
}
|
||||
'''
|
||||
}
|
||||
|
||||
body:ws {
|
||||
name: ping
|
||||
content: '''
|
||||
{
|
||||
"type": "PING"
|
||||
}
|
||||
'''
|
||||
}
|
||||
|
||||
vars:pre-request {
|
||||
gameId: j0nPtcjl
|
||||
}
|
||||
@@ -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,28 @@
|
||||
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"},
|
||||
"timeControl": {
|
||||
"limitSeconds": 300,
|
||||
"incrementSeconds": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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: Yg200tOF
|
||||
}
|
||||
@@ -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: COy3oigz
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"version": "1",
|
||||
"name": "NowChess API",
|
||||
"type": "collection",
|
||||
"ignore": []
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
vars {
|
||||
baseUrl: http://localhost:8080
|
||||
wsBaseUrl: ws://localhost:8084
|
||||
ioBaseUrl: http://localhost:8081
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
meta {
|
||||
name: Export FEN
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
http {
|
||||
method: POST
|
||||
url: {{ioBaseUrl}}/io/export/fen
|
||||
body: json
|
||||
auth: none
|
||||
}
|
||||
|
||||
headers {
|
||||
Content-Type: application/json
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"board": {
|
||||
"a1": {"color": "White", "pieceType": "Rook"},
|
||||
"b1": {"color": "White", "pieceType": "Knight"},
|
||||
"c1": {"color": "White", "pieceType": "Bishop"},
|
||||
"d1": {"color": "White", "pieceType": "Queen"},
|
||||
"e1": {"color": "White", "pieceType": "King"},
|
||||
"f1": {"color": "White", "pieceType": "Bishop"},
|
||||
"g1": {"color": "White", "pieceType": "Knight"},
|
||||
"h1": {"color": "White", "pieceType": "Rook"},
|
||||
"a2": {"color": "White", "pieceType": "Pawn"},
|
||||
"b2": {"color": "White", "pieceType": "Pawn"},
|
||||
"c2": {"color": "White", "pieceType": "Pawn"},
|
||||
"d2": {"color": "White", "pieceType": "Pawn"},
|
||||
"e2": {"color": "White", "pieceType": "Pawn"},
|
||||
"f2": {"color": "White", "pieceType": "Pawn"},
|
||||
"g2": {"color": "White", "pieceType": "Pawn"},
|
||||
"h2": {"color": "White", "pieceType": "Pawn"},
|
||||
"a7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"b7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"c7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"d7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"e7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"f7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"g7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"h7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"a8": {"color": "Black", "pieceType": "Rook"},
|
||||
"b8": {"color": "Black", "pieceType": "Knight"},
|
||||
"c8": {"color": "Black", "pieceType": "Bishop"},
|
||||
"d8": {"color": "Black", "pieceType": "Queen"},
|
||||
"e8": {"color": "Black", "pieceType": "King"},
|
||||
"f8": {"color": "Black", "pieceType": "Bishop"},
|
||||
"g8": {"color": "Black", "pieceType": "Knight"},
|
||||
"h8": {"color": "Black", "pieceType": "Rook"}
|
||||
},
|
||||
"turn": "White",
|
||||
"castlingRights": {
|
||||
"whiteKingSide": true,
|
||||
"whiteQueenSide": true,
|
||||
"blackKingSide": true,
|
||||
"blackQueenSide": true
|
||||
},
|
||||
"enPassantSquare": null,
|
||||
"halfMoveClock": 0,
|
||||
"moves": [],
|
||||
"result": null,
|
||||
"initialBoard": {
|
||||
"a1": {"color": "White", "pieceType": "Rook"},
|
||||
"b1": {"color": "White", "pieceType": "Knight"},
|
||||
"c1": {"color": "White", "pieceType": "Bishop"},
|
||||
"d1": {"color": "White", "pieceType": "Queen"},
|
||||
"e1": {"color": "White", "pieceType": "King"},
|
||||
"f1": {"color": "White", "pieceType": "Bishop"},
|
||||
"g1": {"color": "White", "pieceType": "Knight"},
|
||||
"h1": {"color": "White", "pieceType": "Rook"},
|
||||
"a2": {"color": "White", "pieceType": "Pawn"},
|
||||
"b2": {"color": "White", "pieceType": "Pawn"},
|
||||
"c2": {"color": "White", "pieceType": "Pawn"},
|
||||
"d2": {"color": "White", "pieceType": "Pawn"},
|
||||
"e2": {"color": "White", "pieceType": "Pawn"},
|
||||
"f2": {"color": "White", "pieceType": "Pawn"},
|
||||
"g2": {"color": "White", "pieceType": "Pawn"},
|
||||
"h2": {"color": "White", "pieceType": "Pawn"},
|
||||
"a7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"b7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"c7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"d7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"e7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"f7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"g7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"h7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"a8": {"color": "Black", "pieceType": "Rook"},
|
||||
"b8": {"color": "Black", "pieceType": "Knight"},
|
||||
"c8": {"color": "Black", "pieceType": "Bishop"},
|
||||
"d8": {"color": "Black", "pieceType": "Queen"},
|
||||
"e8": {"color": "Black", "pieceType": "King"},
|
||||
"f8": {"color": "Black", "pieceType": "Bishop"},
|
||||
"g8": {"color": "Black", "pieceType": "Knight"},
|
||||
"h8": {"color": "Black", "pieceType": "Rook"}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
meta {
|
||||
name: Export PGN
|
||||
type: http
|
||||
seq: 2
|
||||
}
|
||||
|
||||
http {
|
||||
method: POST
|
||||
url: {{ioBaseUrl}}/io/export/pgn
|
||||
body: json
|
||||
auth: none
|
||||
}
|
||||
|
||||
headers {
|
||||
Content-Type: application/json
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"board": {
|
||||
"a1": {"color": "White", "pieceType": "Rook"},
|
||||
"b1": {"color": "White", "pieceType": "Knight"},
|
||||
"c1": {"color": "White", "pieceType": "Bishop"},
|
||||
"d1": {"color": "White", "pieceType": "Queen"},
|
||||
"e1": {"color": "White", "pieceType": "King"},
|
||||
"f1": {"color": "White", "pieceType": "Bishop"},
|
||||
"g1": {"color": "White", "pieceType": "Knight"},
|
||||
"h1": {"color": "White", "pieceType": "Rook"},
|
||||
"a2": {"color": "White", "pieceType": "Pawn"},
|
||||
"b2": {"color": "White", "pieceType": "Pawn"},
|
||||
"c2": {"color": "White", "pieceType": "Pawn"},
|
||||
"d2": {"color": "White", "pieceType": "Pawn"},
|
||||
"e2": {"color": "White", "pieceType": "Pawn"},
|
||||
"f2": {"color": "White", "pieceType": "Pawn"},
|
||||
"g2": {"color": "White", "pieceType": "Pawn"},
|
||||
"h2": {"color": "White", "pieceType": "Pawn"},
|
||||
"a7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"b7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"c7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"d7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"e7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"f7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"g7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"h7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"a8": {"color": "Black", "pieceType": "Rook"},
|
||||
"b8": {"color": "Black", "pieceType": "Knight"},
|
||||
"c8": {"color": "Black", "pieceType": "Bishop"},
|
||||
"d8": {"color": "Black", "pieceType": "Queen"},
|
||||
"e8": {"color": "Black", "pieceType": "King"},
|
||||
"f8": {"color": "Black", "pieceType": "Bishop"},
|
||||
"g8": {"color": "Black", "pieceType": "Knight"},
|
||||
"h8": {"color": "Black", "pieceType": "Rook"}
|
||||
},
|
||||
"turn": "White",
|
||||
"castlingRights": {
|
||||
"whiteKingSide": true,
|
||||
"whiteQueenSide": true,
|
||||
"blackKingSide": true,
|
||||
"blackQueenSide": true
|
||||
},
|
||||
"enPassantSquare": null,
|
||||
"halfMoveClock": 0,
|
||||
"moves": [],
|
||||
"result": null,
|
||||
"initialBoard": {
|
||||
"a1": {"color": "White", "pieceType": "Rook"},
|
||||
"b1": {"color": "White", "pieceType": "Knight"},
|
||||
"c1": {"color": "White", "pieceType": "Bishop"},
|
||||
"d1": {"color": "White", "pieceType": "Queen"},
|
||||
"e1": {"color": "White", "pieceType": "King"},
|
||||
"f1": {"color": "White", "pieceType": "Bishop"},
|
||||
"g1": {"color": "White", "pieceType": "Knight"},
|
||||
"h1": {"color": "White", "pieceType": "Rook"},
|
||||
"a2": {"color": "White", "pieceType": "Pawn"},
|
||||
"b2": {"color": "White", "pieceType": "Pawn"},
|
||||
"c2": {"color": "White", "pieceType": "Pawn"},
|
||||
"d2": {"color": "White", "pieceType": "Pawn"},
|
||||
"e2": {"color": "White", "pieceType": "Pawn"},
|
||||
"f2": {"color": "White", "pieceType": "Pawn"},
|
||||
"g2": {"color": "White", "pieceType": "Pawn"},
|
||||
"h2": {"color": "White", "pieceType": "Pawn"},
|
||||
"a7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"b7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"c7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"d7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"e7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"f7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"g7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"h7": {"color": "Black", "pieceType": "Pawn"},
|
||||
"a8": {"color": "Black", "pieceType": "Rook"},
|
||||
"b8": {"color": "Black", "pieceType": "Knight"},
|
||||
"c8": {"color": "Black", "pieceType": "Bishop"},
|
||||
"d8": {"color": "Black", "pieceType": "Queen"},
|
||||
"e8": {"color": "Black", "pieceType": "King"},
|
||||
"f8": {"color": "Black", "pieceType": "Bishop"},
|
||||
"g8": {"color": "Black", "pieceType": "Knight"},
|
||||
"h8": {"color": "Black", "pieceType": "Rook"}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
meta {
|
||||
name: export
|
||||
seq: 2
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
meta {
|
||||
name: Import FEN
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
http {
|
||||
method: POST
|
||||
url: {{ioBaseUrl}}/io/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"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
meta {
|
||||
name: Import PGN
|
||||
type: http
|
||||
seq: 2
|
||||
}
|
||||
|
||||
http {
|
||||
method: POST
|
||||
url: {{ioBaseUrl}}/io/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: 1
|
||||
}
|
||||
+93
-2
@@ -1,11 +1,72 @@
|
||||
plugins {
|
||||
id("org.sonarqube") version "7.2.3.7755"
|
||||
id("org.scoverage") version "8.1" apply false
|
||||
id("com.diffplug.spotless") version "8.4.0" apply false
|
||||
id("io.github.cosmicsilence.scalafix") version "0.2.6" apply false
|
||||
}
|
||||
|
||||
group = "de.nowchess"
|
||||
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/api/**",
|
||||
// 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",
|
||||
// IoResource — same rationale as GameResource; @QuarkusTest not instrumented by Scoverage
|
||||
"**/io/src/main/scala/de/nowchess/io/service/resource/IoResource.scala",
|
||||
// JacksonConfig — Quarkus lifecycle hook, no testable logic beyond ObjectMapper registration
|
||||
"**/io/src/main/scala/de/nowchess/io/service/config/JacksonConfig.scala",
|
||||
//RuleSetRestAdapter - Quarkus integration of rule into core, only testable with Quarkus tests
|
||||
"**/core/src/main/de/nowchess/chess/adapter/RuleSetRestAdapter.scala",
|
||||
// AccountResource / ChallengeResource — REST integration layer; @QuarkusTest not instrumented by Scoverage
|
||||
"**/account/src/main/scala/de/nowchess/account/resource/**",
|
||||
// JacksonConfig / NativeReflectionConfig — Quarkus lifecycle hooks, no testable logic
|
||||
"**/account/src/main/scala/de/nowchess/account/config/**",
|
||||
// WebSocket service — infrastructure CDI beans (RedisConfig)
|
||||
"**/ws/src/main/scala/de/nowchess/ws/config/**",
|
||||
// GameWebSocketResource in core — replaced by ws module
|
||||
"**/core/src/main/scala/de/nowchess/chess/resource/GameWebSocketResource.scala",
|
||||
// Coordinator infrastructure — gRPC, microservice orchestration
|
||||
"**/coordinator/src/main/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 {
|
||||
properties {
|
||||
property("sonar.projectKey", "Now-Chess-Systems")
|
||||
@@ -20,19 +81,49 @@ sonar {
|
||||
}.joinToString(",")
|
||||
|
||||
property("sonar.scala.coverage.reportPaths", scoverageReports)
|
||||
property("sonar.coverage.exclusions", coverageExclusions.joinToString(","))
|
||||
}
|
||||
}
|
||||
|
||||
val versions = mapOf(
|
||||
"QUARKUS_SCALA3" to "1.0.0",
|
||||
"SCALA3" to "3.5.1",
|
||||
"SCALA_LIBRARY" to "2.13.18",
|
||||
"SCALA_LIBRARY" to "2.13.16",
|
||||
"SCALATEST" to "3.2.19",
|
||||
"SCALATEST_JUNIT" to "0.1.11",
|
||||
"SCOVERAGE" to "2.1.1",
|
||||
"SCALAFX" to "21.0.0-R32",
|
||||
"JAVAFX" to "21.0.1",
|
||||
"JUNIT_BOM" to "5.13.4"
|
||||
"JUNIT_BOM" to "5.13.4",
|
||||
"ONNXRUNTIME" to "1.19.2",
|
||||
"SCALA_PARSER_COMBINATORS" to "2.4.0",
|
||||
"FASTPARSE" to "3.0.2",
|
||||
"JACKSON" to "2.17.2",
|
||||
"JACKSON_SCALA" to "2.17.2"
|
||||
)
|
||||
extra["VERSIONS"] = versions
|
||||
|
||||
subprojects {
|
||||
apply(plugin = "com.diffplug.spotless")
|
||||
|
||||
pluginManager.withPlugin("scala") {
|
||||
configure<com.diffplug.gradle.spotless.SpotlessExtension> {
|
||||
scala {
|
||||
scalafmt().configFile(rootProject.file(".scalafmt.conf"))
|
||||
}
|
||||
}
|
||||
|
||||
apply(plugin = "io.github.cosmicsilence.scalafix")
|
||||
configure<io.github.cosmicsilence.scalafix.ScalafixExtension> {
|
||||
configFile.set(rootProject.file(".scalafix.conf"))
|
||||
}
|
||||
|
||||
// Disable SemanticDB config for the scoverage source set — it sets -sourceroot to
|
||||
// the root project dir, which conflicts with scoverage's own -sourceroot and causes
|
||||
// reportTestScoverage to fail with "No source root found".
|
||||
tasks.matching { it.name in setOf("configSemanticDBScoverage", "checkScalafixScoverage", "checkScalafixTest") }.configureEach {
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# Gradle properties
|
||||
quarkusPluginId=io.quarkus
|
||||
quarkusPluginVersion=3.32.4
|
||||
quarkusPlatformGroupId=io.quarkus.platform
|
||||
quarkusPlatformArtifactId=quarkus-bom
|
||||
quarkusPlatformVersion=3.32.4
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#Sat Mar 21 14:37:06 CET 2026
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import glob,re
|
||||
mods=['api','core','io','rule','ui']
|
||||
mods=['api','core','io','rule','ui', 'bot']
|
||||
tot=0
|
||||
for m in mods:
|
||||
s=0
|
||||
|
||||
@@ -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/
|
||||
@@ -0,0 +1,20 @@
|
||||
## (2026-04-30)
|
||||
|
||||
### Features
|
||||
|
||||
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||
* **docker:** add .dockerignore and .gitignore files for build exclusions ([c987d8e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c987d8e258c0e6c4cfbdaa8381c64c410d7a2b83))
|
||||
* **docker:** add Dockerfiles for building Quarkus application in native and JVM modes ([3f2d2bb](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f2d2bb4c97fa8cddba66e1da4427c54236dfeed))
|
||||
* **docker:** add Dockerfiles for Quarkus application in JVM and native modes ([34b9933](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/34b993304670cf2aa62cd2f6460cee7b9864b08e))
|
||||
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||
## (2026-04-30)
|
||||
|
||||
### Features
|
||||
|
||||
* **config:** add H2 database configuration for testing environment ([39c9e49](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/39c9e492cef2515368c074da9406f95e9c0c9e64))
|
||||
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||
* **docker:** add .dockerignore and .gitignore files for build exclusions ([c987d8e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c987d8e258c0e6c4cfbdaa8381c64c410d7a2b83))
|
||||
* **docker:** add Dockerfiles for building Quarkus application in native and JVM modes ([3f2d2bb](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f2d2bb4c97fa8cddba66e1da4427c54236dfeed))
|
||||
* **docker:** add Dockerfiles for Quarkus application in JVM and native modes ([34b9933](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/34b993304670cf2aa62cd2f6460cee7b9864b08e))
|
||||
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||
@@ -0,0 +1,117 @@
|
||||
plugins {
|
||||
id("scala")
|
||||
id("org.scoverage") version "8.1"
|
||||
id("io.quarkus")
|
||||
}
|
||||
|
||||
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"]!!)
|
||||
}
|
||||
|
||||
tasks.withType<ScalaCompile> {
|
||||
scalaCompileOptions.additionalParameters = listOf("-encoding", "UTF-8")
|
||||
}
|
||||
|
||||
val quarkusPlatformGroupId: String by project
|
||||
val quarkusPlatformArtifactId: String by project
|
||||
val quarkusPlatformVersion: String by project
|
||||
|
||||
dependencies {
|
||||
|
||||
runtimeOnly("io.quarkus:quarkus-jdbc-h2")
|
||||
|
||||
compileOnly("org.scala-lang:scala3-compiler_3") {
|
||||
version {
|
||||
strictly(versions["SCALA3"]!!)
|
||||
}
|
||||
}
|
||||
implementation("org.scala-lang:scala3-library_3") {
|
||||
version {
|
||||
strictly(versions["SCALA3"]!!)
|
||||
}
|
||||
}
|
||||
|
||||
implementation(project(":modules:security"))
|
||||
|
||||
implementation(platform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}"))
|
||||
implementation("io.quarkus:quarkus-rest")
|
||||
implementation("io.quarkus:quarkus-rest-jackson")
|
||||
implementation("io.quarkus:quarkus-rest-client-jackson")
|
||||
implementation("io.quarkus:quarkus-config-yaml")
|
||||
implementation("io.quarkus:quarkus-arc")
|
||||
implementation("io.quarkus:quarkus-hibernate-orm-panache")
|
||||
implementation("io.quarkus:quarkus-jdbc-postgresql")
|
||||
implementation("io.quarkus:quarkus-smallrye-jwt")
|
||||
implementation("io.quarkus:quarkus-smallrye-jwt-build")
|
||||
implementation("io.quarkus:quarkus-elytron-security-common")
|
||||
implementation("io.quarkus:quarkus-smallrye-health")
|
||||
implementation("io.quarkus:quarkus-micrometer")
|
||||
implementation("io.quarkus:quarkus-smallrye-openapi")
|
||||
implementation("com.fasterxml.jackson.module:jackson-module-scala_3:${versions["JACKSON_SCALA"]!!}")
|
||||
implementation("io.quarkus:quarkus-redis-client")
|
||||
|
||||
testImplementation(platform("org.junit:junit-bom:5.13.4"))
|
||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||
testImplementation("org.scalatest:scalatest_3:${versions["SCALATEST"]!!}")
|
||||
testImplementation("co.helmethair:scalatest-junit-runner:${versions["SCALATEST_JUNIT"]!!}")
|
||||
testImplementation("io.quarkus:quarkus-junit")
|
||||
testImplementation("io.rest-assured:rest-assured")
|
||||
testImplementation("io.quarkus:quarkus-jdbc-h2")
|
||||
testImplementation("io.quarkus:quarkus-test-security")
|
||||
testImplementation("io.quarkus:quarkus-junit5-mockito")
|
||||
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||
}
|
||||
|
||||
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 {
|
||||
useJUnitPlatform {
|
||||
includeEngines("scalatest", "junit-jupiter")
|
||||
testLogging {
|
||||
events("passed", "skipped", "failed")
|
||||
showStandardStreams = true
|
||||
exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
|
||||
}
|
||||
}
|
||||
finalizedBy(tasks.reportScoverage)
|
||||
}
|
||||
tasks.reportScoverage {
|
||||
dependsOn(tasks.test)
|
||||
}
|
||||
|
||||
tasks.jar {
|
||||
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
||||
}
|
||||
@@ -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 :modules:account: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 modules/account/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"]
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"reflection": [
|
||||
{ "type": "scala.Tuple1[]" },
|
||||
{ "type": "scala.Tuple2[]" },
|
||||
{ "type": "scala.Tuple3[]" },
|
||||
{ "type": "scala.Tuple4[]" },
|
||||
{ "type": "scala.Tuple5[]" },
|
||||
{ "type": "scala.Tuple6[]" },
|
||||
{ "type": "scala.Tuple7[]" },
|
||||
{ "type": "scala.Tuple8[]" },
|
||||
{ "type": "scala.Tuple9[]" },
|
||||
{ "type": "scala.Tuple10[]" },
|
||||
{ "type": "scala.Tuple11[]" },
|
||||
{ "type": "scala.Tuple12[]" },
|
||||
{ "type": "scala.Tuple13[]" },
|
||||
{ "type": "scala.Tuple14[]" },
|
||||
{ "type": "scala.Tuple15[]" },
|
||||
{ "type": "scala.Tuple16[]" },
|
||||
{ "type": "scala.Tuple17[]" },
|
||||
{ "type": "scala.Tuple18[]" },
|
||||
{ "type": "scala.Tuple19[]" },
|
||||
{ "type": "scala.Tuple20[]" },
|
||||
{ "type": "scala.Tuple21[]" },
|
||||
{ "type": "scala.Tuple22[]" },
|
||||
{ "type": "com.fasterxml.jackson.module.scala.introspect.PropertyDescriptor[]" }
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
quarkus:
|
||||
http:
|
||||
port: 8083
|
||||
application:
|
||||
name: nowchess-account
|
||||
redis:
|
||||
hosts: redis://${REDIS_HOST:localhost}:${REDIS_PORT:6379}
|
||||
rest-client:
|
||||
core-service:
|
||||
url: http://localhost:8080
|
||||
smallrye-openapi:
|
||||
info-title: NowChess Account Service
|
||||
path: /openapi
|
||||
swagger-ui:
|
||||
path: /swagger-ui
|
||||
datasource:
|
||||
db-kind: postgresql
|
||||
username: ${DB_USER:nowchess}
|
||||
password: ${DB_PASSWORD:nowchess}
|
||||
jdbc:
|
||||
url: ${DB_URL:jdbc:postgresql://localhost:5432/nowchess}
|
||||
hibernate-orm:
|
||||
schema-management:
|
||||
strategy: update
|
||||
|
||||
nowchess:
|
||||
redis:
|
||||
host: localhost
|
||||
port: 6379
|
||||
prefix: nowchess
|
||||
internal:
|
||||
secret: 123abc
|
||||
|
||||
"%test":
|
||||
quarkus:
|
||||
datasource:
|
||||
db-kind: h2
|
||||
username: sa
|
||||
password: ""
|
||||
jdbc:
|
||||
url: jdbc:h2:mem:nowchess;DB_CLOSE_DELAY=-1
|
||||
hibernate-orm:
|
||||
schema-management:
|
||||
strategy: drop-and-create
|
||||
|
||||
"%dev":
|
||||
quarkus:
|
||||
datasource:
|
||||
db-kind: h2
|
||||
username: sa
|
||||
password: ""
|
||||
jdbc:
|
||||
url: jdbc:h2:mem:nowchess;DB_CLOSE_DELAY=-1
|
||||
hibernate-orm:
|
||||
schema-management:
|
||||
strategy: drop-and-create
|
||||
|
||||
"%deployed":
|
||||
quarkus:
|
||||
rest-client:
|
||||
core-service:
|
||||
url: ${CORE_SERVICE_URL}
|
||||
datasource:
|
||||
db-kind: postgresql
|
||||
username: ${DB_USER}
|
||||
password: ${DB_PASSWORD}
|
||||
jdbc:
|
||||
url: ${DB_URL}
|
||||
hibernate-orm:
|
||||
schema-management:
|
||||
strategy: update
|
||||
nowchess:
|
||||
redis:
|
||||
host: ${REDIS_HOST:localhost}
|
||||
port: ${REDIS_PORT:6379}
|
||||
prefix: ${REDIS_PREFIX:nowchess}
|
||||
internal:
|
||||
secret: ${INTERNAL_SECRET}
|
||||
mp:
|
||||
jwt:
|
||||
verify:
|
||||
publickey:
|
||||
location: ${JWT_PUBLIC_KEY_PATH:keys/public.pem}
|
||||
issuer: nowchess
|
||||
smallrye:
|
||||
jwt:
|
||||
sign:
|
||||
key:
|
||||
location: ${JWT_PRIVATE_KEY_PATH:keys/private.pem}
|
||||
@@ -0,0 +1,9 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxDsnsCAl0vQx7Vu9CLDZ
|
||||
g0SG05NgUzu9T+3DTEaHGq60T2uriO8BenwyvsF3BnDqTbKf4voohZ1DNfzdbT1J
|
||||
Fj8B62FrDmxcO+sp1/b5HUCJP6y2uSRCmzOHe5k7Pk1IEi72FgBpKXSRkFibRlVf
|
||||
634g7mgsPZAQ9PJEsv4Qvm05T9L6+Gmq6N3bMVLKRXs4RhDhaFbYH9GtUg1eI0yH
|
||||
YjGyRfqzW/nqVMstOLHt8CuPouq4p7eMzeDH3YHkxPm4GG5foCXMOd2DZrW0SCcr
|
||||
7dhFeNVWzQ2m53eOhBzNQX+v3pgjVStsePhBRt2LyGfwkNzmqDgqWsMzSHRMY+cn
|
||||
WQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
@@ -0,0 +1,27 @@
|
||||
package de.nowchess.account.client
|
||||
|
||||
import de.nowchess.security.InternalSecretClientFilter
|
||||
import jakarta.ws.rs.*
|
||||
import jakarta.ws.rs.core.MediaType
|
||||
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient
|
||||
|
||||
case class CorePlayerInfo(id: String, displayName: String)
|
||||
case class CoreTimeControl(limitSeconds: Option[Int], incrementSeconds: Option[Int], daysPerMove: Option[Int])
|
||||
case class CoreCreateGameRequest(
|
||||
white: Option[CorePlayerInfo],
|
||||
black: Option[CorePlayerInfo],
|
||||
timeControl: Option[CoreTimeControl],
|
||||
mode: Option[String],
|
||||
)
|
||||
case class CoreGameResponse(gameId: String)
|
||||
|
||||
@Path("/api/board/game")
|
||||
@RegisterRestClient(configKey = "core-service")
|
||||
@RegisterProvider(classOf[InternalSecretClientFilter])
|
||||
trait CoreGameClient:
|
||||
|
||||
@POST
|
||||
@Consumes(Array(MediaType.APPLICATION_JSON))
|
||||
@Produces(Array(MediaType.APPLICATION_JSON))
|
||||
def createGame(req: CoreCreateGameRequest): CoreGameResponse
|
||||
@@ -0,0 +1,17 @@
|
||||
package de.nowchess.account.config
|
||||
|
||||
import com.fasterxml.jackson.core.Version
|
||||
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(new DefaultScalaModule() {
|
||||
override def version(): Version =
|
||||
// scalafix:off DisableSyntax.null
|
||||
new Version(2, 21, 1, null, "com.fasterxml.jackson.module", "jackson-module-scala")
|
||||
// scalafix:on DisableSyntax.null
|
||||
})
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package de.nowchess.account.config
|
||||
|
||||
import de.nowchess.account.client.{CoreCreateGameRequest, CoreGameResponse, CorePlayerInfo, CoreTimeControl}
|
||||
import de.nowchess.account.domain.{
|
||||
BotAccount,
|
||||
Challenge,
|
||||
ChallengeColor,
|
||||
ChallengeStatus,
|
||||
DeclineReason,
|
||||
OfficialBotAccount,
|
||||
TimeControl,
|
||||
UserAccount,
|
||||
}
|
||||
import de.nowchess.account.dto.*
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection
|
||||
|
||||
@RegisterForReflection(
|
||||
targets = Array(
|
||||
classOf[UserAccount],
|
||||
classOf[BotAccount],
|
||||
classOf[OfficialBotAccount],
|
||||
classOf[Challenge],
|
||||
classOf[ChallengeColor],
|
||||
classOf[ChallengeStatus],
|
||||
classOf[DeclineReason],
|
||||
classOf[TimeControl],
|
||||
classOf[LoginRequest],
|
||||
classOf[TokenResponse],
|
||||
classOf[PlayerInfo],
|
||||
classOf[PublicAccountDto],
|
||||
classOf[BotAccountDto],
|
||||
classOf[BotAccountWithTokenDto],
|
||||
classOf[OfficialBotAccountDto],
|
||||
classOf[CreateBotAccountRequest],
|
||||
classOf[UpdateBotNameRequest],
|
||||
classOf[RotatedTokenDto],
|
||||
classOf[TimeControlDto],
|
||||
classOf[ChallengeRequest],
|
||||
classOf[ChallengeDto],
|
||||
classOf[DeclineRequest],
|
||||
classOf[ChallengeListDto],
|
||||
classOf[ErrorDto],
|
||||
classOf[CorePlayerInfo],
|
||||
classOf[CoreTimeControl],
|
||||
classOf[CoreCreateGameRequest],
|
||||
classOf[CoreGameResponse],
|
||||
classOf[OfficialChallengeResponse],
|
||||
),
|
||||
)
|
||||
class NativeReflectionConfig
|
||||
@@ -0,0 +1,12 @@
|
||||
package de.nowchess.account.config
|
||||
|
||||
import jakarta.enterprise.context.ApplicationScoped
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty
|
||||
import scala.compiletime.uninitialized
|
||||
|
||||
@ApplicationScoped
|
||||
class RedisConfig:
|
||||
// scalafix:off DisableSyntax.var
|
||||
@ConfigProperty(name = "nowchess.redis.prefix", defaultValue = "nowchess")
|
||||
var prefix: String = uninitialized
|
||||
// scalafix:on DisableSyntax.var
|
||||
@@ -0,0 +1,56 @@
|
||||
package de.nowchess.account.domain
|
||||
|
||||
import io.quarkus.hibernate.orm.panache.PanacheEntityBase
|
||||
import jakarta.persistence.*
|
||||
import scala.compiletime.uninitialized
|
||||
|
||||
import java.time.Instant
|
||||
import java.util.UUID
|
||||
import scala.Conversion
|
||||
|
||||
@Entity
|
||||
@Table(name = "challenges")
|
||||
class Challenge extends PanacheEntityBase:
|
||||
// scalafix:off DisableSyntax.var
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.UUID)
|
||||
var id: UUID = uninitialized
|
||||
|
||||
@ManyToOne
|
||||
var challenger: UserAccount = uninitialized
|
||||
|
||||
@ManyToOne
|
||||
var destUser: UserAccount = uninitialized
|
||||
|
||||
@Convert(converter = classOf[ChallengeColorConverter])
|
||||
@Column(columnDefinition = "varchar(255)")
|
||||
var color: ChallengeColor = uninitialized
|
||||
|
||||
@Convert(converter = classOf[ChallengeStatusConverter])
|
||||
@Column(columnDefinition = "varchar(255)")
|
||||
var status: ChallengeStatus = uninitialized
|
||||
|
||||
@Convert(converter = classOf[DeclineReasonConverter])
|
||||
@Column(nullable = true, columnDefinition = "varchar(255)")
|
||||
var declineReason: DeclineReason = uninitialized
|
||||
|
||||
var timeControlType: String = uninitialized
|
||||
|
||||
@Column(nullable = true)
|
||||
var timeControlLimit: java.lang.Integer = uninitialized
|
||||
|
||||
@Column(nullable = true)
|
||||
var timeControlIncrement: java.lang.Integer = uninitialized
|
||||
|
||||
var createdAt: Instant = uninitialized
|
||||
|
||||
var expiresAt: Instant = uninitialized
|
||||
|
||||
@Column(nullable = true)
|
||||
var gameId: String = uninitialized
|
||||
// scalafix:on
|
||||
|
||||
def gameIdOpt: Option[String] = Option(gameId)
|
||||
def declineReasonOpt: Option[DeclineReason] = Option(declineReason)
|
||||
def timeControlLimitOpt: Option[Int] = Option(timeControlLimit).map(_.intValue())
|
||||
def timeControlIncrementOpt: Option[Int] = Option(timeControlIncrement).map(_.intValue())
|
||||
@@ -0,0 +1,4 @@
|
||||
package de.nowchess.account.domain
|
||||
|
||||
enum ChallengeColor:
|
||||
case White, Black, Random
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package de.nowchess.account.domain
|
||||
|
||||
import jakarta.persistence.AttributeConverter
|
||||
import jakarta.persistence.Converter
|
||||
|
||||
@Converter(autoApply = true)
|
||||
class ChallengeColorConverter extends AttributeConverter[ChallengeColor, String]:
|
||||
override def convertToDatabaseColumn(attribute: ChallengeColor): String =
|
||||
Option(attribute).map(_.toString).orNull
|
||||
|
||||
override def convertToEntityAttribute(dbData: String): ChallengeColor =
|
||||
Option(dbData).map(ChallengeColor.valueOf).orNull
|
||||
@@ -0,0 +1,4 @@
|
||||
package de.nowchess.account.domain
|
||||
|
||||
enum ChallengeStatus:
|
||||
case Created, Canceled, Declined, Accepted
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package de.nowchess.account.domain
|
||||
|
||||
import jakarta.persistence.AttributeConverter
|
||||
import jakarta.persistence.Converter
|
||||
|
||||
@Converter(autoApply = true)
|
||||
class ChallengeStatusConverter extends AttributeConverter[ChallengeStatus, String]:
|
||||
override def convertToDatabaseColumn(attribute: ChallengeStatus): String =
|
||||
Option(attribute).map(_.toString).orNull
|
||||
|
||||
override def convertToEntityAttribute(dbData: String): ChallengeStatus =
|
||||
Option(dbData).map(ChallengeStatus.valueOf).orNull
|
||||
@@ -0,0 +1,4 @@
|
||||
package de.nowchess.account.domain
|
||||
|
||||
enum DeclineReason:
|
||||
case Generic, Later, TooFast, TooSlow, TimeControl, Rated, Casual, Standard, Variant, NoBot, OnlyBot
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package de.nowchess.account.domain
|
||||
|
||||
import jakarta.persistence.AttributeConverter
|
||||
import jakarta.persistence.Converter
|
||||
|
||||
@Converter(autoApply = true)
|
||||
class DeclineReasonConverter extends AttributeConverter[DeclineReason, String]:
|
||||
override def convertToDatabaseColumn(attribute: DeclineReason): String =
|
||||
Option(attribute).map(_.toString).orNull
|
||||
|
||||
override def convertToEntityAttribute(dbData: String): DeclineReason =
|
||||
Option(dbData).map(DeclineReason.valueOf).orNull
|
||||
@@ -0,0 +1,7 @@
|
||||
package de.nowchess.account.domain
|
||||
|
||||
sealed trait TimeControl
|
||||
|
||||
object TimeControl:
|
||||
case class Clock(limit: Int, increment: Int) extends TimeControl
|
||||
case object Unlimited extends TimeControl
|
||||
@@ -0,0 +1,78 @@
|
||||
package de.nowchess.account.domain
|
||||
|
||||
import io.quarkus.hibernate.orm.panache.PanacheEntityBase
|
||||
import jakarta.persistence.*
|
||||
import scala.compiletime.uninitialized
|
||||
import scala.jdk.CollectionConverters.*
|
||||
|
||||
import java.time.Instant
|
||||
import java.util.UUID
|
||||
|
||||
@Entity
|
||||
@Table(name = "user_accounts")
|
||||
class UserAccount extends PanacheEntityBase:
|
||||
// scalafix:off DisableSyntax.var
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.UUID)
|
||||
var id: UUID = uninitialized
|
||||
|
||||
@Column(unique = true, nullable = false)
|
||||
var username: String = uninitialized
|
||||
|
||||
@Column(unique = true, nullable = false)
|
||||
var email: String = uninitialized
|
||||
|
||||
var passwordHash: String = uninitialized
|
||||
|
||||
var rating: Int = 1500
|
||||
|
||||
var createdAt: Instant = uninitialized
|
||||
|
||||
var banned: Boolean = false
|
||||
|
||||
@OneToMany(mappedBy = "owner", cascade = Array(CascadeType.ALL), orphanRemoval = true)
|
||||
var botAccounts: java.util.List[BotAccount] = uninitialized
|
||||
// scalafix:on
|
||||
|
||||
def getBotAccounts: List[BotAccount] = Option(botAccounts).map(_.asScala.toList).getOrElse(Nil)
|
||||
|
||||
@Entity
|
||||
@Table(name = "bot_accounts")
|
||||
class BotAccount extends PanacheEntityBase:
|
||||
// scalafix:off DisableSyntax.var
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.UUID)
|
||||
var id: UUID = uninitialized
|
||||
|
||||
@Column(nullable = false)
|
||||
var name: String = uninitialized
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "owner_id", nullable = false)
|
||||
var owner: UserAccount = uninitialized
|
||||
|
||||
@Column(unique = true, nullable = false, length = 256)
|
||||
var token: String = uninitialized
|
||||
|
||||
var rating: Int = 1500
|
||||
|
||||
var createdAt: Instant = uninitialized
|
||||
|
||||
var banned: Boolean = false
|
||||
// scalafix:on
|
||||
|
||||
@Entity
|
||||
@Table(name = "official_bot_accounts")
|
||||
class OfficialBotAccount extends PanacheEntityBase:
|
||||
// scalafix:off DisableSyntax.var
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.UUID)
|
||||
var id: UUID = uninitialized
|
||||
|
||||
@Column(nullable = false)
|
||||
var name: String = uninitialized
|
||||
|
||||
var rating: Int = 1500
|
||||
|
||||
var createdAt: Instant = uninitialized
|
||||
// scalafix:on
|
||||
@@ -0,0 +1,49 @@
|
||||
package de.nowchess.account.dto
|
||||
|
||||
case class RegisterRequest(username: String, email: String, password: String)
|
||||
|
||||
case class LoginRequest(username: String, password: String)
|
||||
|
||||
case class TokenResponse(token: String)
|
||||
|
||||
case class PlayerInfo(id: String, name: String, rating: Int)
|
||||
|
||||
case class PublicAccountDto(id: String, username: String, rating: Int, createdAt: String)
|
||||
|
||||
case class TimeControlDto(`type`: String, limit: Option[Int], increment: Option[Int])
|
||||
|
||||
case class ChallengeRequest(color: String, timeControl: TimeControlDto)
|
||||
|
||||
case class ChallengeDto(
|
||||
id: String,
|
||||
challenger: PlayerInfo,
|
||||
destUser: PlayerInfo,
|
||||
variant: String,
|
||||
color: String,
|
||||
timeControl: TimeControlDto,
|
||||
status: String,
|
||||
declineReason: Option[String],
|
||||
gameId: Option[String],
|
||||
createdAt: String,
|
||||
expiresAt: String,
|
||||
)
|
||||
|
||||
case class DeclineRequest(reason: Option[String])
|
||||
|
||||
case class ChallengeListDto(in: List[ChallengeDto], out: List[ChallengeDto])
|
||||
|
||||
case class ErrorDto(error: String)
|
||||
|
||||
case class CreateBotAccountRequest(name: String)
|
||||
|
||||
case class UpdateBotNameRequest(name: String)
|
||||
|
||||
case class BotAccountDto(id: String, name: String, rating: Int, createdAt: String)
|
||||
|
||||
case class BotAccountWithTokenDto(id: String, name: String, rating: Int, token: String, createdAt: String)
|
||||
|
||||
case class RotatedTokenDto(token: String)
|
||||
|
||||
case class OfficialBotAccountDto(id: String, name: String, rating: Int, createdAt: String)
|
||||
|
||||
case class OfficialChallengeResponse(gameId: String, botName: String, difficulty: Int)
|
||||
@@ -0,0 +1,23 @@
|
||||
package de.nowchess.account.error
|
||||
|
||||
enum AccountError:
|
||||
case UsernameTaken(username: String)
|
||||
case EmailAlreadyRegistered(email: String)
|
||||
case InvalidCredentials
|
||||
case UserNotFound
|
||||
case BotNotFound
|
||||
case BotLimitExceeded
|
||||
case NotAuthorized
|
||||
case UserBanned
|
||||
case BotBanned
|
||||
|
||||
def message: String = this match
|
||||
case UsernameTaken(u) => s"Username '$u' is already taken"
|
||||
case EmailAlreadyRegistered(e) => s"Email '$e' is already registered"
|
||||
case InvalidCredentials => "Invalid credentials"
|
||||
case UserNotFound => "User not found"
|
||||
case BotNotFound => "Bot account not found"
|
||||
case BotLimitExceeded => "Maximum of 5 bot accounts per user exceeded"
|
||||
case NotAuthorized => "Not authorized to perform this action"
|
||||
case UserBanned => "User account is banned"
|
||||
case BotBanned => "Bot account is banned"
|
||||
@@ -0,0 +1,25 @@
|
||||
package de.nowchess.account.error
|
||||
|
||||
enum ChallengeError:
|
||||
case UserNotFound(username: String)
|
||||
case ChallengerNotFound
|
||||
case CannotChallengeSelf
|
||||
case DuplicateChallenge
|
||||
case InvalidColor(color: String)
|
||||
case InvalidDeclineReason(reason: String)
|
||||
case ChallengeNotFound
|
||||
case ChallengeNotActive
|
||||
case NotAuthorized
|
||||
case GameCreationFailed
|
||||
|
||||
def message: String = this match
|
||||
case UserNotFound(u) => s"User '$u' not found"
|
||||
case ChallengerNotFound => "Challenger not found"
|
||||
case CannotChallengeSelf => "Cannot challenge yourself"
|
||||
case DuplicateChallenge => "Active challenge to this user already exists"
|
||||
case InvalidColor(c) => s"Unknown color: $c"
|
||||
case InvalidDeclineReason(r) => s"Unknown decline reason: $r"
|
||||
case ChallengeNotFound => "Challenge not found"
|
||||
case ChallengeNotActive => "Challenge is not active"
|
||||
case NotAuthorized => "Not authorized"
|
||||
case GameCreationFailed => "Failed to create game"
|
||||
@@ -0,0 +1,43 @@
|
||||
package de.nowchess.account.filter
|
||||
|
||||
import jakarta.enterprise.context.ApplicationScoped
|
||||
import jakarta.inject.Inject
|
||||
import jakarta.ws.rs.container.{ContainerRequestContext, ContainerRequestFilter}
|
||||
import jakarta.ws.rs.core.Response
|
||||
import jakarta.ws.rs.ext.Provider
|
||||
import org.eclipse.microprofile.jwt.JsonWebToken
|
||||
import scala.compiletime.uninitialized
|
||||
|
||||
@Provider
|
||||
@ApplicationScoped
|
||||
class AlreadyLoggedInFilter extends ContainerRequestFilter:
|
||||
|
||||
@Inject
|
||||
// scalafix:off DisableSyntax.var
|
||||
var jwt: JsonWebToken = uninitialized
|
||||
// scalafix:on
|
||||
|
||||
override def filter(context: ContainerRequestContext): Unit =
|
||||
val path = context.getUriInfo.getPath
|
||||
val method = context.getMethod
|
||||
|
||||
if isProtectedEndpoint(path, method) && isAuthenticated then
|
||||
context.abortWith(
|
||||
Response
|
||||
.status(Response.Status.BAD_REQUEST)
|
||||
.entity("""{"error":"Already logged in"}""")
|
||||
.build(),
|
||||
)
|
||||
|
||||
private def isAuthenticated: Boolean =
|
||||
// scalafix:off DisableSyntax.null
|
||||
try jwt.getName != null
|
||||
catch
|
||||
case _ => false
|
||||
// scalafix:on DisableSyntax.null
|
||||
|
||||
private def isProtectedEndpoint(path: String, method: String): Boolean =
|
||||
(path.contains("/api/account") || path.contains("/account")) &&
|
||||
((path.endsWith("/api/account") && method == "POST") ||
|
||||
(path.endsWith("/account") && method == "POST") ||
|
||||
(path.contains("/login") && method == "POST"))
|
||||
@@ -0,0 +1,98 @@
|
||||
package de.nowchess.account.repository
|
||||
|
||||
import de.nowchess.account.domain.{BotAccount, OfficialBotAccount, UserAccount}
|
||||
import jakarta.enterprise.context.ApplicationScoped
|
||||
import jakarta.inject.Inject
|
||||
import jakarta.persistence.EntityManager
|
||||
|
||||
import java.util.UUID
|
||||
import scala.jdk.CollectionConverters.*
|
||||
|
||||
@ApplicationScoped
|
||||
class UserAccountRepository:
|
||||
|
||||
@Inject
|
||||
// scalafix:off DisableSyntax.var
|
||||
var em: EntityManager = scala.compiletime.uninitialized
|
||||
// scalafix:on
|
||||
|
||||
def findByUsername(username: String): Option[UserAccount] =
|
||||
em.createQuery("FROM UserAccount WHERE username = :username", classOf[UserAccount])
|
||||
.setParameter("username", username)
|
||||
.getResultList
|
||||
.stream()
|
||||
.findFirst()
|
||||
.map(Option(_))
|
||||
.orElse(None)
|
||||
|
||||
def findById(id: UUID): Option[UserAccount] =
|
||||
Option(em.find(classOf[UserAccount], id))
|
||||
|
||||
def persist(account: UserAccount): UserAccount =
|
||||
em.persist(account)
|
||||
account
|
||||
|
||||
def findByEmail(email: String): Option[UserAccount] =
|
||||
em.createQuery("FROM UserAccount WHERE email = :email", classOf[UserAccount])
|
||||
.setParameter("email", email)
|
||||
.getResultList
|
||||
.asScala
|
||||
.headOption
|
||||
|
||||
def findAll(): List[UserAccount] =
|
||||
em.createQuery("FROM UserAccount", classOf[UserAccount]).getResultList.asScala.toList
|
||||
|
||||
@ApplicationScoped
|
||||
class BotAccountRepository:
|
||||
|
||||
@Inject
|
||||
// scalafix:off DisableSyntax.var
|
||||
var em: EntityManager = scala.compiletime.uninitialized
|
||||
// scalafix:on
|
||||
|
||||
def findById(id: UUID): Option[BotAccount] =
|
||||
Option(em.find(classOf[BotAccount], id))
|
||||
|
||||
def findByOwner(ownerId: UUID): List[BotAccount] =
|
||||
em.createQuery("FROM BotAccount WHERE owner.id = :ownerId", classOf[BotAccount])
|
||||
.setParameter("ownerId", ownerId)
|
||||
.getResultList
|
||||
.asScala
|
||||
.toList
|
||||
|
||||
def persist(bot: BotAccount): BotAccount =
|
||||
em.persist(bot)
|
||||
bot
|
||||
|
||||
def delete(botId: UUID): Unit =
|
||||
em.find(classOf[BotAccount], botId) match
|
||||
case bot: BotAccount => em.remove(bot)
|
||||
|
||||
def findByToken(token: String): Option[BotAccount] =
|
||||
em.createQuery("FROM BotAccount WHERE token = :token", classOf[BotAccount])
|
||||
.setParameter("token", token)
|
||||
.getResultList
|
||||
.asScala
|
||||
.headOption
|
||||
|
||||
@ApplicationScoped
|
||||
class OfficialBotAccountRepository:
|
||||
|
||||
@Inject
|
||||
// scalafix:off DisableSyntax.var
|
||||
var em: EntityManager = scala.compiletime.uninitialized
|
||||
// scalafix:on
|
||||
|
||||
def findById(id: UUID): Option[OfficialBotAccount] =
|
||||
Option(em.find(classOf[OfficialBotAccount], id))
|
||||
|
||||
def findAll(): List[OfficialBotAccount] =
|
||||
em.createQuery("FROM OfficialBotAccount", classOf[OfficialBotAccount]).getResultList.asScala.toList
|
||||
|
||||
def persist(bot: OfficialBotAccount): OfficialBotAccount =
|
||||
em.persist(bot)
|
||||
bot
|
||||
|
||||
def delete(botId: UUID): Unit =
|
||||
em.find(classOf[OfficialBotAccount], botId) match
|
||||
case bot: OfficialBotAccount => em.remove(bot)
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
package de.nowchess.account.repository
|
||||
|
||||
import de.nowchess.account.domain.{Challenge, ChallengeStatus}
|
||||
import jakarta.enterprise.context.ApplicationScoped
|
||||
import jakarta.inject.Inject
|
||||
import jakarta.persistence.EntityManager
|
||||
|
||||
import java.time.Instant
|
||||
import java.util.UUID
|
||||
import scala.jdk.CollectionConverters.*
|
||||
|
||||
@ApplicationScoped
|
||||
class ChallengeRepository:
|
||||
|
||||
@Inject
|
||||
// scalafix:off DisableSyntax.var
|
||||
var em: EntityManager = scala.compiletime.uninitialized
|
||||
// scalafix:on
|
||||
|
||||
def findActiveByChallengerId(challengerId: UUID): List[Challenge] =
|
||||
em.createQuery(
|
||||
"FROM Challenge WHERE challenger.id = :cid AND status = :status AND expiresAt > :now",
|
||||
classOf[Challenge],
|
||||
).setParameter("cid", challengerId)
|
||||
.setParameter("status", ChallengeStatus.Created)
|
||||
.setParameter("now", Instant.now())
|
||||
.getResultList
|
||||
.asScala
|
||||
.toList
|
||||
|
||||
def findActiveByDestUserId(destUserId: UUID): List[Challenge] =
|
||||
em.createQuery(
|
||||
"FROM Challenge WHERE destUser.id = :uid AND status = :status AND expiresAt > :now",
|
||||
classOf[Challenge],
|
||||
).setParameter("uid", destUserId)
|
||||
.setParameter("status", ChallengeStatus.Created)
|
||||
.setParameter("now", Instant.now())
|
||||
.getResultList
|
||||
.asScala
|
||||
.toList
|
||||
|
||||
def findDuplicateChallenge(challengerId: UUID, destUserId: UUID): Option[Challenge] =
|
||||
em.createQuery(
|
||||
"FROM Challenge WHERE challenger.id = :cid AND destUser.id = :uid AND status = :status AND expiresAt > :now",
|
||||
classOf[Challenge],
|
||||
).setParameter("cid", challengerId)
|
||||
.setParameter("uid", destUserId)
|
||||
.setParameter("status", ChallengeStatus.Created)
|
||||
.setParameter("now", Instant.now())
|
||||
.getResultList
|
||||
.asScala
|
||||
.headOption
|
||||
|
||||
def findById(id: UUID): Option[Challenge] =
|
||||
Option(em.find(classOf[Challenge], id))
|
||||
|
||||
def persist(challenge: Challenge): Challenge =
|
||||
em.persist(challenge)
|
||||
challenge
|
||||
|
||||
def merge(challenge: Challenge): Challenge =
|
||||
em.merge(challenge)
|
||||
@@ -0,0 +1,202 @@
|
||||
package de.nowchess.account.resource
|
||||
|
||||
import de.nowchess.account.domain.{BotAccount, OfficialBotAccount, UserAccount}
|
||||
import de.nowchess.account.dto.*
|
||||
import de.nowchess.account.error.AccountError
|
||||
import de.nowchess.account.service.AccountService
|
||||
import jakarta.annotation.security.RolesAllowed
|
||||
import jakarta.enterprise.context.ApplicationScoped
|
||||
import jakarta.inject.Inject
|
||||
import jakarta.ws.rs.*
|
||||
import jakarta.ws.rs.core.{MediaType, Response}
|
||||
import org.eclipse.microprofile.jwt.JsonWebToken
|
||||
import scala.compiletime.uninitialized
|
||||
|
||||
import java.util.UUID
|
||||
|
||||
@Path("/api/account")
|
||||
@ApplicationScoped
|
||||
@Consumes(Array(MediaType.APPLICATION_JSON))
|
||||
@Produces(Array(MediaType.APPLICATION_JSON))
|
||||
class AccountResource:
|
||||
|
||||
// scalafix:off DisableSyntax.var
|
||||
@Inject
|
||||
var accountService: AccountService = uninitialized
|
||||
|
||||
@Inject
|
||||
var jwt: JsonWebToken = uninitialized
|
||||
// scalafix:on
|
||||
|
||||
@POST
|
||||
def register(req: RegisterRequest): Response =
|
||||
accountService.register(req) match
|
||||
case Right(account) =>
|
||||
Response.ok(toPublicDto(account)).build()
|
||||
case Left(error) =>
|
||||
Response.status(Response.Status.CONFLICT).entity(ErrorDto(error.message)).build()
|
||||
|
||||
@POST
|
||||
@Path("/login")
|
||||
def login(req: LoginRequest): Response =
|
||||
accountService.login(req) match
|
||||
case Right(token) =>
|
||||
Response.ok(TokenResponse(token)).build()
|
||||
case Left(AccountError.UserBanned) =>
|
||||
Response.status(Response.Status.FORBIDDEN).entity(ErrorDto(AccountError.UserBanned.message)).build()
|
||||
case Left(error) =>
|
||||
Response.status(Response.Status.UNAUTHORIZED).entity(ErrorDto(error.message)).build()
|
||||
|
||||
@GET
|
||||
@Path("/me")
|
||||
@RolesAllowed(Array("**"))
|
||||
def me(): Response =
|
||||
val id = UUID.fromString(jwt.getSubject)
|
||||
accountService.findById(id) match
|
||||
case Some(account) => Response.ok(toPublicDto(account)).build()
|
||||
case None => Response.status(Response.Status.NOT_FOUND).build()
|
||||
|
||||
@GET
|
||||
@Path("/{username}")
|
||||
def publicProfile(@PathParam("username") username: String): Response =
|
||||
accountService.findByUsername(username) match
|
||||
case Some(account) => Response.ok(toPublicDto(account)).build()
|
||||
case None => Response.status(Response.Status.NOT_FOUND).build()
|
||||
|
||||
@POST
|
||||
@Path("/{userId}/ban")
|
||||
@RolesAllowed(Array("Admin"))
|
||||
def banUser(@PathParam("userId") userId: String): Response =
|
||||
accountService.banUser(UUID.fromString(userId)) match
|
||||
case Right(user) => Response.ok(toPublicDto(user)).build()
|
||||
case Left(error) =>
|
||||
Response.status(Response.Status.NOT_FOUND).entity(ErrorDto(error.message)).build()
|
||||
|
||||
@POST
|
||||
@Path("/{userId}/unban")
|
||||
@RolesAllowed(Array("Admin"))
|
||||
def unbanUser(@PathParam("userId") userId: String): Response =
|
||||
accountService.unbanUser(UUID.fromString(userId)) match
|
||||
case Right(user) => Response.ok(toPublicDto(user)).build()
|
||||
case Left(error) =>
|
||||
Response.status(Response.Status.NOT_FOUND).entity(ErrorDto(error.message)).build()
|
||||
|
||||
@POST
|
||||
@Path("/bots")
|
||||
@RolesAllowed(Array("**"))
|
||||
def createBotAccount(req: CreateBotAccountRequest): Response =
|
||||
val ownerId = UUID.fromString(jwt.getSubject)
|
||||
accountService.createBotAccount(ownerId, req.name) match
|
||||
case Right(bot) =>
|
||||
Response.status(Response.Status.CREATED).entity(toBotDtoWithToken(bot)).build()
|
||||
case Left(error) =>
|
||||
val status = error match
|
||||
case AccountError.BotLimitExceeded => Response.Status.BAD_REQUEST
|
||||
case _ => Response.Status.INTERNAL_SERVER_ERROR
|
||||
Response.status(status).entity(ErrorDto(error.message)).build()
|
||||
|
||||
@GET
|
||||
@Path("/bots")
|
||||
@RolesAllowed(Array("**"))
|
||||
def listBotAccounts(): Response =
|
||||
val ownerId = UUID.fromString(jwt.getSubject)
|
||||
val bots = accountService.getBotAccounts(ownerId)
|
||||
Response.ok(bots.map(toBotDto)).build()
|
||||
|
||||
@PUT
|
||||
@Path("/bots/{botId}")
|
||||
@RolesAllowed(Array("**"))
|
||||
def updateBotName(@PathParam("botId") botId: String, req: UpdateBotNameRequest): Response =
|
||||
val ownerId = UUID.fromString(jwt.getSubject)
|
||||
accountService.updateBotName(UUID.fromString(botId), ownerId, req.name) match
|
||||
case Right(bot) => Response.ok(toBotDto(bot)).build()
|
||||
case Left(AccountError.NotAuthorized) =>
|
||||
Response.status(Response.Status.FORBIDDEN).entity(ErrorDto(AccountError.NotAuthorized.message)).build()
|
||||
case Left(error) =>
|
||||
Response.status(Response.Status.NOT_FOUND).entity(ErrorDto(error.message)).build()
|
||||
|
||||
@POST
|
||||
@Path("/bots/{botId}/rotate-token")
|
||||
@RolesAllowed(Array("**"))
|
||||
def rotateBotToken(@PathParam("botId") botId: String): Response =
|
||||
val ownerId = UUID.fromString(jwt.getSubject)
|
||||
accountService.rotateBotToken(UUID.fromString(botId), ownerId) match
|
||||
case Right(bot) => Response.ok(RotatedTokenDto(bot.token)).build()
|
||||
case Left(AccountError.NotAuthorized) =>
|
||||
Response.status(Response.Status.FORBIDDEN).entity(ErrorDto(AccountError.NotAuthorized.message)).build()
|
||||
case Left(error) =>
|
||||
Response.status(Response.Status.NOT_FOUND).entity(ErrorDto(error.message)).build()
|
||||
|
||||
@DELETE
|
||||
@Path("/bots/{botId}")
|
||||
@RolesAllowed(Array("**"))
|
||||
def deleteBotAccount(@PathParam("botId") botId: String): Response =
|
||||
val ownerId = UUID.fromString(jwt.getSubject)
|
||||
val botUuid = UUID.fromString(botId)
|
||||
accountService.getBotAccountWithOwnerCheck(botUuid, ownerId) match
|
||||
case None => Response.status(Response.Status.NOT_FOUND).entity(ErrorDto(AccountError.BotNotFound.message)).build()
|
||||
case Some(None) =>
|
||||
Response.status(Response.Status.FORBIDDEN).entity(ErrorDto(AccountError.NotAuthorized.message)).build()
|
||||
case Some(Some(_)) =>
|
||||
accountService.deleteBotAccount(botUuid) match
|
||||
case Right(_) => Response.noContent().build()
|
||||
case Left(error) =>
|
||||
Response.status(Response.Status.NOT_FOUND).entity(ErrorDto(error.message)).build()
|
||||
|
||||
private def toPublicDto(account: UserAccount): PublicAccountDto =
|
||||
PublicAccountDto(
|
||||
id = account.id.toString,
|
||||
username = account.username,
|
||||
rating = account.rating,
|
||||
createdAt = account.createdAt.toString,
|
||||
)
|
||||
|
||||
private def toBotDto(bot: BotAccount): BotAccountDto =
|
||||
BotAccountDto(
|
||||
id = bot.id.toString,
|
||||
name = bot.name,
|
||||
rating = bot.rating,
|
||||
createdAt = bot.createdAt.toString,
|
||||
)
|
||||
|
||||
private def toBotDtoWithToken(bot: BotAccount): BotAccountWithTokenDto =
|
||||
BotAccountWithTokenDto(
|
||||
id = bot.id.toString,
|
||||
name = bot.name,
|
||||
rating = bot.rating,
|
||||
token = bot.token,
|
||||
createdAt = bot.createdAt.toString,
|
||||
)
|
||||
|
||||
@GET
|
||||
@Path("/official-bots")
|
||||
def getOfficialBots: Response =
|
||||
val bots = accountService.getOfficialBotAccounts()
|
||||
Response.ok(bots.map(toOfficialBotDto)).build()
|
||||
|
||||
@POST
|
||||
@Path("/official-bots")
|
||||
@RolesAllowed(Array("Admin"))
|
||||
def createOfficialBot(req: CreateBotAccountRequest): Response =
|
||||
accountService.createOfficialBotAccount(req.name) match
|
||||
case Right(bot) =>
|
||||
Response.status(Response.Status.CREATED).entity(toOfficialBotDto(bot)).build()
|
||||
case Left(error) =>
|
||||
Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ErrorDto(error.message)).build()
|
||||
|
||||
@DELETE
|
||||
@Path("/official-bots/{botId}")
|
||||
@RolesAllowed(Array("Admin"))
|
||||
def deleteOfficialBot(@PathParam("botId") botId: String): Response =
|
||||
accountService.deleteOfficialBotAccount(UUID.fromString(botId)) match
|
||||
case Right(_) => Response.noContent().build()
|
||||
case Left(error) =>
|
||||
Response.status(Response.Status.NOT_FOUND).entity(ErrorDto(error.message)).build()
|
||||
|
||||
private def toOfficialBotDto(bot: OfficialBotAccount): OfficialBotAccountDto =
|
||||
OfficialBotAccountDto(
|
||||
id = bot.id.toString,
|
||||
name = bot.name,
|
||||
rating = bot.rating,
|
||||
createdAt = bot.createdAt.toString,
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user