remember all draw offers - WIP
parent
93eb5e820c
commit
19b3c16f11
|
@ -66,6 +66,18 @@ object BSONHandlers {
|
|||
)
|
||||
}
|
||||
|
||||
implicit private[game] val gameDrawOffersHandler = tryHandler[GameDrawOffers](
|
||||
{ case arr: BSONArray =>
|
||||
Success(arr.values.foldLeft(GameDrawOffers.empty) {
|
||||
case (offers, BSONInteger(p)) =>
|
||||
if (p > 0) offers.copy(white = offers.white incl p)
|
||||
else offers.copy(black = offers.black incl -p)
|
||||
case (offers, _) => offers
|
||||
})
|
||||
},
|
||||
offers => BSONArray(offers.white ++ offers.black.map(-_))
|
||||
)
|
||||
|
||||
import Player.playerBSONHandler
|
||||
private val emptyPlayerBuilder = playerBSONHandler.read($empty)
|
||||
|
||||
|
@ -160,7 +172,8 @@ object BSONHandlers {
|
|||
tournamentId = r strO F.tournamentId,
|
||||
swissId = r strO F.swissId,
|
||||
simulId = r strO F.simulId,
|
||||
analysed = r boolD F.analysed
|
||||
analysed = r boolD F.analysed,
|
||||
drawOffers = r.getD(F.drawOffers, GameDrawOffers.empty)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -315,15 +315,21 @@ case class Game(
|
|||
blackPlayer = f(blackPlayer)
|
||||
)
|
||||
|
||||
def drawOffers = metadata.drawOffers
|
||||
|
||||
def playerCanOfferDraw(color: Color) =
|
||||
started && playable &&
|
||||
turns >= 2 &&
|
||||
!player(color).isOfferingDraw &&
|
||||
!opponent(color).isAi &&
|
||||
!playerHasOfferedDraw(color)
|
||||
!playerHasOfferedDrawRecently(color)
|
||||
|
||||
def playerHasOfferedDraw(color: Color) =
|
||||
player(color).lastDrawOffer ?? (_ >= turns - 20)
|
||||
def playerHasOfferedDrawRecently(color: Color) =
|
||||
drawOffers.lastBy(color) ?? (_ >= turns - 20)
|
||||
|
||||
def offerDraw(color: Color) = copy(
|
||||
metadata = metadata.copy(drawOffers = drawOffers.add(color, turns))
|
||||
).updatePlayer(color, _.offerDraw)
|
||||
|
||||
def playerCouldRematch =
|
||||
finishedOrAborted &&
|
||||
|
@ -735,14 +741,7 @@ object Game {
|
|||
status = Status.Created,
|
||||
daysPerTurn = daysPerTurn,
|
||||
mode = mode,
|
||||
metadata = Metadata(
|
||||
source = source.some,
|
||||
pgnImport = pgnImport,
|
||||
tournamentId = none,
|
||||
swissId = none,
|
||||
simulId = none,
|
||||
analysed = false
|
||||
),
|
||||
metadata = metadata(source).copy(pgnImport = pgnImport),
|
||||
createdAt = createdAt,
|
||||
movedAt = createdAt
|
||||
)
|
||||
|
@ -756,7 +755,8 @@ object Game {
|
|||
tournamentId = none,
|
||||
swissId = none,
|
||||
simulId = none,
|
||||
analysed = false
|
||||
analysed = false,
|
||||
drawOffers = GameDrawOffers.empty
|
||||
)
|
||||
|
||||
object BSONFields {
|
||||
|
@ -800,6 +800,7 @@ object Game {
|
|||
val initialFen = "if"
|
||||
val checkAt = "ck"
|
||||
val perfType = "pt" // only set on student games for aggregation
|
||||
val drawOffers = "do"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -96,11 +96,11 @@ object GameDiff {
|
|||
BSONHandlers.clockBSONWrite(a.createdAt, c).toOption
|
||||
}
|
||||
)
|
||||
dTry(drawOffers, _.drawOffers, BSONHandlers.gameDrawOffersHandler.writeTry)
|
||||
for (i <- 0 to 1) {
|
||||
import Player.BSONFields._
|
||||
val name = s"p$i."
|
||||
val player: Game => Player = if (i == 0) (_.whitePlayer) else (_.blackPlayer)
|
||||
dOpt(s"$name$lastDrawOffer", player(_).lastDrawOffer, (l: Option[Int]) => l flatMap w.intO)
|
||||
dOpt(s"$name$isOfferingDraw", player(_).isOfferingDraw, w.boolO)
|
||||
dOpt(s"$name$proposeTakebackAt", player(_).proposeTakebackAt, w.intO)
|
||||
dTry(s"$name$blursBits", player(_).blurs, Blurs.BlursBSONHandler.writeTry)
|
||||
|
|
|
@ -327,8 +327,6 @@ final class GameRepo(val coll: Coll)(implicit ec: scala.concurrent.ExecutionCont
|
|||
F.positionHashes -> true,
|
||||
F.playingUids -> true,
|
||||
F.unmovedRooks -> true,
|
||||
("p0." + Player.BSONFields.lastDrawOffer) -> true,
|
||||
("p1." + Player.BSONFields.lastDrawOffer) -> true,
|
||||
("p0." + Player.BSONFields.isOfferingDraw) -> true,
|
||||
("p1." + Player.BSONFields.isOfferingDraw) -> true,
|
||||
("p0." + Player.BSONFields.proposeTakebackAt) -> true,
|
||||
|
|
|
@ -2,6 +2,7 @@ package lila.game
|
|||
|
||||
import java.security.MessageDigest
|
||||
import lila.db.ByteArray
|
||||
import chess.Color
|
||||
|
||||
private[game] case class Metadata(
|
||||
source: Option[Source],
|
||||
|
@ -9,7 +10,8 @@ private[game] case class Metadata(
|
|||
tournamentId: Option[String],
|
||||
swissId: Option[String],
|
||||
simulId: Option[String],
|
||||
analysed: Boolean
|
||||
analysed: Boolean,
|
||||
drawOffers: GameDrawOffers
|
||||
) {
|
||||
|
||||
def pgnDate = pgnImport flatMap (_.date)
|
||||
|
@ -21,7 +23,20 @@ private[game] case class Metadata(
|
|||
|
||||
private[game] object Metadata {
|
||||
|
||||
val empty = Metadata(None, None, None, None, None, analysed = false)
|
||||
val empty = Metadata(None, None, None, None, None, analysed = false, GameDrawOffers.empty)
|
||||
}
|
||||
|
||||
// plies
|
||||
case class GameDrawOffers(white: Set[Int], black: Set[Int]) {
|
||||
|
||||
def lastBy(color: Color): Option[Int] = color.fold(white, black).maxOption
|
||||
|
||||
def add(color: Color, ply: Int) =
|
||||
color.fold(copy(white = white incl ply), copy(black = black incl ply))
|
||||
}
|
||||
|
||||
object GameDrawOffers {
|
||||
val empty = GameDrawOffers(Set.empty, Set.empty)
|
||||
}
|
||||
|
||||
case class PgnImport(
|
||||
|
|
|
@ -14,7 +14,6 @@ case class Player(
|
|||
aiLevel: Option[Int],
|
||||
isWinner: Option[Boolean] = None,
|
||||
isOfferingDraw: Boolean = false,
|
||||
lastDrawOffer: Option[Int] = None,
|
||||
proposeTakebackAt: Int = 0, // ply when takeback was proposed
|
||||
userId: Player.UserId = None,
|
||||
rating: Option[Int] = None,
|
||||
|
@ -49,11 +48,7 @@ case class Player(
|
|||
|
||||
def finish(winner: Boolean) = copy(isWinner = winner option true)
|
||||
|
||||
def offerDraw(turn: Int) =
|
||||
copy(
|
||||
isOfferingDraw = true,
|
||||
lastDrawOffer = Some(turn)
|
||||
)
|
||||
def offerDraw = copy(isOfferingDraw = true)
|
||||
|
||||
def removeDrawOffer = copy(isOfferingDraw = false)
|
||||
|
||||
|
@ -165,7 +160,6 @@ object Player {
|
|||
|
||||
val aiLevel = "ai"
|
||||
val isOfferingDraw = "od"
|
||||
val lastDrawOffer = "ld"
|
||||
val proposeTakebackAt = "ta"
|
||||
val rating = "e"
|
||||
val ratingDiff = "d"
|
||||
|
@ -206,7 +200,6 @@ object Player {
|
|||
aiLevel = r intO aiLevel,
|
||||
isWinner = win,
|
||||
isOfferingDraw = r boolD isOfferingDraw,
|
||||
lastDrawOffer = r intO lastDrawOffer,
|
||||
proposeTakebackAt = r intD proposeTakebackAt,
|
||||
userId = userId,
|
||||
rating = r intO rating flatMap ratingRange,
|
||||
|
@ -222,7 +215,6 @@ object Player {
|
|||
BSONDocument(
|
||||
aiLevel -> p.aiLevel,
|
||||
isOfferingDraw -> w.boolO(p.isOfferingDraw),
|
||||
lastDrawOffer -> p.lastDrawOffer,
|
||||
proposeTakebackAt -> w.intO(p.proposeTakebackAt),
|
||||
rating -> p.rating,
|
||||
ratingDiff -> p.ratingDiff,
|
||||
|
|
|
@ -41,9 +41,7 @@ final private[round] class Drawer(
|
|||
case Pov(g, color) if g playerCanOfferDraw color =>
|
||||
proxy.save {
|
||||
messenger.system(g, color.fold(trans.whiteOffersDraw, trans.blackOffersDraw).txt())
|
||||
Progress(g) map { g =>
|
||||
g.updatePlayer(color, _ offerDraw g.turns)
|
||||
}
|
||||
Progress(g) map { _ offerDraw color }
|
||||
} >>- publishDrawOffer(pov) inject List(Event.DrawOffer(by = color.some))
|
||||
case _ => fuccess(List(Event.ReloadOwner))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue