implement hold alerts

This commit is contained in:
Thibault Duplessis 2014-03-12 20:35:22 +01:00
parent 6fe17fd9f2
commit d0261cdee3
8 changed files with 73 additions and 1 deletions

View file

@ -72,6 +72,7 @@ themepicker = true) {
<div class="advice_summary">
@round.blurs(game)
@round.holdAlerts(game)
@analysis.filter(_.done).map { a =>
<table>
@for((color, pairs) <- a.summary) {

View file

@ -0,0 +1,12 @@
@(game: Game)(implicit ctx: Context)
@if(isGranted(_.ViewBlurs)) {
@game.players.map { p =>
@p.holdAlert.map { h =>
<div class="player_blurs">
@playerLink(p, cssClass = p.color.name.some) hold alert<br />
(ply: @h.ply, mean: @h.mean ms, SD: @h.sd ms)<br />
</div>
}
}
}

View file

@ -106,6 +106,19 @@ trait GameRepo {
def incBookmarks(id: ID, value: Int) =
$update($select(id), $incBson("bm" -> value))
def setHoldAlert(pov: Pov, mean: Int, sd: Int) = {
import Player.holdAlertBSONHandler
$update(
$select(pov.gameId),
BSONDocument(
"$set" -> BSONDocument(
s"p${pov.color.fold(0, 1)}.${Player.BSONFields.holdAlert}" ->
Player.HoldAlert(ply = pov.game.turns, mean = mean, sd = sd)
)
)
).void
}
def finish(id: ID, winnerColor: Option[Color], winnerId: Option[String]) = $update(
$select(id),
BSONDocument(

View file

@ -17,6 +17,7 @@ case class Player(
rating: Option[Int] = None,
ratingDiff: Option[Int] = None,
blurs: Int = 0,
holdAlert: Option[Player.HoldAlert] = None,
name: Option[String] = None) {
def encodePieces(allPieces: Iterable[(Pos, Piece, Boolean)]): String =
@ -43,6 +44,8 @@ case class Player(
def wins = isWinner getOrElse false
def hasHoldAlert = holdAlert.isDefined
def finish(winner: Boolean) = copy(
isWinner = if (winner) Some(true) else None
)
@ -85,6 +88,11 @@ object Player {
def black = make(Color.Black, None)
case class HoldAlert(ply: Int, mean: Int, sd: Int)
import reactivemongo.bson.Macros
implicit val holdAlertBSONHandler = Macros.handler[HoldAlert]
object BSONFields {
val aiLevel = "ai"
@ -95,6 +103,7 @@ object Player {
val rating = "e"
val ratingDiff = "d"
val blurs = "b"
val holdAlert = "h"
val name = "na"
}
@ -123,6 +132,7 @@ object Player {
rating = r intO rating,
ratingDiff = r intO ratingDiff,
blurs = r intD blurs,
holdAlert = r.getO[HoldAlert](holdAlert),
name = r strO name)
def writes(w: BSON.Writer, o: Builder) =
@ -136,6 +146,7 @@ object Player {
rating -> p.rating,
ratingDiff -> p.ratingDiff,
blurs -> w.intO(p.blurs),
holdAlert -> p.holdAlert,
name -> p.name)
}
}

View file

@ -100,6 +100,13 @@ private[round] final class Round(
}
}
case HoldAlert(playerId, mean, sd) => handle(playerId) { pov =>
!pov.player.hasHoldAlert ?? {
play.api.Logger("round").info(s"Hold alert $pov mean: $mean SD: $sd")
GameRepo.setHoldAlert(pov, mean, sd) inject List[Event]()
}
}
case RematchYes(playerRef) => handle(playerRef)(rematcher.yes)
case RematchNo(playerRef) => handle(playerRef)(rematcher.no)

View file

@ -75,6 +75,11 @@ private[round] final class SocketHandler(
case ("talk", o) => o str "d" foreach { text =>
messenger.owner(gameId, member, text, socket)
}
case ("hold", o) => for {
d o obj "d"
mean d int "mean"
sd d int "sd"
} round(HoldAlert(playerId, mean, sd))
}
}
}

View file

@ -102,4 +102,5 @@ package round {
case object Outoftime
case object Abandon
case class Cheat(color: Color)
case class HoldAlert(playerId: String, mean: Int, sd: Int)
}

View file

@ -854,6 +854,8 @@ var storage = {
self.initialTitle = document.title;
self.hasMovedOnce = false;
self.premove = null;
self.holdStart = null;
self.holds = [];
self.options.tableUrl = self.element.data('table-url');
self.options.endUrl = self.element.data('end-url');
self.options.socketUrl = self.element.data('socket-url');
@ -1306,7 +1308,7 @@ var storage = {
if (self.options.game.finished || self.options.player.spectator) {
return;
}
var draggingKey = null;
var draggingKey;
var dropped = false;
// init squares
self.$board.find("div.lcs").each(function() {
@ -1322,6 +1324,7 @@ var storage = {
},
drop: function(ev, ui) {
self.dropPiece(ui.draggable, ui.draggable.parent(), $(this));
self.addHold();
dropped = true;
},
hoverClass: 'droppable-hover'
@ -1338,6 +1341,7 @@ var storage = {
},
start: function() {
draggingKey = $this.hide().parent().attr('id');
self.holdStart = Date.now();
dropped = false;
self.unselect();
},
@ -1364,6 +1368,7 @@ var storage = {
self.unselect();
if (isSelected) return;
$square.addClass('selected');
self.holdStart = Date.now();
});
});
@ -1394,6 +1399,7 @@ var storage = {
$to.removeClass('selectable');
self.dropPiece($piece, $from, $this);
}
self.addHold();
});
});
@ -1401,6 +1407,22 @@ var storage = {
* End of code for touch screens
*/
},
addHold: function() {
if (this.holdStart) {
var nb = 10;
this.holds.push(Date.now() - this.holdStart);
this.holdStart = null;
if (this.holds.length > nb) {
this.holds.shift();
var mean = this.holds.reduce(function(a, b) { return a + b; }) / nb;
if (mean < 80) {
var diffs = this.holds.map(function(a) { return Math.pow(a - mean, 2); });
var sd = Math.sqrt(diffs.reduce(function(a, b) { return a + b; }) / nb);
if (sd < 10) lichess.socket.send('hold', { mean: Math.round(mean), sd: Math.round(sd) });
}
}
}
},
reloadTable: function(callback) {
var self = this;
self.get(self.options.tableUrl, {