fix TCEC broadcasts (support for reusable mono-game URL) - closes #3690

pull/3701/head
Thibault Duplessis 2017-10-14 22:52:43 -05:00
parent 06aa3a60ad
commit 33992c4815
6 changed files with 29 additions and 14 deletions

View File

@ -13,7 +13,7 @@ fs.readdir(dir).then(list => {
});
function serveIndex(index) {
if (!files[index]) return 'Done';
if (!files[index]) index = 0;
const percent = Math.floor(index * 100 / files.length);
if (percent > completion) {
completion = percent;

View File

@ -89,17 +89,17 @@ private final class RelayFetch(
def finishRelay(r: Relay, nbMoves: Int, games: RelayGames): Fu[Option[Relay]] =
if (nbMoves > 0) fuccess(none)
else if (games.forall(!_.started)) fuccess(none)
else if (games.size == 1) fuccess(none) // probably TCEC style where single file/URL is used for many games in a row
else chapterRepo.relaysAndTagsByStudyId(r.studyId) map { chapters =>
games.forall { game =>
chapters.find(c => game is c._1) ?? {
case (chapterRelay, tags) =>
tags.resultColor.isDefined ||
game.end.isDefined ||
chapterRelay.lastMoveAt.isBefore {
DateTime.now.minusMinutes {
tags.clockConfig.fold(60)(_.limitInMinutes.toInt atLeast 30 atMost 120)
}
chapters.find(_.relay.index == game.index) ?? { chapter =>
chapter.tags.resultColor.isDefined ||
game.end.isDefined ||
chapter.relay.lastMoveAt.isBefore {
DateTime.now.minusMinutes {
chapter.tags.clockConfig.fold(60)(_.limitInMinutes.toInt atLeast 30 atMost 120)
}
}
}
} option r.setFinished
}

View File

@ -10,8 +10,9 @@ case class RelayGame(
end: Option[PgnImport.End]
) {
def is(c: Chapter): Boolean = c.relay ?? is
def is(r: Chapter.Relay): Boolean = r.index == index
def staticTagsMatch(chapterTags: Tags) = List("white", "black", "round", "event") forall { name =>
chapterTags(name) == tags(name)
}
def started = root.children.nodes.nonEmpty

View File

@ -19,7 +19,7 @@ private final class RelaySync(
studyApi byId relay.studyId flatten "Missing relay study!" flatMap { study =>
chapterRepo orderedByStudy study.id flatMap { chapters =>
lila.common.Future.traverseSequentially(games) { game =>
chapters.find(game.is) match {
findCorrespondingChapter(game, chapters, games.size) match {
case Some(chapter) => updateChapter(study, chapter, game)
case None => createChapter(study, game) flatMap { chapter =>
chapters.find(_.isEmptyInitial).ifTrue(chapter.order == 2).?? { initial =>
@ -31,6 +31,16 @@ private final class RelaySync(
}
}
/*
* If the source contains several games, use their index to match them with the study chapter.
* If the source contains only one game, use the player tags to match with the study chapter.
* So the TCEC style - one game per file, reusing the file for all games - is supported.
* lichess will create a new chapter when the game player tags differ.
*/
private def findCorrespondingChapter(game: RelayGame, chapters: List[Chapter], nbGames: Int): Option[Chapter] =
if (nbGames == 1) chapters.find(c => game staticTagsMatch c.tags)
else chapters.find(_.relay.exists(_.index == game.index))
private def updateChapter(study: Study, chapter: Chapter, game: RelayGame): Fu[NbMoves] =
updateChapterTags(study, chapter, game) >>
updateChapterTree(study, chapter, game)

View File

@ -80,6 +80,8 @@ case class Chapter(
def isConceal = conceal.isDefined
def withoutChildren = copy(root = root.withoutChildren)
def relayAndTags = relay map { Chapter.RelayAndTags(_, tags) }
}
object Chapter {
@ -116,6 +118,8 @@ object Chapter {
def secondsSinceLastMove: Int = (nowSeconds - lastMoveAt.getSeconds).toInt
}
case class RelayAndTags(relay: Relay, tags: Tags)
case class Metadata(
_id: Chapter.Id,
name: Chapter.Name,

View File

@ -43,13 +43,13 @@ final class ChapterRepo(coll: Coll) {
.cursor[Chapter](readPreference = ReadPreference.secondaryPreferred)
.gather[List](maxChapters)
def relaysAndTagsByStudyId(studyId: Study.Id): Fu[List[(Chapter.Relay, Tags)]] =
def relaysAndTagsByStudyId(studyId: Study.Id): Fu[List[Chapter.RelayAndTags]] =
coll.find($doc("studyId" -> studyId), $doc("relay" -> true, "tags" -> true)).list[Bdoc]() map { docs =>
for {
doc <- docs
relay <- doc.getAs[Chapter.Relay]("relay")
tags <- doc.getAs[Tags]("tags")
} yield (relay, tags)
} yield Chapter.RelayAndTags(relay, tags)
}
def sort(study: Study, ids: List[Chapter.Id]): Funit = ids.zipWithIndex.map {