feat(game): add GameWritebackEventDto and update related services for game state management
Build & Test (NowChessSystems) TeamCity build failed
Build & Test (NowChessSystems) TeamCity build failed
This commit is contained in:
@@ -31,8 +31,15 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
module:
|
module:
|
||||||
|
- account
|
||||||
|
- bot-platform
|
||||||
|
- coordinator
|
||||||
- core
|
- core
|
||||||
- io
|
- io
|
||||||
|
- official-bots
|
||||||
|
- rule
|
||||||
|
- store
|
||||||
|
- ws
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|||||||
Generated
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
<option name="linkedExternalProjectsSettings">
|
<option name="linkedExternalProjectsSettings">
|
||||||
<GradleProjectSettings>
|
<GradleProjectSettings>
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
<option name="gradleJvm" value="corretto-21" />
|
<option name="gradleJvm" value="ms-21" />
|
||||||
<option name="modules">
|
<option name="modules">
|
||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
|
|||||||
Generated
+2
-1
@@ -1,9 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="FrameworkDetectionExcludesConfiguration">
|
<component name="FrameworkDetectionExcludesConfiguration">
|
||||||
<file type="web" url="file://$PROJECT_DIR$" />
|
<file type="web" url="file://$PROJECT_DIR$" />
|
||||||
</component>
|
</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" />
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
+1
-1
@@ -12,7 +12,7 @@ version = "1.0-SNAPSHOT"
|
|||||||
// converted to scoverage regexes via globToScoverageRegex for instrumentation-time exclusion.
|
// converted to scoverage regexes via globToScoverageRegex for instrumentation-time exclusion.
|
||||||
val coverageExclusions = listOf(
|
val coverageExclusions = listOf(
|
||||||
// UI renders JavaFX components; headless test environments cannot exercise rendering paths
|
// UI renders JavaFX components; headless test environments cannot exercise rendering paths
|
||||||
"modules/ui/**",
|
"modules/api/**",
|
||||||
// FastParse macro-generated combinators produce synthetic branches that scoverage marks as uncovered
|
// FastParse macro-generated combinators produce synthetic branches that scoverage marks as uncovered
|
||||||
"modules/io/src/main/scala/de/nowchess/io/fen/FenParserFastParse*",
|
"modules/io/src/main/scala/de/nowchess/io/fen/FenParserFastParse*",
|
||||||
// NNUE inference pipeline — coverage requires a trained model file not present in CI
|
// NNUE inference pipeline — coverage requires a trained model file not present in CI
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ nowchess:
|
|||||||
port: 6379
|
port: 6379
|
||||||
prefix: nowchess
|
prefix: nowchess
|
||||||
internal:
|
internal:
|
||||||
secret: ${INTERNAL_SECRET}
|
secret: 123abc
|
||||||
|
|
||||||
"%deployed":
|
"%deployed":
|
||||||
quarkus:
|
quarkus:
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package de.nowchess.chess.redis
|
package de.nowchess.api.dto
|
||||||
|
|
||||||
case class GameWritebackEventDto(
|
case class GameWritebackEventDto(
|
||||||
gameId: String,
|
gameId: String,
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
package de.nowchess.api.grpc
|
||||||
|
|
||||||
|
import de.nowchess.api.board.{CastlingRights as DomainCastlingRights, *}
|
||||||
|
import de.nowchess.api.game.{DrawReason, GameContext, GameResult, WinReason}
|
||||||
|
import de.nowchess.api.move.{Move as DomainMove, MoveType, PromotionPiece}
|
||||||
|
|
||||||
|
import scala.jdk.CollectionConverters.*
|
||||||
|
|
||||||
|
trait ProtoMapperBase[PC, PPT, PMK, PM, PSP, PBoard, PCR, PRK, PGC]:
|
||||||
|
def toProtoColor(c: Color): PC
|
||||||
|
def fromProtoColor(c: PC): Color
|
||||||
|
def toProtoPieceType(pt: PieceType): PPT
|
||||||
|
def fromProtoPieceType(pt: PPT): PieceType
|
||||||
|
def toProtoMoveKind(mt: MoveType): PMK
|
||||||
|
def fromProtoMoveKind(k: PMK): MoveType
|
||||||
|
|
||||||
|
def toProtoMove(m: DomainMove): PM
|
||||||
|
def fromProtoMove(m: PM): Option[DomainMove]
|
||||||
|
|
||||||
|
def toProtoSquarePiece(sq: Square, piece: Piece): PSP
|
||||||
|
def fromProtoSquarePiece(sp: PSP): Option[(Square, Piece)]
|
||||||
|
|
||||||
|
def toProtoBoard(board: Board): java.util.List[PSP]
|
||||||
|
def fromProtoBoard(pieces: java.util.List[PSP]): Board
|
||||||
|
|
||||||
|
def toProtoResultKind(r: Option[GameResult]): PRK
|
||||||
|
def fromProtoResultKind(k: PRK): Option[GameResult]
|
||||||
|
|
||||||
|
def toProtoCastlingRights(cr: DomainCastlingRights): PCR
|
||||||
|
def fromProtoCastlingRights(pcr: PCR): DomainCastlingRights
|
||||||
|
|
||||||
|
def toProtoGameContext(ctx: GameContext): PGC
|
||||||
|
def fromProtoGameContext(p: PGC): GameContext
|
||||||
|
|
||||||
|
object ProtoMapperBase:
|
||||||
|
def colorConversions[PC](white: PC, black: PC): (Color => PC, PC => Color) =
|
||||||
|
(
|
||||||
|
(c: Color) =>
|
||||||
|
c match
|
||||||
|
case Color.White => white
|
||||||
|
case Color.Black => black,
|
||||||
|
(pc: PC) =>
|
||||||
|
if pc == white then Color.White
|
||||||
|
else Color.Black,
|
||||||
|
)
|
||||||
|
|
||||||
|
def pieceTypeConversions[PPT](
|
||||||
|
pawn: PPT,
|
||||||
|
knight: PPT,
|
||||||
|
bishop: PPT,
|
||||||
|
rook: PPT,
|
||||||
|
queen: PPT,
|
||||||
|
king: PPT,
|
||||||
|
): (PieceType => PPT, PPT => PieceType) =
|
||||||
|
(
|
||||||
|
(pt: PieceType) =>
|
||||||
|
pt match
|
||||||
|
case PieceType.Pawn => pawn
|
||||||
|
case PieceType.Knight => knight
|
||||||
|
case PieceType.Bishop => bishop
|
||||||
|
case PieceType.Rook => rook
|
||||||
|
case PieceType.Queen => queen
|
||||||
|
case PieceType.King => king,
|
||||||
|
(ppt: PPT) =>
|
||||||
|
if ppt == pawn then PieceType.Pawn
|
||||||
|
else if ppt == knight then PieceType.Knight
|
||||||
|
else if ppt == bishop then PieceType.Bishop
|
||||||
|
else if ppt == rook then PieceType.Rook
|
||||||
|
else if ppt == queen then PieceType.Queen
|
||||||
|
else PieceType.King,
|
||||||
|
)
|
||||||
|
|
||||||
|
def moveKindConversions[PMK](
|
||||||
|
quiet: PMK,
|
||||||
|
capture: PMK,
|
||||||
|
castleKingside: PMK,
|
||||||
|
castleQueenside: PMK,
|
||||||
|
enPassant: PMK,
|
||||||
|
promoQueen: PMK,
|
||||||
|
promoRook: PMK,
|
||||||
|
promoBishop: PMK,
|
||||||
|
promoKnight: PMK,
|
||||||
|
): (MoveType => PMK, PMK => MoveType) =
|
||||||
|
(
|
||||||
|
(mt: MoveType) =>
|
||||||
|
mt match
|
||||||
|
case MoveType.Normal(false) => quiet
|
||||||
|
case MoveType.Normal(true) => capture
|
||||||
|
case MoveType.CastleKingside => castleKingside
|
||||||
|
case MoveType.CastleQueenside => castleQueenside
|
||||||
|
case MoveType.EnPassant => enPassant
|
||||||
|
case MoveType.Promotion(PromotionPiece.Queen) => promoQueen
|
||||||
|
case MoveType.Promotion(PromotionPiece.Rook) => promoRook
|
||||||
|
case MoveType.Promotion(PromotionPiece.Bishop) => promoBishop
|
||||||
|
case MoveType.Promotion(PromotionPiece.Knight) => promoKnight,
|
||||||
|
(pmk: PMK) =>
|
||||||
|
if pmk == quiet then MoveType.Normal(false)
|
||||||
|
else if pmk == capture then MoveType.Normal(true)
|
||||||
|
else if pmk == castleKingside then MoveType.CastleKingside
|
||||||
|
else if pmk == castleQueenside then MoveType.CastleQueenside
|
||||||
|
else if pmk == enPassant then MoveType.EnPassant
|
||||||
|
else if pmk == promoQueen then MoveType.Promotion(PromotionPiece.Queen)
|
||||||
|
else if pmk == promoRook then MoveType.Promotion(PromotionPiece.Rook)
|
||||||
|
else if pmk == promoBishop then MoveType.Promotion(PromotionPiece.Bishop)
|
||||||
|
else if pmk == promoKnight then MoveType.Promotion(PromotionPiece.Knight)
|
||||||
|
else MoveType.Normal(false),
|
||||||
|
)
|
||||||
@@ -26,7 +26,7 @@ nowchess:
|
|||||||
prefix: nowchess
|
prefix: nowchess
|
||||||
|
|
||||||
internal:
|
internal:
|
||||||
secret: ${INTERNAL_SECRET}
|
secret: 123abc
|
||||||
|
|
||||||
coordinator:
|
coordinator:
|
||||||
enabled: ${NOWCHESS_COORDINATOR_ENABLED:false}
|
enabled: ${NOWCHESS_COORDINATOR_ENABLED:false}
|
||||||
|
|||||||
@@ -3,61 +3,42 @@ package de.nowchess.chess.grpc
|
|||||||
import de.nowchess.api.board.*
|
import de.nowchess.api.board.*
|
||||||
import de.nowchess.api.board.CastlingRights as DomainCastlingRights
|
import de.nowchess.api.board.CastlingRights as DomainCastlingRights
|
||||||
import de.nowchess.api.game.{DrawReason, GameContext, GameResult, WinReason}
|
import de.nowchess.api.game.{DrawReason, GameContext, GameResult, WinReason}
|
||||||
import de.nowchess.api.move.{Move as DomainMove, MoveType, PromotionPiece}
|
import de.nowchess.api.grpc.ProtoMapperBase
|
||||||
|
import de.nowchess.api.move.{Move as DomainMove, MoveType}
|
||||||
import de.nowchess.core.proto.*
|
import de.nowchess.core.proto.*
|
||||||
|
|
||||||
import scala.jdk.CollectionConverters.*
|
import scala.jdk.CollectionConverters.*
|
||||||
|
|
||||||
object CoreProtoMapper:
|
object CoreProtoMapper extends ProtoMapperBase[ProtoColor, ProtoPieceType, ProtoMoveKind, ProtoMove, ProtoSquarePiece, java.util.List[ProtoSquarePiece], ProtoCastlingRights, ProtoGameResultKind, ProtoGameContext]:
|
||||||
|
private val (colorTo, colorFrom) = ProtoMapperBase.colorConversions(ProtoColor.WHITE, ProtoColor.BLACK)
|
||||||
|
private val (pieceTypeTo, pieceTypeFrom) = ProtoMapperBase.pieceTypeConversions(
|
||||||
|
ProtoPieceType.PAWN,
|
||||||
|
ProtoPieceType.KNIGHT,
|
||||||
|
ProtoPieceType.BISHOP,
|
||||||
|
ProtoPieceType.ROOK,
|
||||||
|
ProtoPieceType.QUEEN,
|
||||||
|
ProtoPieceType.KING,
|
||||||
|
)
|
||||||
|
private val (moveKindTo, moveKindFrom) = ProtoMapperBase.moveKindConversions(
|
||||||
|
ProtoMoveKind.QUIET,
|
||||||
|
ProtoMoveKind.CAPTURE,
|
||||||
|
ProtoMoveKind.CASTLE_KINGSIDE,
|
||||||
|
ProtoMoveKind.CASTLE_QUEENSIDE,
|
||||||
|
ProtoMoveKind.EN_PASSANT,
|
||||||
|
ProtoMoveKind.PROMO_QUEEN,
|
||||||
|
ProtoMoveKind.PROMO_ROOK,
|
||||||
|
ProtoMoveKind.PROMO_BISHOP,
|
||||||
|
ProtoMoveKind.PROMO_KNIGHT,
|
||||||
|
)
|
||||||
|
|
||||||
def toProtoColor(c: Color): ProtoColor = c match
|
override def toProtoColor(c: Color): ProtoColor = colorTo(c)
|
||||||
case Color.White => ProtoColor.WHITE
|
override def fromProtoColor(c: ProtoColor): Color = colorFrom(c)
|
||||||
case Color.Black => ProtoColor.BLACK
|
override def toProtoPieceType(pt: PieceType): ProtoPieceType = pieceTypeTo(pt)
|
||||||
|
override def fromProtoPieceType(pt: ProtoPieceType): PieceType = pieceTypeFrom(pt)
|
||||||
|
override def toProtoMoveKind(mt: MoveType): ProtoMoveKind = moveKindTo(mt)
|
||||||
|
override def fromProtoMoveKind(k: ProtoMoveKind): MoveType = moveKindFrom(k)
|
||||||
|
|
||||||
def fromProtoColor(c: ProtoColor): Color = c match
|
override def toProtoMove(m: DomainMove): ProtoMove =
|
||||||
case ProtoColor.WHITE => Color.White
|
|
||||||
case _ => Color.Black
|
|
||||||
|
|
||||||
def toProtoPieceType(pt: PieceType): ProtoPieceType = pt match
|
|
||||||
case PieceType.Pawn => ProtoPieceType.PAWN
|
|
||||||
case PieceType.Knight => ProtoPieceType.KNIGHT
|
|
||||||
case PieceType.Bishop => ProtoPieceType.BISHOP
|
|
||||||
case PieceType.Rook => ProtoPieceType.ROOK
|
|
||||||
case PieceType.Queen => ProtoPieceType.QUEEN
|
|
||||||
case PieceType.King => ProtoPieceType.KING
|
|
||||||
|
|
||||||
def fromProtoPieceType(pt: ProtoPieceType): PieceType = pt match
|
|
||||||
case ProtoPieceType.PAWN => PieceType.Pawn
|
|
||||||
case ProtoPieceType.KNIGHT => PieceType.Knight
|
|
||||||
case ProtoPieceType.BISHOP => PieceType.Bishop
|
|
||||||
case ProtoPieceType.ROOK => PieceType.Rook
|
|
||||||
case ProtoPieceType.QUEEN => PieceType.Queen
|
|
||||||
case _ => PieceType.King
|
|
||||||
|
|
||||||
def toProtoMoveKind(mt: MoveType): ProtoMoveKind = mt match
|
|
||||||
case MoveType.Normal(false) => ProtoMoveKind.QUIET
|
|
||||||
case MoveType.Normal(true) => ProtoMoveKind.CAPTURE
|
|
||||||
case MoveType.CastleKingside => ProtoMoveKind.CASTLE_KINGSIDE
|
|
||||||
case MoveType.CastleQueenside => ProtoMoveKind.CASTLE_QUEENSIDE
|
|
||||||
case MoveType.EnPassant => ProtoMoveKind.EN_PASSANT
|
|
||||||
case MoveType.Promotion(PromotionPiece.Queen) => ProtoMoveKind.PROMO_QUEEN
|
|
||||||
case MoveType.Promotion(PromotionPiece.Rook) => ProtoMoveKind.PROMO_ROOK
|
|
||||||
case MoveType.Promotion(PromotionPiece.Bishop) => ProtoMoveKind.PROMO_BISHOP
|
|
||||||
case MoveType.Promotion(PromotionPiece.Knight) => ProtoMoveKind.PROMO_KNIGHT
|
|
||||||
|
|
||||||
def fromProtoMoveKind(k: ProtoMoveKind): MoveType = k match
|
|
||||||
case ProtoMoveKind.QUIET => MoveType.Normal(false)
|
|
||||||
case ProtoMoveKind.CAPTURE => MoveType.Normal(true)
|
|
||||||
case ProtoMoveKind.CASTLE_KINGSIDE => MoveType.CastleKingside
|
|
||||||
case ProtoMoveKind.CASTLE_QUEENSIDE => MoveType.CastleQueenside
|
|
||||||
case ProtoMoveKind.EN_PASSANT => MoveType.EnPassant
|
|
||||||
case ProtoMoveKind.PROMO_QUEEN => MoveType.Promotion(PromotionPiece.Queen)
|
|
||||||
case ProtoMoveKind.PROMO_ROOK => MoveType.Promotion(PromotionPiece.Rook)
|
|
||||||
case ProtoMoveKind.PROMO_BISHOP => MoveType.Promotion(PromotionPiece.Bishop)
|
|
||||||
case ProtoMoveKind.PROMO_KNIGHT => MoveType.Promotion(PromotionPiece.Knight)
|
|
||||||
case _ => MoveType.Normal(false)
|
|
||||||
|
|
||||||
def toProtoMove(m: DomainMove): ProtoMove =
|
|
||||||
ProtoMove
|
ProtoMove
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.setFrom(m.from.toString)
|
.setFrom(m.from.toString)
|
||||||
@@ -65,42 +46,44 @@ object CoreProtoMapper:
|
|||||||
.setMoveKind(toProtoMoveKind(m.moveType))
|
.setMoveKind(toProtoMoveKind(m.moveType))
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
def fromProtoMove(m: ProtoMove): Option[DomainMove] =
|
override def fromProtoMove(m: ProtoMove): Option[DomainMove] =
|
||||||
for
|
for
|
||||||
from <- Square.fromAlgebraic(m.getFrom)
|
from <- Square.fromAlgebraic(m.getFrom)
|
||||||
to <- Square.fromAlgebraic(m.getTo)
|
to <- Square.fromAlgebraic(m.getTo)
|
||||||
yield DomainMove(from, to, fromProtoMoveKind(m.getMoveKind))
|
yield DomainMove(from, to, fromProtoMoveKind(m.getMoveKind))
|
||||||
|
|
||||||
def toProtoBoard(board: Board): java.util.List[ProtoSquarePiece] =
|
override def toProtoSquarePiece(sq: Square, piece: Piece): ProtoSquarePiece =
|
||||||
board.pieces
|
ProtoSquarePiece
|
||||||
.map { (sq, piece) =>
|
.newBuilder()
|
||||||
ProtoSquarePiece
|
.setSquare(sq.toString)
|
||||||
|
.setPiece(
|
||||||
|
ProtoPiece
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.setSquare(sq.toString)
|
.setColor(toProtoColor(piece.color))
|
||||||
.setPiece(
|
.setPieceType(toProtoPieceType(piece.pieceType))
|
||||||
ProtoPiece
|
.build(),
|
||||||
.newBuilder()
|
)
|
||||||
.setColor(toProtoColor(piece.color))
|
.build()
|
||||||
.setPieceType(toProtoPieceType(piece.pieceType))
|
|
||||||
.build(),
|
override def fromProtoSquarePiece(sp: ProtoSquarePiece): Option[(Square, Piece)] =
|
||||||
)
|
Square
|
||||||
.build()
|
.fromAlgebraic(sp.getSquare)
|
||||||
}
|
.map(_ -> Piece(fromProtoColor(sp.getPiece.getColor), fromProtoPieceType(sp.getPiece.getPieceType)))
|
||||||
|
|
||||||
|
override def toProtoBoard(board: Board): java.util.List[ProtoSquarePiece] =
|
||||||
|
board.pieces
|
||||||
|
.map { (sq, piece) => toProtoSquarePiece(sq, piece) }
|
||||||
.toSeq
|
.toSeq
|
||||||
.asJava
|
.asJava
|
||||||
|
|
||||||
def fromProtoBoard(pieces: java.util.List[ProtoSquarePiece]): Board =
|
override def fromProtoBoard(pieces: java.util.List[ProtoSquarePiece]): Board =
|
||||||
Board(
|
Board(
|
||||||
pieces.asScala
|
pieces.asScala
|
||||||
.flatMap(sp =>
|
.flatMap(fromProtoSquarePiece)
|
||||||
Square
|
|
||||||
.fromAlgebraic(sp.getSquare)
|
|
||||||
.map(_ -> Piece(fromProtoColor(sp.getPiece.getColor), fromProtoPieceType(sp.getPiece.getPieceType))),
|
|
||||||
)
|
|
||||||
.toMap,
|
.toMap,
|
||||||
)
|
)
|
||||||
|
|
||||||
def toProtoResultKind(r: Option[GameResult]): ProtoGameResultKind = r match
|
override def toProtoResultKind(r: Option[GameResult]): ProtoGameResultKind = r match
|
||||||
case None => ProtoGameResultKind.ONGOING
|
case None => ProtoGameResultKind.ONGOING
|
||||||
case Some(GameResult.Win(Color.White, WinReason.Checkmate)) => ProtoGameResultKind.WIN_CHECKMATE_W
|
case Some(GameResult.Win(Color.White, WinReason.Checkmate)) => ProtoGameResultKind.WIN_CHECKMATE_W
|
||||||
case Some(GameResult.Win(Color.Black, WinReason.Checkmate)) => ProtoGameResultKind.WIN_CHECKMATE_B
|
case Some(GameResult.Win(Color.Black, WinReason.Checkmate)) => ProtoGameResultKind.WIN_CHECKMATE_B
|
||||||
@@ -114,7 +97,7 @@ object CoreProtoMapper:
|
|||||||
case Some(GameResult.Draw(DrawReason.ThreefoldRepetition)) => ProtoGameResultKind.DRAW_THREEFOLD
|
case Some(GameResult.Draw(DrawReason.ThreefoldRepetition)) => ProtoGameResultKind.DRAW_THREEFOLD
|
||||||
case Some(GameResult.Draw(DrawReason.Agreement)) => ProtoGameResultKind.DRAW_AGREEMENT
|
case Some(GameResult.Draw(DrawReason.Agreement)) => ProtoGameResultKind.DRAW_AGREEMENT
|
||||||
|
|
||||||
def fromProtoResultKind(k: ProtoGameResultKind): Option[GameResult] = k match
|
override def fromProtoResultKind(k: ProtoGameResultKind): Option[GameResult] = k match
|
||||||
case ProtoGameResultKind.ONGOING => None
|
case ProtoGameResultKind.ONGOING => None
|
||||||
case ProtoGameResultKind.WIN_CHECKMATE_W => Some(GameResult.Win(Color.White, WinReason.Checkmate))
|
case ProtoGameResultKind.WIN_CHECKMATE_W => Some(GameResult.Win(Color.White, WinReason.Checkmate))
|
||||||
case ProtoGameResultKind.WIN_CHECKMATE_B => Some(GameResult.Win(Color.Black, WinReason.Checkmate))
|
case ProtoGameResultKind.WIN_CHECKMATE_B => Some(GameResult.Win(Color.Black, WinReason.Checkmate))
|
||||||
@@ -129,20 +112,24 @@ object CoreProtoMapper:
|
|||||||
case ProtoGameResultKind.DRAW_AGREEMENT => Some(GameResult.Draw(DrawReason.Agreement))
|
case ProtoGameResultKind.DRAW_AGREEMENT => Some(GameResult.Draw(DrawReason.Agreement))
|
||||||
case _ => None
|
case _ => None
|
||||||
|
|
||||||
def toProtoGameContext(ctx: GameContext): ProtoGameContext =
|
override def toProtoCastlingRights(cr: DomainCastlingRights): ProtoCastlingRights =
|
||||||
|
ProtoCastlingRights
|
||||||
|
.newBuilder()
|
||||||
|
.setWhiteKingSide(cr.whiteKingSide)
|
||||||
|
.setWhiteQueenSide(cr.whiteQueenSide)
|
||||||
|
.setBlackKingSide(cr.blackKingSide)
|
||||||
|
.setBlackQueenSide(cr.blackQueenSide)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
override def fromProtoCastlingRights(pcr: ProtoCastlingRights): DomainCastlingRights =
|
||||||
|
DomainCastlingRights(pcr.getWhiteKingSide, pcr.getWhiteQueenSide, pcr.getBlackKingSide, pcr.getBlackQueenSide)
|
||||||
|
|
||||||
|
override def toProtoGameContext(ctx: GameContext): ProtoGameContext =
|
||||||
ProtoGameContext
|
ProtoGameContext
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.addAllBoard(toProtoBoard(ctx.board))
|
.addAllBoard(toProtoBoard(ctx.board))
|
||||||
.setTurn(toProtoColor(ctx.turn))
|
.setTurn(toProtoColor(ctx.turn))
|
||||||
.setCastlingRights(
|
.setCastlingRights(toProtoCastlingRights(ctx.castlingRights))
|
||||||
ProtoCastlingRights
|
|
||||||
.newBuilder()
|
|
||||||
.setWhiteKingSide(ctx.castlingRights.whiteKingSide)
|
|
||||||
.setWhiteQueenSide(ctx.castlingRights.whiteQueenSide)
|
|
||||||
.setBlackKingSide(ctx.castlingRights.blackKingSide)
|
|
||||||
.setBlackQueenSide(ctx.castlingRights.blackQueenSide)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.setEnPassantSquare(ctx.enPassantSquare.map(_.toString).getOrElse(""))
|
.setEnPassantSquare(ctx.enPassantSquare.map(_.toString).getOrElse(""))
|
||||||
.setHalfMoveClock(ctx.halfMoveClock)
|
.setHalfMoveClock(ctx.halfMoveClock)
|
||||||
.addAllMoves(ctx.moves.map(toProtoMove).asJava)
|
.addAllMoves(ctx.moves.map(toProtoMove).asJava)
|
||||||
@@ -150,13 +137,11 @@ object CoreProtoMapper:
|
|||||||
.addAllInitialBoard(toProtoBoard(ctx.initialBoard))
|
.addAllInitialBoard(toProtoBoard(ctx.initialBoard))
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
def fromProtoGameContext(p: ProtoGameContext): GameContext =
|
override def fromProtoGameContext(p: ProtoGameContext): GameContext =
|
||||||
val cr = p.getCastlingRights
|
|
||||||
GameContext(
|
GameContext(
|
||||||
board = fromProtoBoard(p.getBoardList),
|
board = fromProtoBoard(p.getBoardList),
|
||||||
turn = fromProtoColor(p.getTurn),
|
turn = fromProtoColor(p.getTurn),
|
||||||
castlingRights =
|
castlingRights = fromProtoCastlingRights(p.getCastlingRights),
|
||||||
DomainCastlingRights(cr.getWhiteKingSide, cr.getWhiteQueenSide, cr.getBlackKingSide, cr.getBlackQueenSide),
|
|
||||||
enPassantSquare = Option(p.getEnPassantSquare).filter(_.nonEmpty).flatMap(Square.fromAlgebraic),
|
enPassantSquare = Option(p.getEnPassantSquare).filter(_.nonEmpty).flatMap(Square.fromAlgebraic),
|
||||||
halfMoveClock = p.getHalfMoveClock,
|
halfMoveClock = p.getHalfMoveClock,
|
||||||
moves = p.getMovesList.asScala.flatMap(fromProtoMove).toList,
|
moves = p.getMovesList.asScala.flatMap(fromProtoMove).toList,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package de.nowchess.chess.redis
|
package de.nowchess.chess.redis
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import de.nowchess.api.dto.GameStateEventDto
|
import de.nowchess.api.dto.{GameStateEventDto, GameWritebackEventDto}
|
||||||
import de.nowchess.api.game.{CorrespondenceClockState, LiveClockState}
|
import de.nowchess.api.game.{CorrespondenceClockState, LiveClockState}
|
||||||
import de.nowchess.chess.grpc.IoGrpcClientWrapper
|
import de.nowchess.chess.grpc.IoGrpcClientWrapper
|
||||||
import de.nowchess.api.game.{DrawReason, GameResult, WinReason}
|
import de.nowchess.api.game.{DrawReason, GameResult, WinReason}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ quarkus:
|
|||||||
|
|
||||||
nowchess:
|
nowchess:
|
||||||
internal:
|
internal:
|
||||||
secret: ${INTERNAL_SECRET}
|
secret: 123abc
|
||||||
smallrye-openapi:
|
smallrye-openapi:
|
||||||
info-title: NowChess IO Service
|
info-title: NowChess IO Service
|
||||||
info-version: 1.0.0
|
info-version: 1.0.0
|
||||||
|
|||||||
@@ -3,61 +3,42 @@ package de.nowchess.io.grpc
|
|||||||
import de.nowchess.api.board.*
|
import de.nowchess.api.board.*
|
||||||
import de.nowchess.api.board.CastlingRights as DomainCastlingRights
|
import de.nowchess.api.board.CastlingRights as DomainCastlingRights
|
||||||
import de.nowchess.api.game.{DrawReason, GameContext, GameResult, WinReason}
|
import de.nowchess.api.game.{DrawReason, GameContext, GameResult, WinReason}
|
||||||
import de.nowchess.api.move.{Move as DomainMove, MoveType, PromotionPiece}
|
import de.nowchess.api.grpc.ProtoMapperBase
|
||||||
|
import de.nowchess.api.move.{Move as DomainMove, MoveType}
|
||||||
import de.nowchess.io.proto.*
|
import de.nowchess.io.proto.*
|
||||||
|
|
||||||
import scala.jdk.CollectionConverters.*
|
import scala.jdk.CollectionConverters.*
|
||||||
|
|
||||||
object IoProtoMapper:
|
object IoProtoMapper extends ProtoMapperBase[ProtoColor, ProtoPieceType, ProtoMoveKind, ProtoMove, ProtoSquarePiece, java.util.List[ProtoSquarePiece], ProtoCastlingRights, ProtoGameResultKind, ProtoGameContext]:
|
||||||
|
private val (colorTo, colorFrom) = ProtoMapperBase.colorConversions(ProtoColor.WHITE, ProtoColor.BLACK)
|
||||||
|
private val (pieceTypeTo, pieceTypeFrom) = ProtoMapperBase.pieceTypeConversions(
|
||||||
|
ProtoPieceType.PAWN,
|
||||||
|
ProtoPieceType.KNIGHT,
|
||||||
|
ProtoPieceType.BISHOP,
|
||||||
|
ProtoPieceType.ROOK,
|
||||||
|
ProtoPieceType.QUEEN,
|
||||||
|
ProtoPieceType.KING,
|
||||||
|
)
|
||||||
|
private val (moveKindTo, moveKindFrom) = ProtoMapperBase.moveKindConversions(
|
||||||
|
ProtoMoveKind.QUIET,
|
||||||
|
ProtoMoveKind.CAPTURE,
|
||||||
|
ProtoMoveKind.CASTLE_KINGSIDE,
|
||||||
|
ProtoMoveKind.CASTLE_QUEENSIDE,
|
||||||
|
ProtoMoveKind.EN_PASSANT,
|
||||||
|
ProtoMoveKind.PROMO_QUEEN,
|
||||||
|
ProtoMoveKind.PROMO_ROOK,
|
||||||
|
ProtoMoveKind.PROMO_BISHOP,
|
||||||
|
ProtoMoveKind.PROMO_KNIGHT,
|
||||||
|
)
|
||||||
|
|
||||||
def toProtoColor(c: Color): ProtoColor = c match
|
override def toProtoColor(c: Color): ProtoColor = colorTo(c)
|
||||||
case Color.White => ProtoColor.WHITE
|
override def fromProtoColor(c: ProtoColor): Color = colorFrom(c)
|
||||||
case Color.Black => ProtoColor.BLACK
|
override def toProtoPieceType(pt: PieceType): ProtoPieceType = pieceTypeTo(pt)
|
||||||
|
override def fromProtoPieceType(pt: ProtoPieceType): PieceType = pieceTypeFrom(pt)
|
||||||
|
override def toProtoMoveKind(mt: MoveType): ProtoMoveKind = moveKindTo(mt)
|
||||||
|
override def fromProtoMoveKind(k: ProtoMoveKind): MoveType = moveKindFrom(k)
|
||||||
|
|
||||||
def fromProtoColor(c: ProtoColor): Color = c match
|
override def toProtoMove(m: DomainMove): ProtoMove =
|
||||||
case ProtoColor.WHITE => Color.White
|
|
||||||
case _ => Color.Black
|
|
||||||
|
|
||||||
def toProtoPieceType(pt: PieceType): ProtoPieceType = pt match
|
|
||||||
case PieceType.Pawn => ProtoPieceType.PAWN
|
|
||||||
case PieceType.Knight => ProtoPieceType.KNIGHT
|
|
||||||
case PieceType.Bishop => ProtoPieceType.BISHOP
|
|
||||||
case PieceType.Rook => ProtoPieceType.ROOK
|
|
||||||
case PieceType.Queen => ProtoPieceType.QUEEN
|
|
||||||
case PieceType.King => ProtoPieceType.KING
|
|
||||||
|
|
||||||
def fromProtoPieceType(pt: ProtoPieceType): PieceType = pt match
|
|
||||||
case ProtoPieceType.PAWN => PieceType.Pawn
|
|
||||||
case ProtoPieceType.KNIGHT => PieceType.Knight
|
|
||||||
case ProtoPieceType.BISHOP => PieceType.Bishop
|
|
||||||
case ProtoPieceType.ROOK => PieceType.Rook
|
|
||||||
case ProtoPieceType.QUEEN => PieceType.Queen
|
|
||||||
case _ => PieceType.King
|
|
||||||
|
|
||||||
def toProtoMoveKind(mt: MoveType): ProtoMoveKind = mt match
|
|
||||||
case MoveType.Normal(false) => ProtoMoveKind.QUIET
|
|
||||||
case MoveType.Normal(true) => ProtoMoveKind.CAPTURE
|
|
||||||
case MoveType.CastleKingside => ProtoMoveKind.CASTLE_KINGSIDE
|
|
||||||
case MoveType.CastleQueenside => ProtoMoveKind.CASTLE_QUEENSIDE
|
|
||||||
case MoveType.EnPassant => ProtoMoveKind.EN_PASSANT
|
|
||||||
case MoveType.Promotion(PromotionPiece.Queen) => ProtoMoveKind.PROMO_QUEEN
|
|
||||||
case MoveType.Promotion(PromotionPiece.Rook) => ProtoMoveKind.PROMO_ROOK
|
|
||||||
case MoveType.Promotion(PromotionPiece.Bishop) => ProtoMoveKind.PROMO_BISHOP
|
|
||||||
case MoveType.Promotion(PromotionPiece.Knight) => ProtoMoveKind.PROMO_KNIGHT
|
|
||||||
|
|
||||||
def fromProtoMoveKind(k: ProtoMoveKind): MoveType = k match
|
|
||||||
case ProtoMoveKind.QUIET => MoveType.Normal(false)
|
|
||||||
case ProtoMoveKind.CAPTURE => MoveType.Normal(true)
|
|
||||||
case ProtoMoveKind.CASTLE_KINGSIDE => MoveType.CastleKingside
|
|
||||||
case ProtoMoveKind.CASTLE_QUEENSIDE => MoveType.CastleQueenside
|
|
||||||
case ProtoMoveKind.EN_PASSANT => MoveType.EnPassant
|
|
||||||
case ProtoMoveKind.PROMO_QUEEN => MoveType.Promotion(PromotionPiece.Queen)
|
|
||||||
case ProtoMoveKind.PROMO_ROOK => MoveType.Promotion(PromotionPiece.Rook)
|
|
||||||
case ProtoMoveKind.PROMO_BISHOP => MoveType.Promotion(PromotionPiece.Bishop)
|
|
||||||
case ProtoMoveKind.PROMO_KNIGHT => MoveType.Promotion(PromotionPiece.Knight)
|
|
||||||
case _ => MoveType.Normal(false)
|
|
||||||
|
|
||||||
def toProtoMove(m: DomainMove): ProtoMove =
|
|
||||||
ProtoMove
|
ProtoMove
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.setFrom(m.from.toString)
|
.setFrom(m.from.toString)
|
||||||
@@ -65,42 +46,44 @@ object IoProtoMapper:
|
|||||||
.setMoveKind(toProtoMoveKind(m.moveType))
|
.setMoveKind(toProtoMoveKind(m.moveType))
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
def fromProtoMove(m: ProtoMove): Option[DomainMove] =
|
override def fromProtoMove(m: ProtoMove): Option[DomainMove] =
|
||||||
for
|
for
|
||||||
from <- Square.fromAlgebraic(m.getFrom)
|
from <- Square.fromAlgebraic(m.getFrom)
|
||||||
to <- Square.fromAlgebraic(m.getTo)
|
to <- Square.fromAlgebraic(m.getTo)
|
||||||
yield DomainMove(from, to, fromProtoMoveKind(m.getMoveKind))
|
yield DomainMove(from, to, fromProtoMoveKind(m.getMoveKind))
|
||||||
|
|
||||||
def toProtoBoard(board: Board): java.util.List[ProtoSquarePiece] =
|
override def toProtoSquarePiece(sq: Square, piece: Piece): ProtoSquarePiece =
|
||||||
board.pieces
|
ProtoSquarePiece
|
||||||
.map { (sq, piece) =>
|
.newBuilder()
|
||||||
ProtoSquarePiece
|
.setSquare(sq.toString)
|
||||||
|
.setPiece(
|
||||||
|
ProtoPiece
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.setSquare(sq.toString)
|
.setColor(toProtoColor(piece.color))
|
||||||
.setPiece(
|
.setPieceType(toProtoPieceType(piece.pieceType))
|
||||||
ProtoPiece
|
.build(),
|
||||||
.newBuilder()
|
)
|
||||||
.setColor(toProtoColor(piece.color))
|
.build()
|
||||||
.setPieceType(toProtoPieceType(piece.pieceType))
|
|
||||||
.build(),
|
override def fromProtoSquarePiece(sp: ProtoSquarePiece): Option[(Square, Piece)] =
|
||||||
)
|
Square
|
||||||
.build()
|
.fromAlgebraic(sp.getSquare)
|
||||||
}
|
.map(_ -> Piece(fromProtoColor(sp.getPiece.getColor), fromProtoPieceType(sp.getPiece.getPieceType)))
|
||||||
|
|
||||||
|
override def toProtoBoard(board: Board): java.util.List[ProtoSquarePiece] =
|
||||||
|
board.pieces
|
||||||
|
.map { (sq, piece) => toProtoSquarePiece(sq, piece) }
|
||||||
.toSeq
|
.toSeq
|
||||||
.asJava
|
.asJava
|
||||||
|
|
||||||
def fromProtoBoard(pieces: java.util.List[ProtoSquarePiece]): Board =
|
override def fromProtoBoard(pieces: java.util.List[ProtoSquarePiece]): Board =
|
||||||
Board(
|
Board(
|
||||||
pieces.asScala
|
pieces.asScala
|
||||||
.flatMap(sp =>
|
.flatMap(fromProtoSquarePiece)
|
||||||
Square
|
|
||||||
.fromAlgebraic(sp.getSquare)
|
|
||||||
.map(_ -> Piece(fromProtoColor(sp.getPiece.getColor), fromProtoPieceType(sp.getPiece.getPieceType))),
|
|
||||||
)
|
|
||||||
.toMap,
|
.toMap,
|
||||||
)
|
)
|
||||||
|
|
||||||
def toProtoResultKind(r: Option[GameResult]): ProtoGameResultKind = r match
|
override def toProtoResultKind(r: Option[GameResult]): ProtoGameResultKind = r match
|
||||||
case None => ProtoGameResultKind.ONGOING
|
case None => ProtoGameResultKind.ONGOING
|
||||||
case Some(GameResult.Win(Color.White, WinReason.Checkmate)) => ProtoGameResultKind.WIN_CHECKMATE_W
|
case Some(GameResult.Win(Color.White, WinReason.Checkmate)) => ProtoGameResultKind.WIN_CHECKMATE_W
|
||||||
case Some(GameResult.Win(Color.Black, WinReason.Checkmate)) => ProtoGameResultKind.WIN_CHECKMATE_B
|
case Some(GameResult.Win(Color.Black, WinReason.Checkmate)) => ProtoGameResultKind.WIN_CHECKMATE_B
|
||||||
@@ -114,7 +97,7 @@ object IoProtoMapper:
|
|||||||
case Some(GameResult.Draw(DrawReason.ThreefoldRepetition)) => ProtoGameResultKind.DRAW_THREEFOLD
|
case Some(GameResult.Draw(DrawReason.ThreefoldRepetition)) => ProtoGameResultKind.DRAW_THREEFOLD
|
||||||
case Some(GameResult.Draw(DrawReason.Agreement)) => ProtoGameResultKind.DRAW_AGREEMENT
|
case Some(GameResult.Draw(DrawReason.Agreement)) => ProtoGameResultKind.DRAW_AGREEMENT
|
||||||
|
|
||||||
def fromProtoResultKind(k: ProtoGameResultKind): Option[GameResult] = k match
|
override def fromProtoResultKind(k: ProtoGameResultKind): Option[GameResult] = k match
|
||||||
case ProtoGameResultKind.ONGOING => None
|
case ProtoGameResultKind.ONGOING => None
|
||||||
case ProtoGameResultKind.WIN_CHECKMATE_W => Some(GameResult.Win(Color.White, WinReason.Checkmate))
|
case ProtoGameResultKind.WIN_CHECKMATE_W => Some(GameResult.Win(Color.White, WinReason.Checkmate))
|
||||||
case ProtoGameResultKind.WIN_CHECKMATE_B => Some(GameResult.Win(Color.Black, WinReason.Checkmate))
|
case ProtoGameResultKind.WIN_CHECKMATE_B => Some(GameResult.Win(Color.Black, WinReason.Checkmate))
|
||||||
@@ -129,20 +112,24 @@ object IoProtoMapper:
|
|||||||
case ProtoGameResultKind.DRAW_AGREEMENT => Some(GameResult.Draw(DrawReason.Agreement))
|
case ProtoGameResultKind.DRAW_AGREEMENT => Some(GameResult.Draw(DrawReason.Agreement))
|
||||||
case _ => None
|
case _ => None
|
||||||
|
|
||||||
def toProtoGameContext(ctx: GameContext): ProtoGameContext =
|
override def toProtoCastlingRights(cr: DomainCastlingRights): ProtoCastlingRights =
|
||||||
|
ProtoCastlingRights
|
||||||
|
.newBuilder()
|
||||||
|
.setWhiteKingSide(cr.whiteKingSide)
|
||||||
|
.setWhiteQueenSide(cr.whiteQueenSide)
|
||||||
|
.setBlackKingSide(cr.blackKingSide)
|
||||||
|
.setBlackQueenSide(cr.blackQueenSide)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
override def fromProtoCastlingRights(pcr: ProtoCastlingRights): DomainCastlingRights =
|
||||||
|
DomainCastlingRights(pcr.getWhiteKingSide, pcr.getWhiteQueenSide, pcr.getBlackKingSide, pcr.getBlackQueenSide)
|
||||||
|
|
||||||
|
override def toProtoGameContext(ctx: GameContext): ProtoGameContext =
|
||||||
ProtoGameContext
|
ProtoGameContext
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.addAllBoard(toProtoBoard(ctx.board))
|
.addAllBoard(toProtoBoard(ctx.board))
|
||||||
.setTurn(toProtoColor(ctx.turn))
|
.setTurn(toProtoColor(ctx.turn))
|
||||||
.setCastlingRights(
|
.setCastlingRights(toProtoCastlingRights(ctx.castlingRights))
|
||||||
ProtoCastlingRights
|
|
||||||
.newBuilder()
|
|
||||||
.setWhiteKingSide(ctx.castlingRights.whiteKingSide)
|
|
||||||
.setWhiteQueenSide(ctx.castlingRights.whiteQueenSide)
|
|
||||||
.setBlackKingSide(ctx.castlingRights.blackKingSide)
|
|
||||||
.setBlackQueenSide(ctx.castlingRights.blackQueenSide)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.setEnPassantSquare(ctx.enPassantSquare.map(_.toString).getOrElse(""))
|
.setEnPassantSquare(ctx.enPassantSquare.map(_.toString).getOrElse(""))
|
||||||
.setHalfMoveClock(ctx.halfMoveClock)
|
.setHalfMoveClock(ctx.halfMoveClock)
|
||||||
.addAllMoves(ctx.moves.map(toProtoMove).asJava)
|
.addAllMoves(ctx.moves.map(toProtoMove).asJava)
|
||||||
@@ -150,13 +137,11 @@ object IoProtoMapper:
|
|||||||
.addAllInitialBoard(toProtoBoard(ctx.initialBoard))
|
.addAllInitialBoard(toProtoBoard(ctx.initialBoard))
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
def fromProtoGameContext(p: ProtoGameContext): GameContext =
|
override def fromProtoGameContext(p: ProtoGameContext): GameContext =
|
||||||
val cr = p.getCastlingRights
|
|
||||||
GameContext(
|
GameContext(
|
||||||
board = fromProtoBoard(p.getBoardList),
|
board = fromProtoBoard(p.getBoardList),
|
||||||
turn = fromProtoColor(p.getTurn),
|
turn = fromProtoColor(p.getTurn),
|
||||||
castlingRights =
|
castlingRights = fromProtoCastlingRights(p.getCastlingRights),
|
||||||
DomainCastlingRights(cr.getWhiteKingSide, cr.getWhiteQueenSide, cr.getBlackKingSide, cr.getBlackQueenSide),
|
|
||||||
enPassantSquare = Option(p.getEnPassantSquare).filter(_.nonEmpty).flatMap(Square.fromAlgebraic),
|
enPassantSquare = Option(p.getEnPassantSquare).filter(_.nonEmpty).flatMap(Square.fromAlgebraic),
|
||||||
halfMoveClock = p.getHalfMoveClock,
|
halfMoveClock = p.getHalfMoveClock,
|
||||||
moves = p.getMovesList.asScala.flatMap(fromProtoMove).toList,
|
moves = p.getMovesList.asScala.flatMap(fromProtoMove).toList,
|
||||||
|
|||||||
@@ -9,4 +9,4 @@ quarkus:
|
|||||||
|
|
||||||
nowchess:
|
nowchess:
|
||||||
internal:
|
internal:
|
||||||
secret: ${INTERNAL_SECRET}
|
secret: 123abc
|
||||||
|
|||||||
@@ -2,61 +2,42 @@ package de.nowchess.rules.grpc
|
|||||||
|
|
||||||
import de.nowchess.api.board.{CastlingRights as DomainCastlingRights, *}
|
import de.nowchess.api.board.{CastlingRights as DomainCastlingRights, *}
|
||||||
import de.nowchess.api.game.{DrawReason, GameContext, GameResult, WinReason}
|
import de.nowchess.api.game.{DrawReason, GameContext, GameResult, WinReason}
|
||||||
import de.nowchess.api.move.{Move as DomainMove, MoveType, PromotionPiece}
|
import de.nowchess.api.grpc.ProtoMapperBase
|
||||||
|
import de.nowchess.api.move.{Move as DomainMove, MoveType}
|
||||||
import de.nowchess.rules.proto.*
|
import de.nowchess.rules.proto.*
|
||||||
|
|
||||||
import scala.jdk.CollectionConverters.*
|
import scala.jdk.CollectionConverters.*
|
||||||
|
|
||||||
object ProtoMapper:
|
object ProtoMapper extends ProtoMapperBase[ProtoColor, ProtoPieceType, ProtoMoveKind, ProtoMove, ProtoSquarePiece, java.util.List[ProtoSquarePiece], ProtoCastlingRights, ProtoGameResultKind, ProtoGameContext]:
|
||||||
|
private val (colorTo, colorFrom) = ProtoMapperBase.colorConversions(ProtoColor.WHITE, ProtoColor.BLACK)
|
||||||
|
private val (pieceTypeTo, pieceTypeFrom) = ProtoMapperBase.pieceTypeConversions(
|
||||||
|
ProtoPieceType.PAWN,
|
||||||
|
ProtoPieceType.KNIGHT,
|
||||||
|
ProtoPieceType.BISHOP,
|
||||||
|
ProtoPieceType.ROOK,
|
||||||
|
ProtoPieceType.QUEEN,
|
||||||
|
ProtoPieceType.KING,
|
||||||
|
)
|
||||||
|
private val (moveKindTo, moveKindFrom) = ProtoMapperBase.moveKindConversions(
|
||||||
|
ProtoMoveKind.QUIET,
|
||||||
|
ProtoMoveKind.CAPTURE,
|
||||||
|
ProtoMoveKind.CASTLE_KINGSIDE,
|
||||||
|
ProtoMoveKind.CASTLE_QUEENSIDE,
|
||||||
|
ProtoMoveKind.EN_PASSANT,
|
||||||
|
ProtoMoveKind.PROMO_QUEEN,
|
||||||
|
ProtoMoveKind.PROMO_ROOK,
|
||||||
|
ProtoMoveKind.PROMO_BISHOP,
|
||||||
|
ProtoMoveKind.PROMO_KNIGHT,
|
||||||
|
)
|
||||||
|
|
||||||
def toProtoColor(c: Color): ProtoColor = c match
|
override def toProtoColor(c: Color): ProtoColor = colorTo(c)
|
||||||
case Color.White => ProtoColor.WHITE
|
override def fromProtoColor(c: ProtoColor): Color = colorFrom(c)
|
||||||
case Color.Black => ProtoColor.BLACK
|
override def toProtoPieceType(pt: PieceType): ProtoPieceType = pieceTypeTo(pt)
|
||||||
|
override def fromProtoPieceType(pt: ProtoPieceType): PieceType = pieceTypeFrom(pt)
|
||||||
|
override def toProtoMoveKind(mt: MoveType): ProtoMoveKind = moveKindTo(mt)
|
||||||
|
override def fromProtoMoveKind(k: ProtoMoveKind): MoveType = moveKindFrom(k)
|
||||||
|
|
||||||
def fromProtoColor(c: ProtoColor): Color = c match
|
override def toProtoMove(m: DomainMove): ProtoMove =
|
||||||
case ProtoColor.WHITE => Color.White
|
|
||||||
case _ => Color.Black
|
|
||||||
|
|
||||||
def toProtoPieceType(pt: PieceType): ProtoPieceType = pt match
|
|
||||||
case PieceType.Pawn => ProtoPieceType.PAWN
|
|
||||||
case PieceType.Knight => ProtoPieceType.KNIGHT
|
|
||||||
case PieceType.Bishop => ProtoPieceType.BISHOP
|
|
||||||
case PieceType.Rook => ProtoPieceType.ROOK
|
|
||||||
case PieceType.Queen => ProtoPieceType.QUEEN
|
|
||||||
case PieceType.King => ProtoPieceType.KING
|
|
||||||
|
|
||||||
def fromProtoPieceType(pt: ProtoPieceType): PieceType = pt match
|
|
||||||
case ProtoPieceType.PAWN => PieceType.Pawn
|
|
||||||
case ProtoPieceType.KNIGHT => PieceType.Knight
|
|
||||||
case ProtoPieceType.BISHOP => PieceType.Bishop
|
|
||||||
case ProtoPieceType.ROOK => PieceType.Rook
|
|
||||||
case ProtoPieceType.QUEEN => PieceType.Queen
|
|
||||||
case _ => PieceType.King
|
|
||||||
|
|
||||||
def toProtoMoveKind(mt: MoveType): ProtoMoveKind = mt match
|
|
||||||
case MoveType.Normal(false) => ProtoMoveKind.QUIET
|
|
||||||
case MoveType.Normal(true) => ProtoMoveKind.CAPTURE
|
|
||||||
case MoveType.CastleKingside => ProtoMoveKind.CASTLE_KINGSIDE
|
|
||||||
case MoveType.CastleQueenside => ProtoMoveKind.CASTLE_QUEENSIDE
|
|
||||||
case MoveType.EnPassant => ProtoMoveKind.EN_PASSANT
|
|
||||||
case MoveType.Promotion(PromotionPiece.Queen) => ProtoMoveKind.PROMO_QUEEN
|
|
||||||
case MoveType.Promotion(PromotionPiece.Rook) => ProtoMoveKind.PROMO_ROOK
|
|
||||||
case MoveType.Promotion(PromotionPiece.Bishop) => ProtoMoveKind.PROMO_BISHOP
|
|
||||||
case MoveType.Promotion(PromotionPiece.Knight) => ProtoMoveKind.PROMO_KNIGHT
|
|
||||||
|
|
||||||
def fromProtoMoveKind(k: ProtoMoveKind): MoveType = k match
|
|
||||||
case ProtoMoveKind.QUIET => MoveType.Normal(false)
|
|
||||||
case ProtoMoveKind.CAPTURE => MoveType.Normal(true)
|
|
||||||
case ProtoMoveKind.CASTLE_KINGSIDE => MoveType.CastleKingside
|
|
||||||
case ProtoMoveKind.CASTLE_QUEENSIDE => MoveType.CastleQueenside
|
|
||||||
case ProtoMoveKind.EN_PASSANT => MoveType.EnPassant
|
|
||||||
case ProtoMoveKind.PROMO_QUEEN => MoveType.Promotion(PromotionPiece.Queen)
|
|
||||||
case ProtoMoveKind.PROMO_ROOK => MoveType.Promotion(PromotionPiece.Rook)
|
|
||||||
case ProtoMoveKind.PROMO_BISHOP => MoveType.Promotion(PromotionPiece.Bishop)
|
|
||||||
case ProtoMoveKind.PROMO_KNIGHT => MoveType.Promotion(PromotionPiece.Knight)
|
|
||||||
case _ => MoveType.Normal(false)
|
|
||||||
|
|
||||||
def toProtoMove(m: DomainMove): ProtoMove =
|
|
||||||
ProtoMove
|
ProtoMove
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.setFrom(m.from.toString)
|
.setFrom(m.from.toString)
|
||||||
@@ -64,42 +45,44 @@ object ProtoMapper:
|
|||||||
.setMoveKind(toProtoMoveKind(m.moveType))
|
.setMoveKind(toProtoMoveKind(m.moveType))
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
def fromProtoMove(m: ProtoMove): Option[DomainMove] =
|
override def fromProtoMove(m: ProtoMove): Option[DomainMove] =
|
||||||
for
|
for
|
||||||
from <- Square.fromAlgebraic(m.getFrom)
|
from <- Square.fromAlgebraic(m.getFrom)
|
||||||
to <- Square.fromAlgebraic(m.getTo)
|
to <- Square.fromAlgebraic(m.getTo)
|
||||||
yield DomainMove(from, to, fromProtoMoveKind(m.getMoveKind))
|
yield DomainMove(from, to, fromProtoMoveKind(m.getMoveKind))
|
||||||
|
|
||||||
def toProtoBoard(board: Board): java.util.List[ProtoSquarePiece] =
|
override def toProtoSquarePiece(sq: Square, piece: Piece): ProtoSquarePiece =
|
||||||
board.pieces
|
ProtoSquarePiece
|
||||||
.map { (sq, piece) =>
|
.newBuilder()
|
||||||
ProtoSquarePiece
|
.setSquare(sq.toString)
|
||||||
|
.setPiece(
|
||||||
|
ProtoPiece
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.setSquare(sq.toString)
|
.setColor(toProtoColor(piece.color))
|
||||||
.setPiece(
|
.setPieceType(toProtoPieceType(piece.pieceType))
|
||||||
ProtoPiece
|
.build(),
|
||||||
.newBuilder()
|
)
|
||||||
.setColor(toProtoColor(piece.color))
|
.build()
|
||||||
.setPieceType(toProtoPieceType(piece.pieceType))
|
|
||||||
.build(),
|
override def fromProtoSquarePiece(sp: ProtoSquarePiece): Option[(Square, Piece)] =
|
||||||
)
|
Square
|
||||||
.build()
|
.fromAlgebraic(sp.getSquare)
|
||||||
}
|
.map(_ -> Piece(fromProtoColor(sp.getPiece.getColor), fromProtoPieceType(sp.getPiece.getPieceType)))
|
||||||
|
|
||||||
|
override def toProtoBoard(board: Board): java.util.List[ProtoSquarePiece] =
|
||||||
|
board.pieces
|
||||||
|
.map { (sq, piece) => toProtoSquarePiece(sq, piece) }
|
||||||
.toSeq
|
.toSeq
|
||||||
.asJava
|
.asJava
|
||||||
|
|
||||||
def fromProtoBoard(pieces: java.util.List[ProtoSquarePiece]): Board =
|
override def fromProtoBoard(pieces: java.util.List[ProtoSquarePiece]): Board =
|
||||||
Board(
|
Board(
|
||||||
pieces.asScala
|
pieces.asScala
|
||||||
.flatMap(sp =>
|
.flatMap(fromProtoSquarePiece)
|
||||||
Square
|
|
||||||
.fromAlgebraic(sp.getSquare)
|
|
||||||
.map(_ -> Piece(fromProtoColor(sp.getPiece.getColor), fromProtoPieceType(sp.getPiece.getPieceType))),
|
|
||||||
)
|
|
||||||
.toMap,
|
.toMap,
|
||||||
)
|
)
|
||||||
|
|
||||||
def toProtoResultKind(r: Option[GameResult]): ProtoGameResultKind = r match
|
override def toProtoResultKind(r: Option[GameResult]): ProtoGameResultKind = r match
|
||||||
case None => ProtoGameResultKind.ONGOING
|
case None => ProtoGameResultKind.ONGOING
|
||||||
case Some(GameResult.Win(Color.White, WinReason.Checkmate)) => ProtoGameResultKind.WIN_CHECKMATE_W
|
case Some(GameResult.Win(Color.White, WinReason.Checkmate)) => ProtoGameResultKind.WIN_CHECKMATE_W
|
||||||
case Some(GameResult.Win(Color.Black, WinReason.Checkmate)) => ProtoGameResultKind.WIN_CHECKMATE_B
|
case Some(GameResult.Win(Color.Black, WinReason.Checkmate)) => ProtoGameResultKind.WIN_CHECKMATE_B
|
||||||
@@ -113,7 +96,7 @@ object ProtoMapper:
|
|||||||
case Some(GameResult.Draw(DrawReason.ThreefoldRepetition)) => ProtoGameResultKind.DRAW_THREEFOLD
|
case Some(GameResult.Draw(DrawReason.ThreefoldRepetition)) => ProtoGameResultKind.DRAW_THREEFOLD
|
||||||
case Some(GameResult.Draw(DrawReason.Agreement)) => ProtoGameResultKind.DRAW_AGREEMENT
|
case Some(GameResult.Draw(DrawReason.Agreement)) => ProtoGameResultKind.DRAW_AGREEMENT
|
||||||
|
|
||||||
def fromProtoResultKind(k: ProtoGameResultKind): Option[GameResult] = k match
|
override def fromProtoResultKind(k: ProtoGameResultKind): Option[GameResult] = k match
|
||||||
case ProtoGameResultKind.ONGOING => None
|
case ProtoGameResultKind.ONGOING => None
|
||||||
case ProtoGameResultKind.WIN_CHECKMATE_W => Some(GameResult.Win(Color.White, WinReason.Checkmate))
|
case ProtoGameResultKind.WIN_CHECKMATE_W => Some(GameResult.Win(Color.White, WinReason.Checkmate))
|
||||||
case ProtoGameResultKind.WIN_CHECKMATE_B => Some(GameResult.Win(Color.Black, WinReason.Checkmate))
|
case ProtoGameResultKind.WIN_CHECKMATE_B => Some(GameResult.Win(Color.Black, WinReason.Checkmate))
|
||||||
@@ -128,20 +111,24 @@ object ProtoMapper:
|
|||||||
case ProtoGameResultKind.DRAW_AGREEMENT => Some(GameResult.Draw(DrawReason.Agreement))
|
case ProtoGameResultKind.DRAW_AGREEMENT => Some(GameResult.Draw(DrawReason.Agreement))
|
||||||
case _ => None
|
case _ => None
|
||||||
|
|
||||||
def toProtoGameContext(ctx: GameContext): ProtoGameContext =
|
override def toProtoCastlingRights(cr: DomainCastlingRights): ProtoCastlingRights =
|
||||||
|
ProtoCastlingRights
|
||||||
|
.newBuilder()
|
||||||
|
.setWhiteKingSide(cr.whiteKingSide)
|
||||||
|
.setWhiteQueenSide(cr.whiteQueenSide)
|
||||||
|
.setBlackKingSide(cr.blackKingSide)
|
||||||
|
.setBlackQueenSide(cr.blackQueenSide)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
override def fromProtoCastlingRights(pcr: ProtoCastlingRights): DomainCastlingRights =
|
||||||
|
DomainCastlingRights(pcr.getWhiteKingSide, pcr.getWhiteQueenSide, pcr.getBlackKingSide, pcr.getBlackQueenSide)
|
||||||
|
|
||||||
|
override def toProtoGameContext(ctx: GameContext): ProtoGameContext =
|
||||||
ProtoGameContext
|
ProtoGameContext
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.addAllBoard(toProtoBoard(ctx.board))
|
.addAllBoard(toProtoBoard(ctx.board))
|
||||||
.setTurn(toProtoColor(ctx.turn))
|
.setTurn(toProtoColor(ctx.turn))
|
||||||
.setCastlingRights(
|
.setCastlingRights(toProtoCastlingRights(ctx.castlingRights))
|
||||||
ProtoCastlingRights
|
|
||||||
.newBuilder()
|
|
||||||
.setWhiteKingSide(ctx.castlingRights.whiteKingSide)
|
|
||||||
.setWhiteQueenSide(ctx.castlingRights.whiteQueenSide)
|
|
||||||
.setBlackKingSide(ctx.castlingRights.blackKingSide)
|
|
||||||
.setBlackQueenSide(ctx.castlingRights.blackQueenSide)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.setEnPassantSquare(ctx.enPassantSquare.map(_.toString).getOrElse(""))
|
.setEnPassantSquare(ctx.enPassantSquare.map(_.toString).getOrElse(""))
|
||||||
.setHalfMoveClock(ctx.halfMoveClock)
|
.setHalfMoveClock(ctx.halfMoveClock)
|
||||||
.addAllMoves(ctx.moves.map(toProtoMove).asJava)
|
.addAllMoves(ctx.moves.map(toProtoMove).asJava)
|
||||||
@@ -149,13 +136,11 @@ object ProtoMapper:
|
|||||||
.addAllInitialBoard(toProtoBoard(ctx.initialBoard))
|
.addAllInitialBoard(toProtoBoard(ctx.initialBoard))
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
def fromProtoGameContext(p: ProtoGameContext): GameContext =
|
override def fromProtoGameContext(p: ProtoGameContext): GameContext =
|
||||||
val cr = p.getCastlingRights
|
|
||||||
GameContext(
|
GameContext(
|
||||||
board = fromProtoBoard(p.getBoardList),
|
board = fromProtoBoard(p.getBoardList),
|
||||||
turn = fromProtoColor(p.getTurn),
|
turn = fromProtoColor(p.getTurn),
|
||||||
castlingRights =
|
castlingRights = fromProtoCastlingRights(p.getCastlingRights),
|
||||||
DomainCastlingRights(cr.getWhiteKingSide, cr.getWhiteQueenSide, cr.getBlackKingSide, cr.getBlackQueenSide),
|
|
||||||
enPassantSquare = Option(p.getEnPassantSquare).filter(_.nonEmpty).flatMap(Square.fromAlgebraic),
|
enPassantSquare = Option(p.getEnPassantSquare).filter(_.nonEmpty).flatMap(Square.fromAlgebraic),
|
||||||
halfMoveClock = p.getHalfMoveClock,
|
halfMoveClock = p.getHalfMoveClock,
|
||||||
moves = p.getMovesList.asScala.flatMap(fromProtoMove).toList,
|
moves = p.getMovesList.asScala.flatMap(fromProtoMove).toList,
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ class InternalGrpcSecretClientInterceptor extends ClientInterceptor:
|
|||||||
|
|
||||||
private val secretKey = Metadata.Key.of("x-internal-secret", Metadata.ASCII_STRING_MARSHALLER)
|
private val secretKey = Metadata.Key.of("x-internal-secret", Metadata.ASCII_STRING_MARSHALLER)
|
||||||
|
|
||||||
@ConfigProperty(name = "nowchess.internal.secret")
|
@ConfigProperty(name = "nowchess.internal.secret", defaultValue = "")
|
||||||
// scalafix:off DisableSyntax.var
|
// scalafix:off DisableSyntax.var
|
||||||
var secret: String = uninitialized
|
var secret: String = uninitialized
|
||||||
// scalafix:on DisableSyntax.var
|
// scalafix:on DisableSyntax.var
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ import scala.compiletime.uninitialized
|
|||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
class InternalSecretClientFilter extends ClientRequestFilter:
|
class InternalSecretClientFilter extends ClientRequestFilter:
|
||||||
|
|
||||||
@ConfigProperty(name = "nowchess.internal.secret")
|
@ConfigProperty(name = "nowchess.internal.secret", defaultValue = "")
|
||||||
// scalafix:off DisableSyntax.var
|
// scalafix:off DisableSyntax.var
|
||||||
var secret: String = uninitialized
|
var secret: String = uninitialized
|
||||||
// scalafix:on DisableSyntax.var
|
// scalafix:on DisableSyntax.var
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ val quarkusPlatformArtifactId: String by project
|
|||||||
val quarkusPlatformVersion: String by project
|
val quarkusPlatformVersion: String by project
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation(project(":modules:api"))
|
||||||
|
|
||||||
runtimeOnly("io.quarkus:quarkus-jdbc-h2")
|
runtimeOnly("io.quarkus:quarkus-jdbc-h2")
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package de.nowchess.store.config
|
package de.nowchess.store.config
|
||||||
|
|
||||||
|
import de.nowchess.api.dto.{GameWritebackEventDto}
|
||||||
import de.nowchess.store.domain.GameRecord
|
import de.nowchess.store.domain.GameRecord
|
||||||
import de.nowchess.store.redis.GameWritebackEventDto
|
|
||||||
import io.quarkus.runtime.annotations.RegisterForReflection
|
import io.quarkus.runtime.annotations.RegisterForReflection
|
||||||
|
|
||||||
@RegisterForReflection(
|
@RegisterForReflection(
|
||||||
|
|||||||
@@ -86,6 +86,9 @@ class GameRecord extends PanacheEntityBase:
|
|||||||
@Column
|
@Column
|
||||||
var pendingDrawOffer: String = uninitialized
|
var pendingDrawOffer: String = uninitialized
|
||||||
|
|
||||||
|
@Column
|
||||||
|
var pendingTakebackOffer: String = uninitialized
|
||||||
|
|
||||||
// Game result
|
// Game result
|
||||||
@Column
|
@Column
|
||||||
var result: String = uninitialized
|
var result: String = uninitialized
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
package de.nowchess.store.redis
|
|
||||||
|
|
||||||
case class GameWritebackEventDto(
|
|
||||||
gameId: String,
|
|
||||||
fen: String,
|
|
||||||
pgn: String,
|
|
||||||
moveCount: Int,
|
|
||||||
whiteId: String,
|
|
||||||
whiteName: String,
|
|
||||||
blackId: String,
|
|
||||||
blackName: String,
|
|
||||||
mode: String,
|
|
||||||
resigned: Boolean,
|
|
||||||
limitSeconds: Option[Int],
|
|
||||||
incrementSeconds: Option[Int],
|
|
||||||
daysPerMove: Option[Int],
|
|
||||||
whiteRemainingMs: Option[Long],
|
|
||||||
blackRemainingMs: Option[Long],
|
|
||||||
incrementMs: Option[Long],
|
|
||||||
clockLastTickAt: Option[Long],
|
|
||||||
clockMoveDeadline: Option[Long],
|
|
||||||
clockActiveColor: Option[String],
|
|
||||||
pendingDrawOffer: Option[String],
|
|
||||||
result: Option[String] = None,
|
|
||||||
terminationReason: Option[String] = None,
|
|
||||||
)
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package de.nowchess.store.redis
|
package de.nowchess.store.redis
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
|
import de.nowchess.api.dto.GameWritebackEventDto
|
||||||
import de.nowchess.store.service.GameWritebackService
|
import de.nowchess.store.service.GameWritebackService
|
||||||
import io.quarkus.redis.datasource.RedisDataSource
|
import io.quarkus.redis.datasource.RedisDataSource
|
||||||
import jakarta.annotation.PostConstruct
|
import jakarta.annotation.PostConstruct
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ class GameRecordRepository:
|
|||||||
|
|
||||||
def findByPlayerId(playerId: String, offset: Int, limit: Int): List[GameRecord] =
|
def findByPlayerId(playerId: String, offset: Int, limit: Int): List[GameRecord] =
|
||||||
em.createQuery(
|
em.createQuery(
|
||||||
"SELECT g FROM GameRecord g WHERE g.whiteId = :id OR g.blackId = :id ORDER BY g.updatedAt DESC",
|
"SELECT g FROM GameRecord g WHERE g.whiteId = :id OR g.blackId = :id AND g.result != null ORDER BY g.updatedAt DESC",
|
||||||
classOf[GameRecord],
|
classOf[GameRecord],
|
||||||
).setParameter("id", playerId)
|
).setParameter("id", playerId)
|
||||||
.setFirstResult(offset)
|
.setFirstResult(offset)
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package de.nowchess.store.service
|
package de.nowchess.store.service
|
||||||
|
|
||||||
|
import de.nowchess.api.dto.GameWritebackEventDto
|
||||||
import de.nowchess.store.domain.GameRecord
|
import de.nowchess.store.domain.GameRecord
|
||||||
import de.nowchess.store.redis.GameWritebackEventDto
|
|
||||||
import de.nowchess.store.repository.GameRecordRepository
|
import de.nowchess.store.repository.GameRecordRepository
|
||||||
import jakarta.enterprise.context.ApplicationScoped
|
import jakarta.enterprise.context.ApplicationScoped
|
||||||
import jakarta.inject.Inject
|
import jakarta.inject.Inject
|
||||||
import jakarta.transaction.Transactional
|
import jakarta.transaction.Transactional
|
||||||
|
|
||||||
import scala.compiletime.uninitialized
|
import scala.compiletime.uninitialized
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
@@ -66,6 +67,7 @@ class GameWritebackService:
|
|||||||
r.clockMoveDeadline = event.clockMoveDeadline.map(java.lang.Long.valueOf).orNull
|
r.clockMoveDeadline = event.clockMoveDeadline.map(java.lang.Long.valueOf).orNull
|
||||||
r.clockActiveColor = event.clockActiveColor.orNull
|
r.clockActiveColor = event.clockActiveColor.orNull
|
||||||
r.pendingDrawOffer = event.pendingDrawOffer.orNull
|
r.pendingDrawOffer = event.pendingDrawOffer.orNull
|
||||||
|
r.pendingTakebackOffer = event.pendingTakebackRequest.orNull
|
||||||
r.result = event.result.orNull
|
r.result = event.result.orNull
|
||||||
r.terminationReason = event.terminationReason.orNull
|
r.terminationReason = event.terminationReason.orNull
|
||||||
r.updatedAt = Instant.now()
|
r.updatedAt = Instant.now()
|
||||||
|
|||||||
Reference in New Issue
Block a user