Skip to content

Commit

Permalink
show check in study multiboard, and checkmate in mini eval gauges
Browse files Browse the repository at this point in the history
  • Loading branch information
ornicar committed Jun 21, 2024
1 parent f154ca6 commit 2e18b68
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 34 deletions.
6 changes: 6 additions & 0 deletions modules/study/src/main/BSONHandlers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -327,15 +327,21 @@ object BSONHandlers:

private val clockPair: BSONHandler[PairOf[Option[Centis]]] = optionPairHandler
given BSONHandler[Chapter.BothClocks] = clockPair.as[Chapter.BothClocks](ByColor.fromPair, _.toPair)
given BSONHandler[Chapter.Check] = quickHandler[Chapter.Check](
{ case BSONString(v) => if v == "#" then Chapter.Check.Mate else Chapter.Check.Check },
v => BSONString(if v == Chapter.Check.Mate then "#" else "+")
)
given BSON[Chapter.LastPosDenorm] with
def reads(r: Reader) = Chapter.LastPosDenorm(
fen = r.getO[Fen.Full]("fen") | Fen.initial,
uci = r.getO[Uci]("uci"),
check = r.getO[Chapter.Check]("check"),
clocks = ~r.getO[Chapter.BothClocks]("clocks")
)
def writes(w: Writer, l: Chapter.LastPosDenorm) = $doc(
"fen" -> l.fen.some.filterNot(Fen.Full.isInitial),
"uci" -> l.uci,
"check" -> l.check,
"clocks" -> l.clocks.some.filter(_.exists(_.isDefined))
)

Expand Down
14 changes: 12 additions & 2 deletions modules/study/src/main/Chapter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ case class Chapter(
val parentNode = parentPath.flatMap(root.nodeAt)
val clockSwap = ByColor(node.clock, parentNode.flatMap(_.clock).orElse(node.clock))
if node.color.black then clockSwap else clockSwap.swap
Chapter.LastPosDenorm(node.fen, node.moveOption.map(_.uci), clocks = clocks)
val uci = node.moveOption.map(_.uci)
val check = node.moveOption
.flatMap(_.san.value.lastOption)
.collect:
case '+' => Chapter.Check.Check
case '#' => Chapter.Check.Mate
Chapter.LastPosDenorm(node.fen, uci, check, clocks)
copy(denorm = newDenorm)

def updateRoot(f: Root => Option[Root]) =
Expand Down Expand Up @@ -104,6 +110,7 @@ case class Chapter(
fen = denorm.fold(Fen.initial)(_.fen),
lastMove = denorm.flatMap(_.uci),
lastMoveAt = relay.map(_.lastMoveAt),
check = denorm.flatMap(_.check),
result = tags.outcome.isDefined.option(tags.outcome)
)

Expand Down Expand Up @@ -149,9 +156,12 @@ object Chapter:

type BothClocks = ByColor[Option[Centis]]

enum Check:
case Check, Mate

/* Last position of the main line.
* Used for chapter previews. */
case class LastPosDenorm(fen: Fen.Full, uci: Option[Uci], clocks: BothClocks)
case class LastPosDenorm(fen: Fen.Full, uci: Option[Uci], check: Option[Check], clocks: BothClocks)

case class IdName(@Key("_id") id: StudyChapterId, name: StudyChapterName)

Expand Down
7 changes: 7 additions & 0 deletions modules/study/src/main/StudyChapterPreview.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ case class ChapterPreview(
fen: Fen.Full,
lastMove: Option[Uci],
lastMoveAt: Option[Instant],
check: Option[Chapter.Check],
/* None = No Result PGN tag, the chapter may not be a game
* Some(None) = Result PGN tag is "*", the game is ongoing
* Some(Some(Outcome)) = Game is over with a result
Expand Down Expand Up @@ -122,6 +123,10 @@ object ChapterPreview:
.add("clock" -> p.clock)
.add("fed" -> p.fideId.flatMap(federations.get))

private given Writes[Chapter.Check] = Writes:
case Chapter.Check.Check => JsString("+")
case Chapter.Check.Mate => JsString("#")

private def writesWithFederations(using Federation.ByFideIds): OWrites[ChapterPreview] = c =>
Json
.obj(
Expand All @@ -132,6 +137,7 @@ object ChapterPreview:
.add("players", c.players.map(_.mapList(playerWithFederations)))
.add("orientation", c.orientation.some.filter(_.black))
.add("lastMove", c.lastMove)
.add("check", c.check)
.add("thinkTime", c.thinkTime)
.add("status", c.result.map(o => Outcome.showResult(o).replace("1/2", "½")))

Expand Down Expand Up @@ -163,5 +169,6 @@ object ChapterPreview:
fen = lastPos.map(_.fen).orElse(doc.getAsOpt[Fen.Full]("rootFen")).getOrElse(Fen.initial),
lastMove = lastPos.flatMap(_.uci),
lastMoveAt = lastMoveAt,
check = lastPos.flatMap(_.check),
result = tags.flatMap(_(_.Result)).map(Outcome.fromResult)
)
2 changes: 0 additions & 2 deletions modules/study/src/main/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,3 @@ export lila.common.extensions.*
export lila.core.study.data.{ StudyName, StudyChapterName }

private val logger = lila.log("study")

private type ChapterMap = Map[lila.study.StudyChapterId, lila.study.Chapter]
1 change: 1 addition & 0 deletions ui/analyse/src/study/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export interface ChapterPreviewBase {
name: string;
status?: StatusStr;
lastMove?: string;
check?: '+' | '#';
}

export interface ChapterPreviewFromServer extends ChapterPreviewBase {
Expand Down
74 changes: 44 additions & 30 deletions ui/analyse/src/study/multiBoard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,13 @@ const renderPlayingToggle = (ctrl: MultiBoardCtrl): MaybeVNode =>
ctrl.trans.noarg('playing'),
]);

const previewToCgConfig = (cp: ChapterPreview): CgConfig => ({
fen: cp.fen,
lastMove: uciToMove(cp.lastMove),
turnColor: fenColor(cp.fen),
check: !!cp.check,
});

const makePreview =
(basePath: string, current: ChapterId, cloudEval?: MultiCloudEval) => (preview: ChapterPreview) => {
const orientation = preview.orientation || 'white';
Expand All @@ -137,11 +144,10 @@ const makePreview =
insert(vnode) {
const el = vnode.elm as HTMLElement;
vnode.data!.cg = site.makeChessground(el, {
...previewToCgConfig(preview),
coordinates: false,
viewOnly: true,
fen: preview.fen,
orientation,
lastMove: uciToMove(preview.lastMove),
drawable: {
enabled: false,
visible: false,
Expand All @@ -151,10 +157,7 @@ const makePreview =
},
postpatch(old, vnode) {
if (old.data!.fen !== preview.fen) {
old.data!.cg?.set({
fen: preview.fen,
lastMove: uciToMove(preview.lastMove),
});
old.data!.cg?.set(previewToCgConfig(preview));
}
vnode.data!.fen = preview.fen;
vnode.data!.cg = old.data!.cg;
Expand All @@ -169,31 +172,42 @@ const makePreview =
};

export const verticalEvalGauge = (chap: ChapterPreview, cloudEval: MultiCloudEval): MaybeVNode =>
h(
'span.mini-game__gauge',
{
attrs: { 'data-id': chap.id },
hook: {
...onInsert(cloudEval.observe),
postpatch(old, vnode) {
const prevNodeCloud: CloudEval | undefined = old.data?.cloud;
const cev = cloudEval.getCloudEval(chap.fen) || prevNodeCloud;
if (cev?.chances != prevNodeCloud?.chances) {
const elm = vnode.elm as HTMLElement;
(elm.firstChild as HTMLElement).style.height = `${Math.round(
((1 - (cev?.chances || 0)) / 2) * 100,
)}%`;
if (cev) {
elm.title = renderScoreAtDepth(cev);
elm.classList.add('mini-game__gauge--set');
}
}
vnode.data!.cloud = cev;
chap.check == '#'
? h(
'span.mini-game__gauge.mini-game__gauge--set',
{ attrs: { 'data-id': chap.id, title: 'Checkmate' } },
[
h('span.mini-game__gauge__black', {
attrs: { style: `height: ${fenColor(chap.fen) == 'white' ? 100 : 0}%` },
}),
h('tick'),
],
)
: h(
'span.mini-game__gauge',
{
attrs: { 'data-id': chap.id },
hook: {
...onInsert(cloudEval.observe),
postpatch(old, vnode) {
const elm = vnode.elm as HTMLElement;
const prevNodeCloud: CloudEval | undefined = old.data?.cloud;
const cev = cloudEval.getCloudEval(chap.fen) || prevNodeCloud;
if (cev?.chances != prevNodeCloud?.chances) {
(elm.firstChild as HTMLElement).style.height = `${Math.round(
((1 - (cev?.chances || 0)) / 2) * 100,
)}%`;
if (cev) {
elm.title = renderScoreAtDepth(cev);
elm.classList.add('mini-game__gauge--set');
}
}
vnode.data!.cloud = cev;
},
},
},
},
},
[h('span.mini-game__gauge__black'), h('tick')],
);
[h('span.mini-game__gauge__black'), h('tick')],
);

const renderUser = (player: ChapterPreviewPlayer): VNode =>
h('span.mini-game__user', [
Expand Down
1 change: 1 addition & 0 deletions ui/analyse/src/study/studyChapters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export default class StudyChaptersCtrl {
if (onRelayPath || !d.relayPath) {
cp.fen = node.fen;
cp.lastMove = node.uci;
cp.check = node.san?.includes('#') ? '#' : node.san?.includes('+') ? '+' : undefined;
}
if (onRelayPath) {
cp.lastMoveAt = Date.now();
Expand Down

0 comments on commit 2e18b68

Please sign in to comment.