Skip to content

Commit

Permalink
better global integration of chess glyphs
Browse files Browse the repository at this point in the history
  • Loading branch information
ornicar committed May 10, 2016
1 parent e7c2b7f commit a165bb5
Show file tree
Hide file tree
Showing 12 changed files with 65 additions and 72 deletions.
13 changes: 6 additions & 7 deletions app/templating/AnalysisHelper.scala
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
package lila.app
package templating

import chess.format.Nag
import lila.analyse.Advice.Judgment
import play.api.data._
import play.twirl.api.Html

import lila.api.Context

trait AnalysisHelper { self: I18nHelper with SecurityHelper =>

def nagName(nag: Nag)(implicit ctx: Context) = nag match {
case Nag.Blunder => trans.blunders()
case Nag.Mistake => trans.mistakes()
case Nag.Inaccuracy => trans.inaccuracies()
case nag => nag.toString
def judgmentName(judgment: Judgment)(implicit ctx: Context) = judgment match {
case Judgment.Blunder => trans.blunders()
case Judgment.Mistake => trans.mistakes()
case Judgment.Inaccuracy => trans.inaccuracies()
case judgment => judgment.toString
}
}
6 changes: 3 additions & 3 deletions app/views/analyse/replay.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@
</tr>
</thead>
<tbody>
@for((nag, nb) <- pairs) {
<tr @if(nb > 0) {class="nag" data-color="@color.name" data-nag="@nag.symbol"}>
@for((judgment, nb) <- pairs) {
<tr @if(nb > 0) {class="nag" data-color="@color.name" data-nag="@judgment.glyph.symbol"}>
<td><strong>@nb</strong></td>
<th>@nagName(nag)</th>
<th>@judgmentName(judgment)</th>
</tr>
}
<tr>
Expand Down
4 changes: 2 additions & 2 deletions app/views/analyse/replayBot.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ <h1>@titleGame(pov.game)</h1>
</tr>
</thead>
<tbody>
@for((nag, nb) <- pairs) {
@for((judgment, nb) <- pairs) {
<tr>
<td><strong>@nb</strong></td>
<th>@nagName(nag)</th>
<th>@judgmentName(judgment)</th>
</tr>
}
<tr>
Expand Down
72 changes: 33 additions & 39 deletions modules/analyse/src/main/Advice.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package lila.analyse

import chess.format.Nag
import chess.format.pgn.Glyph

sealed trait Advice {
def nag: Nag
def judgment: Advice.Judgment
def info: Info
def prev: Info

Expand All @@ -17,7 +17,7 @@ sealed trait Advice {
withEval.??(evalComment ?? { c => s"($c) " }) +
(this match {
case MateAdvice(seq, _, _, _) => seq.desc
case CpAdvice(nag, _, _) => nag.toString
case CpAdvice(judgment, _, _) => judgment.toString
}) + "." + {
withBestMove ?? {
info.variation.headOption ?? { move => s" Best move was $move." }
Expand All @@ -29,47 +29,40 @@ sealed trait Advice {
}.some filter (_.nonEmpty)
}

private[analyse] object Advice {
object Advice {

sealed abstract class Judgment(val glyph: Glyph, val name: String) {
override def toString = name
def isBlunder = this == Judgment.Blunder
}
object Judgment {
object Inaccuracy extends Judgment(Glyph.MoveAssessment.questionable, "Inaccuracy")
object Mistake extends Judgment(Glyph.MoveAssessment.mistake, "Mistake")
object Blunder extends Judgment(Glyph.MoveAssessment.blunder, "Blunder")
val all = List(Inaccuracy, Mistake, Blunder)
}

def apply(prev: Info, info: Info): Option[Advice] = CpAdvice(prev, info) orElse MateAdvice(prev, info)
}

private[analyse] case class CpAdvice(
nag: Nag,
judgment: Advice.Judgment,
info: Info,
prev: Info) extends Advice

private[analyse] object CpAdvice {

// private val cpNags = List(
// 0.20 -> Nag.Blunder,
// 0.10 -> Nag.Mistake,
// 0.05 -> Nag.Inaccuracy)

// def apply(prev: Info, info: Info): Option[CpAdvice] = for {
// cp ← prev.score map (_.ceiled.centipawns)
// infoCp ← info.score map (_.ceiled.centipawns)
// a = -0.002409
// b = 1.001726
// c = 0.006963
// d = 2.386803
// before = a + (b-a)/(1 + math.exp(-c * (cp - d)));
// after = a + (b-a)/(1 + math.exp(-c * (infoCp - d)));
// delta = (after - before) |> { d => info.color.fold(-d, d) }
// nag ← cpNags find { case (d, n) => d <= delta } map (_._2)
// } yield CpAdvice(nag, info, prev)

private val cpNags = List(
300 -> Nag.Blunder,
100 -> Nag.Mistake,
50 -> Nag.Inaccuracy)
private val cpJudgments = List(
300 -> Advice.Judgment.Blunder,
100 -> Advice.Judgment.Mistake,
50 -> Advice.Judgment.Inaccuracy)

def apply(prev: Info, info: Info): Option[CpAdvice] = for {
cp prev.score map (_.ceiled.centipawns)
infoCp info.score map (_.ceiled.centipawns)
delta = (infoCp - cp) |> { d => info.color.fold(-d, d) }
nag cpNags find { case (d, n) => d <= delta } map (_._2)
} yield CpAdvice(nag, info, prev)
judgment cpJudgments find { case (d, n) => d <= delta } map (_._2)
} yield CpAdvice(judgment, info, prev)
}

private[analyse] sealed abstract class MateSequence(val desc: String)
Expand All @@ -91,7 +84,7 @@ private[analyse] object MateSequence {
}
private[analyse] case class MateAdvice(
sequence: MateSequence,
nag: Nag,
judgment: Advice.Judgment,
info: Info,
prev: Info) extends Advice
private[analyse] object MateAdvice {
Expand All @@ -101,16 +94,17 @@ private[analyse] object MateAdvice {
def prevScore = reverse(prev.score ?? (_.centipawns))
def nextScore = reverse(info.score ?? (_.centipawns))
MateSequence(prev.mate map reverse, info.mate map reverse) map { sequence =>
val nag = sequence match {
case MateCreated if prevScore < -999 => Nag.Inaccuracy
case MateCreated if prevScore < -700 => Nag.Mistake
case MateCreated => Nag.Blunder
case MateLost if nextScore > 999 => Nag.Inaccuracy
case MateLost if nextScore > 700 => Nag.Mistake
case MateLost => Nag.Blunder
case MateDelayed => Nag.Inaccuracy
import Advice.Judgment._
val judgment = sequence match {
case MateCreated if prevScore < -999 => Inaccuracy
case MateCreated if prevScore < -700 => Mistake
case MateCreated => Blunder
case MateLost if nextScore > 999 => Inaccuracy
case MateLost if nextScore > 700 => Mistake
case MateLost => Blunder
case MateDelayed => Inaccuracy
}
MateAdvice(sequence, nag, info, prev)
MateAdvice(sequence, judgment, info, prev)
}
}
}
9 changes: 4 additions & 5 deletions modules/analyse/src/main/Analysis.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package lila.analyse

import chess.Color
import chess.format.Nag

import org.joda.time.DateTime

Expand Down Expand Up @@ -34,10 +33,10 @@ case class Analysis(
i.best map { b => i.ply -> b.keys }
}.toMap

def summary: List[(Color, List[(Nag, Int)])] = Color.all map { color =>
color -> (Nag.badOnes map { nag =>
nag -> (advices count { adv =>
adv.color == color && adv.nag == nag
def summary: List[(Color, List[(Advice.Judgment, Int)])] = Color.all map { color =>
color -> (Advice.Judgment.all map { judgment =>
judgment -> (advices count { adv =>
adv.color == color && adv.judgment == judgment
})
})
}
Expand Down
4 changes: 2 additions & 2 deletions modules/analyse/src/main/Annotator.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package lila.analyse

import chess.format.pgn.{ Pgn, Tag, Turn, Move }
import chess.format.pgn.{ Pgn, Tag, Turn, Move, Glyphs }
import chess.opening._
import chess.{ Status, Color, Clock }

Expand Down Expand Up @@ -53,7 +53,7 @@ private[analyse] final class Annotator(netDomain: String) {
case (pgn, advice) => pgn.updateTurn(advice.turn, turn =>
turn.update(advice.color, move =>
move.copy(
nag = advice.nag.code.some,
glyphs = Glyphs.fromList(advice.judgment.glyph :: Nil),
comments = List(advice.makeComment(true, true)),
variations = makeVariation(turn, advice) :: Nil
)
Expand Down
2 changes: 1 addition & 1 deletion modules/chess
Submodule chess updated from 8f9c27 to 648cb4
13 changes: 6 additions & 7 deletions modules/insight/src/main/PovToEntry.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package lila.insight

import chess.format.Nag
import chess.{ Role, Board }
import lila.analyse.{ Accuracy, Advice }
import lila.game.{ Game, Pov, GameRepo }
Expand Down Expand Up @@ -91,16 +90,16 @@ object PovToEntry {
val ply = i * 2 + from.pov.color.fold(1, 2)
val prevInfo = prevInfos lift i
val opportunism = from.advices.get(ply - 1) flatMap {
case o if o.nag == Nag.Blunder => from.advices get ply match {
case Some(p) if p.nag == Nag.Blunder => false.some
case _ => true.some
case o if o.judgment.isBlunder => from.advices get ply match {
case Some(p) if p.judgment.isBlunder => false.some
case _ => true.some
}
case _ => none
}
val luck = from.advices.get(ply) flatMap {
case o if o.nag == Nag.Blunder => from.advices.get(ply + 1) match {
case Some(p) if p.nag == Nag.Blunder => true.some
case _ => false.some
case o if o.judgment.isBlunder => from.advices.get(ply + 1) match {
case Some(p) if p.judgment.isBlunder => true.some
case _ => false.some
}
case _ => none
}
Expand Down
4 changes: 2 additions & 2 deletions modules/round/src/main/TreeBuilder.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package lila.round

import chess.format.pgn.Pgn
import chess.format.pgn.{ Pgn, Glyphs }
import chess.format.{ Forsyth, Uci, UciCharPair }
import chess.opening._
import chess.variant.Variant
Expand Down Expand Up @@ -69,7 +69,7 @@ object TreeBuilder {
opening = openingOf(fen),
crazyData = g.situation.board.crazyData,
eval = info map makeEval,
nag = advice.map(_.nag.symbol),
glyphs = Glyphs.fromList(advice.map(_.judgment.glyph).toList),
comments = Node.Comments {
advice.map(_.makeComment(false, true)).toList.map(Node.Comment.byLichess)
})
Expand Down
2 changes: 1 addition & 1 deletion modules/study/src/main/PgnDump.scala
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ final class PgnDump(

private def node2move(parent: RootOrNode, node: Node) = chessPgn.Move(
san = node.move.san,
nag = none,
glyphs = node.glyphs,
comments = node.comments.list.map(_.text),
opening = none,
result = none,
Expand Down
6 changes: 4 additions & 2 deletions public/stylesheets/analyse.css
Original file line number Diff line number Diff line change
Expand Up @@ -553,8 +553,6 @@ body.dark .explorer_box .black {
text-align: center;
}
.lichess_ground .replay move {
min-width: 40%;
display: inline-block;
font-family: 'ChessSansPiratf', sans-serif;
white-space: nowrap;
overflow: hidden;
Expand All @@ -563,6 +561,9 @@ body.dark .explorer_box .black {
position: relative;
padding: 2px 7px;
}
.lichess_ground .replay turn > move {
min-width: 40%;
}
.lichess_ground .replay move.current {
background: rgba(191, 231, 255, 0.7);
}
Expand All @@ -585,6 +586,7 @@ body.dark .explorer_box .black {
.lichess_ground .replay glyph {
font-family: 'Noto Sans';
color: #444;
margin-left: 3px;
}
.lichess_ground .replay .meta {
background-color: #e0e0e0;
Expand Down
2 changes: 1 addition & 1 deletion ui/analyse/src/tree/treeView.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function renderMove(ctrl, node, path, isMainline) {
defined(eval.mate) ? renderEvalTag('#' + eval.mate) : null
),
node.san[0] === 'P' ? node.san.slice(1) : node.san,
node.glyphs ? [' ', renderGlyphs(node.glyphs)] : null
node.glyphs ? renderGlyphs(node.glyphs) : null
]
};
}
Expand Down

0 comments on commit a165bb5

Please sign in to comment.