Skip to content

Commit

Permalink
parse broadcast time control and use increment in %emt computations
Browse files Browse the repository at this point in the history
  • Loading branch information
ornicar committed Dec 29, 2024
1 parent 961701d commit 96189f0
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 24 deletions.
6 changes: 3 additions & 3 deletions modules/relay/src/main/RelayFetch.scala
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,10 @@ final private class RelayFetch(
sliced = RelayGame.Slices.filter(~rt.round.sync.slices)(filtered)
limited = sliced.take(RelayFetch.maxChaptersToShow.value)
withPlayers <- playerEnrich.enrichAndReportAmbiguous(rt)(limited)
enriched <- fidePlayers.enrichGames(rt.tour)(withPlayers)
withTeams = rt.tour.teams.fold(enriched)(_.update(enriched))
withFide <- fidePlayers.enrichGames(rt.tour)(withPlayers)
enriched = rt.tour.enrichGames(withFide)
res <- sync
.updateStudyChapters(rt, withTeams)
.updateStudyChapters(rt, enriched)
.withTimeoutError(7 seconds, SyncResult.Timeout)
.mon(_.relay.syncTime(rt.tour.official, rt.tour.id, rt.tour.slug))
games = res.plan.input.games
Expand Down
2 changes: 1 addition & 1 deletion modules/relay/src/main/RelayPush.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ final class RelayPush(
for
withPlayers <- playerEnrich.enrichAndReportAmbiguous(rt)(rawGames)
enriched <- fidePlayers.enrichGames(rt.tour)(withPlayers)
games = rt.tour.teams.fold(enriched)(_.update(enriched))
games = rt.tour.enrichGames(enriched)
event <- sync
.updateStudyChapters(rt, games)
.map: res =>
Expand Down
13 changes: 11 additions & 2 deletions modules/relay/src/main/RelayTour.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import lila.core.id.ImageId
import lila.core.misc.PicfitUrl
import lila.core.fide.FideTC
import lila.core.study.Visibility
import chess.TournamentClock
import chess.format.pgn.Tag

case class RelayTour(
@Key("_id") id: RelayTourId,
Expand Down Expand Up @@ -52,6 +54,12 @@ case class RelayTour(
then Visibility.`private`
else Visibility.public

def enrichGames(games: RelayGames): RelayGames =
val withTeams = teams.fold(games)(_.update(games))
info.clock.fold(withTeams): clock =>
val tag = Tag.timeControl(clock)
withTeams.map(g => g.copy(tags = g.tags + tag))

object RelayTour:

val maxRelays = Max(64)
Expand Down Expand Up @@ -94,8 +102,9 @@ object RelayTour:
):
def nonEmpty = List(format, tc, fideTc, location, players, website, standings).flatten.nonEmpty
override def toString = List(format, tc, fideTc, location, players).flatten.mkString(" | ")
lazy val fideTcOrGuess: FideTC = fideTc | FideTC.standard
def timeZoneOrDefault: ZoneId = timeZone | ZoneId.systemDefault
lazy val fideTcOrGuess: FideTC = fideTc | FideTC.standard
def timeZoneOrDefault: ZoneId = timeZone | ZoneId.systemDefault
def clock: Option[TournamentClock] = tc.flatMap(TournamentClock.parse.apply)

case class Dates(start: Instant, end: Option[Instant])

Expand Down
2 changes: 1 addition & 1 deletion modules/relay/src/main/ui/RelayFormUi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ final class RelayFormUi(helpers: Helpers, ui: RelayUi, tourUi: RelayTourUi):
form3.group(
form("info.tc"),
trs.timeControl(),
help = frag(""""Classical" or "Rapid" or "Rapid & Blitz"""").some,
help = frag("""e.g. "15 min + 10 sec" or "15+10"""").some,
half = true
)(form3.input(_)),
form3.group(
Expand Down
2 changes: 1 addition & 1 deletion modules/study/src/main/PgnTags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ object PgnTags:
tags.pipe(filterRelevant(types)).pipe(removeContradictingTermination).pipe(sort)

def setRootClockFromTags(c: Chapter): Option[Chapter] =
c.updateRoot { _.setClockAt(c.tags.clockConfig.map(_.limit), UciPath.root) }.filter(c !=)
c.updateRoot { _.setClockAt(c.tags.timeControl.map(_.limit), UciPath.root) }.filter(c !=)

// clean up tags before exposing them
def cleanUpForPublication(tags: Tags) = tags.copy(
Expand Down
32 changes: 26 additions & 6 deletions modules/study/src/main/StudyPgnImport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,27 @@ package lila.study
import chess.MoveOrDrop.*
import chess.format.pgn.{ Comment as ChessComment, Glyphs, ParsedPgn, PgnNodeData, PgnStr, Tags, Tag }
import chess.format.{ Fen, Uci, UciCharPair }
import chess.{ Centis, ErrorStr, Node as PgnNode, Outcome, Status }
import chess.{ Centis, ErrorStr, Node as PgnNode, Outcome, Status, TournamentClock, Ply }

import lila.core.LightUser
import lila.tree.Node.{ Comment, Comments, Shapes }
import lila.tree.{ Branch, Branches, ImportResult, Root }

object StudyPgnImport:

case class Context(
currentGame: chess.Game,
timeControl: Option[TournamentClock],
currentClock: Option[Centis],
previousClock: Option[Centis]
)

def apply(pgn: PgnStr, contributors: List[LightUser]): Either[ErrorStr, Result] =
lila.tree.parseImport(pgn).map { case ImportResult(game, result, replay, initialFen, parsedPgn) =>
val annotator = findAnnotator(parsedPgn, contributors)

val clock = parsedPgn.tags.clockConfig.map(_.limit)
val timeControl = parsedPgn.tags.timeControl
val clock = timeControl.map(_.limit)
parseComments(parsedPgn.initialPosition.comments, annotator) match
case (shapes, _, _, comments) =>
val root = Root(
Expand All @@ -27,8 +35,8 @@ object StudyPgnImport:
glyphs = Glyphs.empty,
clock = clock,
crazyData = replay.setup.board.crazyData,
children = parsedPgn.tree
.fold(Branches.empty)(makeBranches(Context(replay.setup, clock, clock), _, annotator))
children = parsedPgn.tree.fold(Branches.empty):
makeBranches(Context(replay.setup, timeControl, clock, clock), _, annotator)
)

val end = result.map: res =>
Expand Down Expand Up @@ -133,7 +141,7 @@ object StudyPgnImport:
val sanStr = moveOrDrop.toSanStr
val (shapes, clock, emt, comments) = parseComments(node.value.metas.comments, annotator)
val computedClock = clock
.orElse((context.previousClock, emt).mapN(_ - _))
.orElse(context.previousClock.map(guessNewClockState(_, game.ply, context.timeControl, emt)))
.filter(_ > Centis(0))
Branch(
id = UciCharPair(uci),
Expand All @@ -147,14 +155,26 @@ object StudyPgnImport:
clock = computedClock,
crazyData = game.situation.board.crazyData,
children = node.child.fold(Branches.empty):
makeBranches(Context(game, computedClock, context.currentClock), _, annotator)
makeBranches(
Context(game, context.timeControl, computedClock, context.currentClock),
_,
annotator
)
).some
)
catch
case _: StackOverflowError =>
logger.warn(s"study PgnImport.makeNode StackOverflowError")
None

private def guessNewClockState(
prev: Centis,
ply: Ply,
tc: Option[TournamentClock],
emt: Option[Centis]
): Centis =
prev - ~emt + ~tc.map(_.incrementAtPly(ply))

/*
* Fix bad PGN like this one found on reddit:
* 7. c4 (7. c4 Nf6) (7. c4 dxc4) 7... cxd4
Expand Down
15 changes: 6 additions & 9 deletions modules/study/src/main/StudyPgnImportNew.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,13 @@ import lila.core.LightUser
import lila.tree.Node.{ Comment, Comments }
import lila.tree.{ ImportResult, Metas, NewBranch, NewRoot, NewTree }

case class Context(
currentGame: chess.Game,
currentClock: Option[Centis],
previousClock: Option[Centis]
)

/** This code is still unused, and is now out of sync with the StudyPgnImport it's supposed to replace. Some
* features are missing that are present in StudyPgnImport, such as the ability to replay clock states.
*/
object StudyPgnImportNew:

import StudyPgnImport.Context

case class Result(
root: NewRoot,
variant: chess.variant.Variant,
Expand All @@ -33,8 +29,9 @@ object StudyPgnImportNew:
val annotator = StudyPgnImport.findAnnotator(parsedPgn, contributors)
StudyPgnImport.parseComments(parsedPgn.initialPosition.comments, annotator) match
case (shapes, _, _, comments) =>
val clock = parsedPgn.tags.clockConfig.map(_.limit)
val setup = Context(replay.setup, clock, clock)
val tc = parsedPgn.tags.timeControl
val clock = tc.map(_.limit)
val setup = Context(replay.setup, tc, clock, clock)
val root: NewRoot =
NewRoot(
Metas(
Expand Down Expand Up @@ -124,7 +121,7 @@ object StudyPgnImportNew:
)
)

(Context(game, newBranch.metas.clock, context.currentClock), newBranch.some)
(Context(game, context.timeControl, newBranch.metas.clock, context.currentClock), newBranch.some)
)
.toOption
.match
Expand Down
2 changes: 1 addition & 1 deletion project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ object Dependencies {
}

object chess {
val version = "16.6.0"
val version = "17.0.0"
val core = "org.lichess" %% "scalachess" % version
val testKit = "org.lichess" %% "scalachess-test-kit" % version % Test
val playJson = "org.lichess" %% "scalachess-play-json" % version
Expand Down

0 comments on commit 96189f0

Please sign in to comment.