Skip to content

Commit

Permalink
provide definitions of metrics and dimensions
Browse files Browse the repository at this point in the history
  • Loading branch information
ornicar committed Nov 28, 2015
1 parent 56f0a58 commit 30b0cc8
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 37 deletions.
25 changes: 17 additions & 8 deletions modules/insight/src/main/Dimension.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package lila.insight

import reactivemongo.bson._
import play.twirl.api.Html

import chess.{ Color, Role }
import lila.db.Types._
Expand All @@ -11,7 +12,8 @@ sealed abstract class Dimension[A: BSONValueHandler](
val name: String,
val dbKey: String,
val position: Position,
val valueName: A => String) {
val valueName: A => String,
val description: Html) {

implicit def bson = implicitly[BSONValueHandler[A]]

Expand All @@ -25,25 +27,32 @@ object Dimension {
import Position._

case object Perf extends Dimension[PerfType](
"perf", "Variant", "perf", Game, _.name)
"perf", "Variant", "perf", Game, _.name,
Html("The rating category of the game, like Bullet, Blitz, or Chess960."))

case object Phase extends Dimension[Phase](
"phase", "Game phase", "moves.p", Move, _.name)
"phase", "Game phase", "moves.p", Move, _.name,
Html("The portion of the game: Opening, Middlegame, or Endgame."))

case object Result extends Dimension[Result](
"result", "Result", "result", Game, _.name)
"result", "Game result", "result", Game, _.name,
Html("Whether you won, lost, or drew the game."))

case object Color extends Dimension[Color](
"color", "Color", "color", Game, _.toString)
"color", "Color", "color", Game, _.toString,
Html("The side you are playing: White or Black."))

case object Opening extends Dimension[Ecopening](
"opening", "Opening", "eco", Game, _.ecoName)
"opening", "Opening", "eco", Game, _.ecoName,
Html("ECO identification of the initial moves, like \"A58 Benko Gambit\"."))

case object OpponentStrength extends Dimension[RelativeStrength](
"opponentStrength", "Opponent strength", "opponent.strength", Game, _.name)
"opponentStrength", "Opponent strength", "opponent.strength", Game, _.name,
Html("Rating of your opponent compared to yours. Much weaker:-250, Weaker:-100, Stronger:+100, Much stronger:+250."))

case object PieceRole extends Dimension[Role](
"pieceRole", "Piece moved", "moves.r", Move, _.toString)
"pieceRole", "Piece moved", "moves.r", Move, _.toString,
Html("The type of piece you move."))

// case object Castling extends Dimension[Castling](
// "castling", "Castling side", "moves.c", Move, _.name)
Expand Down
4 changes: 2 additions & 2 deletions modules/insight/src/main/Entry.scala
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,10 @@ object RelativeStrength {
val all = List(MuchWeaker, Weaker, Equal, Stronger, MuchStronger)
val byId = all map { p => (p.id, p) } toMap
def apply(diff: Int) = diff match {
case d if d < -300 => MuchWeaker
case d if d < -250 => MuchWeaker
case d if d < -100 => Weaker
case d if d > 100 => Stronger
case d if d > 300 => MuchStronger
case d if d > 250 => MuchStronger
case _ => Equal
}
}
2 changes: 2 additions & 0 deletions modules/insight/src/main/JsonView.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ final class JsonView {
"key" -> d.key,
"name" -> d.name,
"position" -> d.position,
"description" -> d.description.body,
"values" -> Dimension.valuesOf(d).map(Dimension.valueToJson(d)))
}

private implicit def metricWriter: OWrites[Metric] = OWrites { m =>
Json.obj(
"key" -> m.key,
"name" -> m.name,
"description" -> m.description.body,
"position" -> m.position)
}

Expand Down
28 changes: 19 additions & 9 deletions modules/insight/src/main/Metric.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package lila.insight

import play.twirl.api.Html
import reactivemongo.bson._

sealed abstract class Metric(
val key: String,
val name: String,
val position: Position,
val per: Position,
val dataType: Metric.DataType)
val dataType: Metric.DataType,
val description: Html)

object Metric {

Expand All @@ -25,21 +27,29 @@ object Metric {
import DataType._
import Position._

case object MeanCpl extends Metric("meanCpl", "Average centipawn loss", Move, Move, Average)
case object MeanCpl extends Metric("meanCpl", "Average centipawn loss", Move, Move, Average,
Html("""Precision of your moves. Lower is better. <a href="http://lichess.org/qa/103/what-is-average-centipawn-loss">More info</a>"""))

case object Movetime extends Metric("movetime", "Move time", Move, Move, Seconds)
case object Movetime extends Metric("movetime", "Move time", Move, Move, Seconds,
Html("Time you spend thinking on each move, in seconds."))

case object Result extends Metric("result", "Result", Game, Game, Percent)
case object Result extends Metric("result", "Game result", Game, Game, Percent,
Dimension.Result.description)

case object Termination extends Metric("termination", "Termination", Game, Game, Percent)
case object Termination extends Metric("termination", "Termination", Game, Game, Percent,
Html("The way the game ended, like Checkmate or Resignation."))

case object RatingDiff extends Metric("ratingDiff", "Rating gain", Game, Game, Average)
case object RatingDiff extends Metric("ratingDiff", "Rating gain", Game, Game, Average,
Html("The rating points you win or lose when the game ends."))

case object OpponentRating extends Metric("opponentRating", "Opponent rating", Game, Game, Average)
case object OpponentRating extends Metric("opponentRating", "Opponent rating", Game, Game, Average,
Html("Rating of your opponent for the relevant game category."))

case object NbMoves extends Metric("nbMoves", "Moves per game", Move, Game, Count)
case object NbMoves extends Metric("nbMoves", "Moves per game", Move, Game, Count,
Html("Number of moves you play in the game. Doesn't count the opponent moves."))

case object PieceRole extends Metric("pieceRole", "Piece moved", Move, Move, Percent)
case object PieceRole extends Metric("pieceRole", "Piece moved", Move, Move, Percent,
Dimension.PieceRole.description)

val all = List(MeanCpl, Movetime, Result, Termination, RatingDiff, OpponentRating, NbMoves, PieceRole)
val byKey = all map { p => (p.key, p) } toMap
Expand Down
31 changes: 20 additions & 11 deletions public/stylesheets/insight.css
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@
}
#insight .filters .ms-choice {
padding: 20px 10px;
border-width: 1px 1px 0 1px;
border-width: 0 1px 1px 0;
background: #e0e0e0;
transition: background 0.13s;
}
#insight .filters .ms-parent:last-child .ms-choice {
border-width: 1px;
border-bottom: 0;
}
#insight .filters .ms-parent:hover .ms-choice,
#insight .filters .ms-parent.selected .ms-choice {
Expand Down Expand Up @@ -126,24 +126,33 @@
background: #f0f0f0;
}

#insight .filters p {
padding: 5px;
text-transform: uppercase;
border: 1px solid #ccc;
border-bottom: 0;
background: linear-gradient(to bottom, rgba(245, 245, 245, 1) 0%, rgba(240, 240, 240, 1) 100%);
}

#insight .info.box {
margin-bottom: 20px;
}
#insight .info.box .content {
#insight .box .content {
padding: 7px;
}
#insight .box .top {
text-transform: uppercase;
}
#insight .info.box .insight-stale button {
width: 100%;
}

#insight .help.box {
margin-top: 20px;
}
#insight .help .dimension {
margin-top: 10px;
}
#insight .help h3 {
margin: 0;
font-weight: bold;
}
#insight .help a {
text-decoration: underline;
}

#insight table {
border: 1px solid #d4d4d4;
}
Expand Down
6 changes: 3 additions & 3 deletions ui/insight/src/chart.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ function makeChart(el, data) {
xAxis: {
categories: data.xAxis.categories,
crosshair: true,
labels: {
rotation: -30
}
// labels: {
// rotation: -30
// }
},
yAxis: [data.valueYaxis, data.sizeYaxis].map(function(a, i) {
return {
Expand Down
6 changes: 3 additions & 3 deletions ui/insight/src/filters.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
var m = require('mithril');

module.exports = function(ctrl) {
return m('div.filters', [
m('p', 'Filter results'),
return m('div.filters.box', [
m('div.top', 'Filter results'),
ctrl.ui.dimensions.map(function(dimension) {
return m('select', {
multiple: true,
config: function(e, isUpdate) {
if (isUpdate) return;
$(e).multipleSelect({
placeholder: dimension.name,
width: '240px',
width: '239px',
selectAll: false,
filter: dimension.key === 'opening',
// single: dimension.key === 'color',
Expand Down
14 changes: 14 additions & 0 deletions ui/insight/src/help.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
var m = require('mithril');

module.exports = function(ctrl) {
return m('div.help.box', [
m('div.top', 'Definitions'),
m('div.content', ['metric', 'dimension'].map(function(type) {
var data = ctrl.vm[type];
return m('section.' + type, [
m('h3', data.name),
m('p', m.trust(data.description))
]);
}))
]);
};
4 changes: 3 additions & 1 deletion ui/insight/src/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ var axis = require('./axis');
var filters = require('./filters');
var chart = require('./chart');
var table = require('./table');
var help = require('./help');

module.exports = function(ctrl) {
return m('div', {
Expand All @@ -11,7 +12,7 @@ module.exports = function(ctrl) {
m('div.left', [
m('div.info.box', [
m('div.top', [
m('a.username', {
m('a.username.user_link.ulpt', {
href: '/@/' + ctrl.user.name
}, ctrl.user.name)
]),
Expand All @@ -30,6 +31,7 @@ module.exports = function(ctrl) {
])
]),
filters(ctrl),
help(ctrl)
]),
m('header', [
axis(ctrl),
Expand Down

0 comments on commit 30b0cc8

Please sign in to comment.