implement hold alerts
This commit is contained in:
parent
6fe17fd9f2
commit
d0261cdee3
|
@ -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) {
|
||||
|
|
12
app/views/round/holdAlerts.scala.html
Normal file
12
app/views/round/holdAlerts.scala.html
Normal 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>
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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, {
|
||||
|
|
Loading…
Reference in a new issue