feat: NCS-37 Add initial API structure and DTOs for NowChess application
This commit is contained in:
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ScalaProjectSettings">
|
||||
<option name="scala3DisclaimerShown" value="true" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,6 +1,5 @@
|
||||
package de.nowchess.chess.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
|
||||
@@ -9,9 +8,4 @@ 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
|
||||
})
|
||||
mapper.registerModule(DefaultScalaModule)
|
||||
|
||||
@@ -9,5 +9,6 @@ final case class GameEntry(
|
||||
engine: GameEngine,
|
||||
white: PlayerInfo,
|
||||
black: PlayerInfo,
|
||||
drawOfferedBy: Option[Color] = None,
|
||||
resigned: Boolean = false,
|
||||
)
|
||||
|
||||
@@ -20,19 +20,10 @@ import jakarta.ws.rs.*
|
||||
import jakarta.ws.rs.core.{MediaType, Response}
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
import scala.compiletime.uninitialized
|
||||
|
||||
@Path("/api/board/game")
|
||||
@ApplicationScoped
|
||||
class GameResource:
|
||||
|
||||
// scalafix:off DisableSyntax.var
|
||||
@Inject
|
||||
var registry: GameRegistry = uninitialized
|
||||
|
||||
@Inject
|
||||
var objectMapper: ObjectMapper = uninitialized
|
||||
// scalafix:on DisableSyntax.var
|
||||
class GameResource(@Inject val registry: GameRegistry, @Inject val objectMapper: ObjectMapper):
|
||||
|
||||
private val DefaultWhite = PlayerInfo(PlayerId("p1"), "Player 1")
|
||||
private val DefaultBlack = PlayerInfo(PlayerId("p2"), "Player 2")
|
||||
@@ -40,7 +31,7 @@ class GameResource:
|
||||
// ── mapping ──────────────────────────────────────────────────────────────
|
||||
|
||||
private def statusOf(entry: GameEntry): String =
|
||||
if entry.engine.pendingDrawOfferBy.isDefined then "drawOffered"
|
||||
if entry.drawOfferedBy.isDefined then "drawOffered"
|
||||
else
|
||||
val ctx = entry.engine.context
|
||||
ctx.result match
|
||||
@@ -113,7 +104,7 @@ class GameResource:
|
||||
val error = new AtomicReference[Option[String]](None)
|
||||
val obs = new Observer:
|
||||
def onGameEvent(e: GameEvent): Unit = e match
|
||||
case InvalidMoveEvent(_, reason) => error.set(Some(reason.toString))
|
||||
case InvalidMoveEvent(_, reason) => error.set(Some(reason))
|
||||
case _ => ()
|
||||
engine.subscribe(obs)
|
||||
engine.processUserInput(uci)
|
||||
@@ -142,7 +133,6 @@ class GameResource:
|
||||
val black = playerInfoFrom(req.black, DefaultBlack)
|
||||
val entry = newEntry(GameContext.initial, white, black)
|
||||
registry.store(entry)
|
||||
println(s"Created game ${entry.gameId}")
|
||||
created(toGameFullDto(entry))
|
||||
|
||||
@GET
|
||||
@@ -245,16 +235,26 @@ class GameResource:
|
||||
assertGameNotOver(entry)
|
||||
action match
|
||||
case "offer" =>
|
||||
entry.engine.offerDraw(entry.engine.context.turn)
|
||||
registry.update(entry.copy(drawOfferedBy = Some(entry.engine.context.turn)))
|
||||
ok(OkResponseDto())
|
||||
case "accept" =>
|
||||
entry.engine.acceptDraw(entry.engine.context.turn)
|
||||
ok(OkResponseDto())
|
||||
entry.drawOfferedBy match
|
||||
case None =>
|
||||
throw BadRequestException("NO_DRAW_OFFER", "No draw offer to accept")
|
||||
case Some(offerer) if offerer == entry.engine.context.turn =>
|
||||
throw BadRequestException("CANNOT_ACCEPT_OWN_OFFER", "Cannot accept your own draw offer")
|
||||
case _ =>
|
||||
entry.engine.applyDraw(DrawReason.Agreement)
|
||||
registry.update(entry.copy(drawOfferedBy = None))
|
||||
ok(OkResponseDto())
|
||||
case "decline" =>
|
||||
entry.engine.declineDraw(entry.engine.context.turn)
|
||||
if entry.drawOfferedBy.isEmpty then throw BadRequestException("NO_DRAW_OFFER", "No draw offer to decline")
|
||||
registry.update(entry.copy(drawOfferedBy = None))
|
||||
ok(OkResponseDto())
|
||||
case "claim" =>
|
||||
entry.engine.claimDraw()
|
||||
if entry.engine.context.halfMoveClock < 100 then
|
||||
throw BadRequestException("CLAIM_NOT_AVAILABLE", "Fifty-move rule draw is not available")
|
||||
entry.engine.applyDraw(DrawReason.FiftyMoveRule)
|
||||
ok(OkResponseDto())
|
||||
case _ =>
|
||||
throw BadRequestException("INVALID_ACTION", s"Unknown draw action: $action", Some("action"))
|
||||
|
||||
Reference in New Issue
Block a user