more work on mithril tournaments

This commit is contained in:
Thibault Duplessis 2015-01-04 19:28:30 +01:00
parent 1b09f2b3fd
commit 6b0db65f03
8 changed files with 91 additions and 75 deletions

View file

@ -51,11 +51,8 @@ object Tournament extends LilaController {
def show(id: String) = Open { implicit ctx =>
repo byId id flatMap {
_ match {
case Some(tour: Created) => showCreated(tour) map { Ok(_) }
case Some(tour: Started) => showStarted(tour) map { Ok(_) }
case Some(tour: Finished) => showFinished(tour) map { Ok(_) }
case _ => tournamentNotFound.fuccess
_.fold(tournamentNotFound.fuccess) { tour =>
showJs(tour) map { Ok(_) }
}
}
}
@ -67,20 +64,6 @@ object Tournament extends LilaController {
case ((version, data), chat) => html.tournament.showJs(tour, version, data, chat)
}
private def showCreated(tour: Created)(implicit ctx: Context) =
showJs(tour)
private def showStarted(tour: Started)(implicit ctx: Context) =
showJs(tour)
private def showFinished(tour: Finished)(implicit ctx: Context) =
env.version(tour.id) zip
chatOf(tour) zip
GameRepo.games(tour recentGameIds 4) map {
case ((version, chat), games) =>
html.tournament.show.finished(tour, version, chat, games)
}
def join(id: String) = AuthBody { implicit ctx =>
implicit me =>
NoEngine {

View file

@ -16,6 +16,7 @@ final class JsonView(
def apply(tour: Tournament): Fu[JsObject] =
lastGames(tour) map { games =>
val sheets = tour.system.scoringSystem scoreSheets tour
Json.obj(
"id" -> tour.id,
"createdBy" -> tour.createdBy,
@ -23,7 +24,7 @@ final class JsonView(
"private" -> tour.hasPassword,
"schedule" -> tour.schedule.map(scheduleJson),
"variant" -> tour.variant.key,
"players" -> tour.players.map(playerJson),
"players" -> tour.rankedPlayers.map((playerJson(sheets) _).tupled),
"winner" -> tour.winner.map(_.id),
"pairings" -> tour.pairings.map(pairingJson),
"isOpen" -> tour.isOpen,
@ -69,16 +70,30 @@ final class JsonView(
"user1" -> gameUserJson(g.firstPlayer),
"user2" -> gameUserJson(g.secondPlayer))
private def playerJson(p: Player) = {
private def sheetJson(sheet: ScoreSheet) = sheet match {
case s: arena.ScoringSystem.Sheet => Json.obj(
"scores" -> s.scores.take(20).reverse.map { score =>
Json.arr(score.value, score.flag.toString.toLowerCase)
},
"total" -> s.total,
"fire" -> s.onFire)
case s: swiss.SwissSystem.Sheet => Json.obj(
"scores" -> s.scores.take(20).reverse.map(_.value),
"total" -> s.total)
}
private def playerJson(sheets: Map[String, ScoreSheet])(rank: Int, p: Player) = {
val light = getLightUser(p.id)
Json.obj(
"rank" -> rank,
"id" -> p.id,
"username" -> light.map(_.name),
"title" -> light.map(_.title),
"online" -> isOnline(p.id).option(true),
"rating" -> p.rating,
"withdraw" -> p.withdraw.option(true),
"score" -> p.score).noNull
"score" -> p.score,
"sheet" -> sheets.get(p.id).map(sheetJson)).noNull
}
private def pairingJson(p: Pairing) = Json.obj(

View file

@ -69,6 +69,7 @@ sealed trait Tournament {
def isActive(user: User): Boolean = isActive(user.id)
def isActive(user: Option[User]): Boolean = ~user.map(isActive)
def missingPlayers = minPlayers - players.size
def rankedPlayers: RankedPlayers = system.scoringSystem.rank(this, players)
def createdBy = data.createdBy
def createdAt = data.createdAt
@ -111,14 +112,11 @@ sealed trait Enterable extends Tournament {
}
sealed trait StartedOrFinished extends Tournament {
type RankedPlayers = List[(Int, Player)]
def startedAt: DateTime
def withPlayers(s: Players): StartedOrFinished
def refreshPlayers: StartedOrFinished
def rankedPlayers: RankedPlayers = system.scoringSystem.rank(this, players)
def winner = players.headOption
def winnerUserId = winner map (_.id)

View file

@ -6,6 +6,8 @@ package object tournament extends PackageObject with WithPlay with WithSocket {
private[tournament]type Players = List[tournament.Player]
private[tournament]type RankedPlayers = List[(Int, Player)]
private[tournament]type Pairings = List[tournament.Pairing]
private[tournament]type Events = List[tournament.Event]

View file

@ -1881,14 +1881,12 @@ lichess.storage = {
});
function startTournament(element, cfg) {
$('body').data('tournament-id', cfg.data.id);
var $watchers = $("div.watchers").watchers();
var $chat = $('#chat');
if ($chat.length) $chat.chat({
messages: lichess_chat
});
var tournament;
lichess.socket = new lichess.StrongSocket(
'/tournament/' + cfg.data.id + '/socket/v1', cfg.socketVersion, {
@ -1906,50 +1904,6 @@ lichess.storage = {
});
cfg.socketSend = lichess.socket.send.bind(lichess.socket);
tournament = LichessTournament(element, cfg);
// function startClock() {
// $("div.tournament_clock").each(function() {
// $(this).clock({
// time: $(this).data("time")
// }).clock("start");
// });
// }
// startClock();
// function drawBars() {
// $wrap.find('table.standing').each(function() {
// var $bars = $(this).find('.bar');
// var max = Math.max.apply(Math, $bars.map(function() {
// return parseInt(this.getAttribute('data-value'));
// }));
// $bars.each(function() {
// var width = Math.ceil((parseInt($(this).data('value')) * 100) / max);
// $(this).css('width', width + '%');
// });
// });
// }
// drawBars();
// function reload() {
// $.ajax({
// url: $wrap.data('href'),
// success: function(html) {
// var $tour = $(html);
// if ($wrap.find('table.standing').length) {
// // started
// $wrap.find('table.standing thead').replaceWith($tour.find('table.standing thead'));
// $wrap.find('table.standing tbody').replaceWith($tour.find('table.standing tbody'));
// drawBars();
// $wrap.find('div.pairings').replaceWith($tour.find('div.pairings'));
// $wrap.find('div.game_list').replaceWith($tour.find('div.game_list'));
// } else {
// // created
// $wrap.find('table.user_list').replaceWith($tour.find('table.user_list'));
// }
// $('body').trigger('lichess.content_loaded');
// }
// });
// }
};
////////////////

View file

@ -3,7 +3,71 @@ var partial = require('chessground').util.partial;
var tournament = require('../tournament');
var util = require('./util');
var legend = m('th.legend', [
m('span.streakstarter', 'Streak starter'),
m('span.double', 'Double points')
]);
function scoreTag(s) {
return {
tag: 'span',
attrs: {
class: s[1]
},
children: [s[0]]
};
}
function playerTrs(ctrl, player, maxScore) {
return [
m('tr' + ctrl.userId === player.id ? '.me' : '', [
m('td.name', [
player.withdraw ? m('span', {
'data-icon': 'b',
'title': ctrl.trans('withdraw')
}) : (
(tour.isFinished && player.rank === 1) ? m('span', {
'data-icon': 'g',
'title': ctrl.trans('winner')
}) : m('span.rank', player.rank)),
util.player(player)
]),
m('td.sheet', player.sheet.scores.map(scoreTag)),
m('td.total',
m('strong',
player.sheet.fire ? {
class: 'is-gold text',
'data-icon': 'Q'
} : {}, player.sheet.total))
]),
m('tr',
m('td', {
class: 'around-bar',
colspan: 3
}, m('div', {
class: 'bar',
style: {
width: Math.ceil(player.sheet.total * 100 / maxScore) + '%'
}
})))
];
}
module.exports = {
standing: function(ctrl) {
var maxScore = Math.max.apply(Math, ctrl.data.players.map(function(p) {
return p.sheet.total;
}));
return [
m('thead',
m('tr', [
m('th.large', [
ctrl.trans('standing'),
'(' + ctrl.data.players.length + ')'
]),
legend
])),
m('tbody', ctrl.data.players.map(util.partial(playerTrs, ctrl, maxScore)))
];
}
};

View file

@ -52,7 +52,7 @@ module.exports = {
m('div.standing_wrap.scroll-shadow-soft',
m('table.slist.standing' + ctrl.data.scheduled ? '.scheduled' : '',
ctrl.data.system === 'arena' ? arena.standing(ctrl) : null)),
util.games(ctrl.data.games)
util.games(ctrl.data.lastGames)
];
},
side: function(ctrl) {

View file

@ -21,7 +21,7 @@ function miniGame(game) {
game.user1.title ? game.user1.title + ' ' : '',
game.user1.rating
]),
m('div.left', [
m('div.right', [
game.user1.name,
m('br'),
game.user1.rating,
@ -54,7 +54,7 @@ module.exports = {
p.rating ? ' (' + p.rating + ')' : '',
]);
},
games: function(ctrl) {
return m('div.game_list.playing', ctrl.data.games.map(miniGame));
games: function(games) {
return m('div.game_list.playing', games.map(miniGame));
}
};