perfStat: remove ui/perfStat
parent
2d628c051b
commit
435fbd89d2
|
@ -392,12 +392,12 @@ object User extends LilaController {
|
||||||
}
|
}
|
||||||
ratingChart <- Env.history.ratingChartApi.apply(u)
|
ratingChart <- Env.history.ratingChartApi.apply(u)
|
||||||
_ <- Env.user.lightUserApi preloadMany { u.id :: perfStat.userIds.map(_.value) }
|
_ <- Env.user.lightUserApi preloadMany { u.id :: perfStat.userIds.map(_.value) }
|
||||||
data = Env.perfStat.jsonView(u, perfStat, ranks get perfType, percentile)
|
|
||||||
response <- negotiate(
|
response <- negotiate(
|
||||||
html = Ok(html.user.perfStat(u, ranks, perfType, percentile, perfStat, data, ratingChart)).fuccess,
|
html = Ok(html.user.perfStat(u, ranks, perfType, percentile, perfStat, ratingChart)).fuccess,
|
||||||
api = _ => getBool("graph").?? {
|
api = _ => getBool("graph").?? {
|
||||||
Env.history.ratingChartApi.singlePerf(u, perfType).map(_.some)
|
Env.history.ratingChartApi.singlePerf(u, perfType).map(_.some)
|
||||||
} map {
|
} map {
|
||||||
|
val data = Env.perfStat.jsonView(u, perfStat, ranks get perfType, percentile)
|
||||||
_.fold(data) { graph => data + ("graph" -> graph) }
|
_.fold(data) { graph => data + ("graph" -> graph) }
|
||||||
} map { Ok(_) }
|
} map { Ok(_) }
|
||||||
)
|
)
|
||||||
|
|
|
@ -18,7 +18,6 @@ object perfStat {
|
||||||
perfType: lila.rating.PerfType,
|
perfType: lila.rating.PerfType,
|
||||||
percentile: Option[Double],
|
percentile: Option[Double],
|
||||||
stat: PerfStat,
|
stat: PerfStat,
|
||||||
data: play.api.libs.json.JsObject,
|
|
||||||
ratingChart: Option[String]
|
ratingChart: Option[String]
|
||||||
)(implicit ctx: Context) = views.html.base.layout(
|
)(implicit ctx: Context) = views.html.base.layout(
|
||||||
title = s"${u.username} ${perfType.name} stats",
|
title = s"${u.username} ${perfType.name} stats",
|
||||||
|
@ -30,13 +29,7 @@ object perfStat {
|
||||||
jsTag("chart/ratingHistory.js"),
|
jsTag("chart/ratingHistory.js"),
|
||||||
embedJsUnsafe(s"lichess.ratingHistoryChart($rc,'${perfType.name}');")
|
embedJsUnsafe(s"lichess.ratingHistoryChart($rc,'${perfType.name}');")
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
jsAt(s"compiled/lichess.perfStat${isProd ?? (".min")}.js"),
|
|
||||||
embedJsUnsafe(s"""$$(function() {
|
|
||||||
if (false) LichessPerfStat(document.querySelector('.perf-stat__content'), {
|
|
||||||
data: ${safeJsonValue(data)}
|
|
||||||
});
|
|
||||||
});""")
|
|
||||||
),
|
),
|
||||||
moreCss = cssTag("perf-stat")
|
moreCss = cssTag("perf-stat")
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -43,7 +43,6 @@
|
||||||
"ui/learn",
|
"ui/learn",
|
||||||
"ui/lobby",
|
"ui/lobby",
|
||||||
"ui/notify",
|
"ui/notify",
|
||||||
"ui/perfStat",
|
|
||||||
"ui/puzzle",
|
"ui/puzzle",
|
||||||
"ui/round",
|
"ui/round",
|
||||||
"ui/simul",
|
"ui/simul",
|
||||||
|
|
2
ui/build
2
ui/build
|
@ -13,7 +13,7 @@ mkdir -p public/compiled
|
||||||
|
|
||||||
ts_apps1="common chess"
|
ts_apps1="common chess"
|
||||||
ts_apps2="ceval game tree chat nvui"
|
ts_apps2="ceval game tree chat nvui"
|
||||||
apps="site chat cli challenge notify learn insight editor puzzle round analyse lobby tournament tournamentSchedule tournamentCalendar simul perfStat dasher speech palantir"
|
apps="site chat cli challenge notify learn insight editor puzzle round analyse lobby tournament tournamentSchedule tournamentCalendar simul dasher speech palantir"
|
||||||
|
|
||||||
if [ $mode == "upgrade" ]; then
|
if [ $mode == "upgrade" ]; then
|
||||||
yarn upgrade --non-interactive
|
yarn upgrade --non-interactive
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
const lilaGulp = require('../gulp/jsProject.js');
|
|
||||||
|
|
||||||
lilaGulp('LichessPerfStat', 'lichess.perfStat', __dirname);
|
|
|
@ -1,36 +0,0 @@
|
||||||
{
|
|
||||||
"name": "perfStat",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "lichess.org chess performance statistics",
|
|
||||||
"main": "src/main.js",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/ornicar/lila"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"chess",
|
|
||||||
"lichess",
|
|
||||||
"performance",
|
|
||||||
"statistic"
|
|
||||||
],
|
|
||||||
"author": "ornicar",
|
|
||||||
"license": "AGPL-3.0",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/ornicar/lila/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/ornicar/lila",
|
|
||||||
"devDependencies": {
|
|
||||||
"browserify": "^16",
|
|
||||||
"gulp": "^4",
|
|
||||||
"gulp-terser": "^1",
|
|
||||||
"gulp-size": "^3",
|
|
||||||
"fancy-log": "^1",
|
|
||||||
"vinyl-source-stream": "^2",
|
|
||||||
"vinyl-buffer": "^1",
|
|
||||||
"watchify": "^3"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"mithril": "github:ornicar/mithril.js#lila-1",
|
|
||||||
"numeral": "^1.5"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,71 +0,0 @@
|
||||||
var m = require('mithril');
|
|
||||||
var util = require('./util');
|
|
||||||
|
|
||||||
function percent(x, y) {
|
|
||||||
if (y === 0) return 0;
|
|
||||||
return Math.round(x * 100 / y);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = function(d) {
|
|
||||||
var c = d.stat.count;
|
|
||||||
var per = function(x, y) {
|
|
||||||
return percent(x, y || c.all) + '%';
|
|
||||||
};
|
|
||||||
return [
|
|
||||||
m('div', m('table', m('tbody', [
|
|
||||||
m('tr', [
|
|
||||||
m('th', 'Total games'),
|
|
||||||
m('td', c.all),
|
|
||||||
m('td'),
|
|
||||||
]),
|
|
||||||
m('tr.full', [
|
|
||||||
m('th', 'Rated games'),
|
|
||||||
m('td', c.rated),
|
|
||||||
m('td', per(c.rated)),
|
|
||||||
]),
|
|
||||||
m('tr.full', [
|
|
||||||
m('th', 'Tournament games'),
|
|
||||||
m('td', c.tour),
|
|
||||||
m('td', per(c.tour)),
|
|
||||||
]),
|
|
||||||
m('tr.full', [
|
|
||||||
m('th', 'Berserked games'),
|
|
||||||
m('td', c.berserk),
|
|
||||||
m('td', per(c.berserk, c.tour)),
|
|
||||||
]),
|
|
||||||
c.seconds ? m('tr.full', [
|
|
||||||
m('th', 'Time spent playing'),
|
|
||||||
m('td[colspan=2]', util.formatSeconds(c.seconds, 'short'))
|
|
||||||
]) : null
|
|
||||||
]))),
|
|
||||||
m('div', m('table', m('tbody', [
|
|
||||||
m('tr', [
|
|
||||||
m('th', 'Average opponent'),
|
|
||||||
m('td', c.opAvg),
|
|
||||||
m('td')
|
|
||||||
]),
|
|
||||||
m('tr.full', [
|
|
||||||
m('th', 'Victories'),
|
|
||||||
m('td', util.green(c.win)),
|
|
||||||
m('td', util.green(per(c.win)))
|
|
||||||
]),
|
|
||||||
m('tr.full', [
|
|
||||||
m('th', 'Draws'),
|
|
||||||
m('td', c.draw),
|
|
||||||
m('td', per(c.draw))
|
|
||||||
]),
|
|
||||||
m('tr.full', [
|
|
||||||
m('th', 'Defeats'),
|
|
||||||
m('td', util.red(c.loss)),
|
|
||||||
m('td', util.red(per(c.loss)))
|
|
||||||
]),
|
|
||||||
m('tr.full', (function(color) {
|
|
||||||
return [
|
|
||||||
m('th', 'Disconnections'),
|
|
||||||
m('td', color(c.disconnects)),
|
|
||||||
m('td', color(per(c.disconnects, c.loss)))
|
|
||||||
];
|
|
||||||
})(percent(c.disconnects, c.loss) >= 15 ? util.red : util.identity))
|
|
||||||
])))
|
|
||||||
];
|
|
||||||
};
|
|
|
@ -1,47 +0,0 @@
|
||||||
var m = require('mithril');
|
|
||||||
|
|
||||||
function provisional() {
|
|
||||||
return m('span', {
|
|
||||||
title: 'Not enough rated games have been played to establish a reliable rating.'
|
|
||||||
}, '(provisional)');
|
|
||||||
}
|
|
||||||
|
|
||||||
function percentile(d) {
|
|
||||||
return d.percentile === 0 ? '' : [
|
|
||||||
' Better than ',
|
|
||||||
m('a', {
|
|
||||||
href: '/stat/rating/distribution/' + d.stat.perfType.key
|
|
||||||
}, [
|
|
||||||
m('strong', d.percentile + '%'),
|
|
||||||
' of ' + d.stat.perfType.name + ' players.'
|
|
||||||
])
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
function progress(p) {
|
|
||||||
if (p > 0) return m('green[data-icon=N]', p);
|
|
||||||
else if (p < 0) return m('red[data-icon=M]', -p);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = function(d) {
|
|
||||||
return [
|
|
||||||
m('h2', [
|
|
||||||
'Rating: ',
|
|
||||||
m('strong', {
|
|
||||||
title: 'Yes, ratings have decimal accuracy.'
|
|
||||||
}, d.perf.glicko.rating),
|
|
||||||
'. ',
|
|
||||||
m('span.details', d.perf.glicko.provisional ? provisional() : percentile(d))
|
|
||||||
]),
|
|
||||||
m('p', [
|
|
||||||
'Progression over the last twelve games: ',
|
|
||||||
m('span.progress', progress(d.perf.progress) || 'none'),
|
|
||||||
'. ',
|
|
||||||
'Rating deviation: ',
|
|
||||||
m('strong', {
|
|
||||||
title: 'Lower value means the rating is more stable. Above 110, the rating is considered provisional.'
|
|
||||||
}, d.perf.glicko.deviation),
|
|
||||||
'. '
|
|
||||||
])
|
|
||||||
];
|
|
||||||
};
|
|
|
@ -1,21 +0,0 @@
|
||||||
var m = require('mithril');
|
|
||||||
var util = require('./util');
|
|
||||||
|
|
||||||
function ratingAt(title, opt, color) {
|
|
||||||
return util.fMap(opt, function(r) {
|
|
||||||
return [
|
|
||||||
m('h2', [title + ': ', m('strong', color(r.int))]),
|
|
||||||
util.gameLink(r.gameId, util.date(r.at))
|
|
||||||
];
|
|
||||||
}, [
|
|
||||||
m('h2', title + ': '),
|
|
||||||
m('span', util.noData)
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = function(d) {
|
|
||||||
return [
|
|
||||||
m('div', ratingAt('Highest rating', d.stat.highest, util.green)),
|
|
||||||
m('div', ratingAt('Lowest rating', d.stat.lowest, util.red))
|
|
||||||
];
|
|
||||||
};
|
|
|
@ -1,13 +0,0 @@
|
||||||
var m = require('mithril');
|
|
||||||
|
|
||||||
module.exports = function(element, opts) {
|
|
||||||
|
|
||||||
m.module(element, {
|
|
||||||
controller: function() {
|
|
||||||
return {
|
|
||||||
data: opts.data
|
|
||||||
};
|
|
||||||
},
|
|
||||||
view: require('./view')
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,49 +0,0 @@
|
||||||
var m = require('mithril');
|
|
||||||
var util = require('./util');
|
|
||||||
|
|
||||||
function streak(s, title, display) {
|
|
||||||
return m('div.streak', [
|
|
||||||
m('h3', [
|
|
||||||
title + ': ',
|
|
||||||
display(s.v)
|
|
||||||
]),
|
|
||||||
util.fromTo(s)
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function streaks(s, display) {
|
|
||||||
return m('div.split', [
|
|
||||||
m('div', streak(s.max, 'Longest streak', display)),
|
|
||||||
m('div', streak(s.cur, 'Current streak', display))
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
var lessThan = 'Less than one hour between games.';
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
nb: function(d) {
|
|
||||||
return util.fMap(d.stat.playStreak.nb, function(s) {
|
|
||||||
return [
|
|
||||||
m('h2', m('span', {
|
|
||||||
title: lessThan
|
|
||||||
}, 'Games played in a row')),
|
|
||||||
streaks(s, function(v) {
|
|
||||||
return v ? [
|
|
||||||
m('strong', v),
|
|
||||||
' game' + (v > 1 ? 's' : '')
|
|
||||||
] : 'none';
|
|
||||||
})
|
|
||||||
];
|
|
||||||
});
|
|
||||||
},
|
|
||||||
time: function(d) {
|
|
||||||
return util.fMap(d.stat.playStreak.time, function(s) {
|
|
||||||
return [
|
|
||||||
m('h2', m('span', {
|
|
||||||
title: lessThan
|
|
||||||
}, 'Max time spent playing')),
|
|
||||||
streaks(s, util.formatSeconds)
|
|
||||||
];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,21 +0,0 @@
|
||||||
var m = require('mithril');
|
|
||||||
var util = require('./util');
|
|
||||||
|
|
||||||
function resultTable(results, title) {
|
|
||||||
return m('table', [
|
|
||||||
m('thead', m('tr', m('th[colspan=2]', m('h2', title)))),
|
|
||||||
m('tbody', results.map(function(r) {
|
|
||||||
return m('tr', [
|
|
||||||
m('td', util.showUser(r.opId, r.opInt)),
|
|
||||||
m('td', util.gameLink(r.gameId, util.date(r.at)))
|
|
||||||
]);
|
|
||||||
}))
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = function(d) {
|
|
||||||
return [
|
|
||||||
m('div', resultTable(d.stat.bestWins.results, 'Best rated victories')),
|
|
||||||
m('div', resultTable(d.stat.worstLosses.results, 'Worst rated defeats'))
|
|
||||||
];
|
|
||||||
};
|
|
|
@ -1,37 +0,0 @@
|
||||||
var m = require('mithril');
|
|
||||||
var util = require('./util');
|
|
||||||
|
|
||||||
function streak(s, title, color) {
|
|
||||||
return m('div.streak', [
|
|
||||||
m('h3', [
|
|
||||||
title + ': ',
|
|
||||||
s.v > 0 ? color([
|
|
||||||
m('strong', s.v),
|
|
||||||
' game' + (s.v > 1 ? 's' : '')
|
|
||||||
]) : 'none'
|
|
||||||
]),
|
|
||||||
util.fromTo(s)
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function streaks(color) {
|
|
||||||
return function(s) {
|
|
||||||
return [
|
|
||||||
streak(s.max, 'Longest', color),
|
|
||||||
streak(s.cur, 'Current', color)
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = function(d) {
|
|
||||||
return [
|
|
||||||
m('div', [
|
|
||||||
m('h2', 'Winning streak'),
|
|
||||||
util.fMap(d.stat.resultStreak.win, streaks(util.green), util.noData)
|
|
||||||
]),
|
|
||||||
m('div', [
|
|
||||||
m('h2', 'Losing streak'),
|
|
||||||
util.fMap(d.stat.resultStreak.loss, streaks(util.red), util.noData)
|
|
||||||
])
|
|
||||||
];
|
|
||||||
};
|
|
|
@ -1,68 +0,0 @@
|
||||||
var m = require('mithril');
|
|
||||||
|
|
||||||
function fMap(v, f, orDefault) {
|
|
||||||
return v ? f(v) : (orDefault || null);
|
|
||||||
}
|
|
||||||
|
|
||||||
function gameLink(id, content) {
|
|
||||||
return m('a', {
|
|
||||||
class: 'glpt',
|
|
||||||
href: '/' + id
|
|
||||||
}, content);
|
|
||||||
}
|
|
||||||
|
|
||||||
function absDate(d) {
|
|
||||||
return m('time', window.lichess.timeago.absolute(d));
|
|
||||||
}
|
|
||||||
|
|
||||||
function fromTo(s) {
|
|
||||||
return fMap(s.from, function(r) {
|
|
||||||
return [
|
|
||||||
'from ',
|
|
||||||
gameLink(r.gameId, absDate(r.at)),
|
|
||||||
' to ',
|
|
||||||
fMap(s.to, function(r) {
|
|
||||||
return gameLink(r.gameId, absDate(r.at));
|
|
||||||
}, 'now')
|
|
||||||
];
|
|
||||||
}, m.trust(' '));
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
fMap: fMap,
|
|
||||||
gameLink: gameLink,
|
|
||||||
date: absDate,
|
|
||||||
showUser: function(u, rating) {
|
|
||||||
return m('a', {
|
|
||||||
class: 'ulpt',
|
|
||||||
href: '/@/' + u.name
|
|
||||||
}, (u.title ? (u.title + ' ') : '') + u.name + ' (' + rating + ')');
|
|
||||||
},
|
|
||||||
noData: 'Not enough games played.',
|
|
||||||
fromTo: fromTo,
|
|
||||||
streaks: function(s, f) {
|
|
||||||
return [
|
|
||||||
m('div.streak', [
|
|
||||||
m('h3', 'Longest: '), f(s.max)
|
|
||||||
]),
|
|
||||||
m('div.streak', [
|
|
||||||
m('h3', 'Current streak'), f(s.cur)
|
|
||||||
])
|
|
||||||
];
|
|
||||||
},
|
|
||||||
green: function(v) {
|
|
||||||
return m('green', v);
|
|
||||||
},
|
|
||||||
red: function(v) {
|
|
||||||
return m('red', v);
|
|
||||||
},
|
|
||||||
identity: function(v) {
|
|
||||||
return v;
|
|
||||||
},
|
|
||||||
formatSeconds: function(s, format) {
|
|
||||||
var hours = Math.floor(s / 3600);
|
|
||||||
var minutes = Math.floor((s % 3600) / 60);
|
|
||||||
if (format === 'short') return hours + 'h, ' + minutes + 'm';
|
|
||||||
return hours + ' hours, ' + minutes + ' minutes';
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,16 +0,0 @@
|
||||||
var m = require('mithril');
|
|
||||||
|
|
||||||
module.exports = function(ctrl) {
|
|
||||||
var d = ctrl.data;
|
|
||||||
return m('div', {
|
|
||||||
config: lichess.powertip.manualGameIn
|
|
||||||
}, [
|
|
||||||
m('section.glicko', require('./glicko')(d)),
|
|
||||||
m('section.counter.split', require('./counter')(d)),
|
|
||||||
m('section.highlow.split', require('./highlow')(d)),
|
|
||||||
m('section.resultStreak.split', require('./resultStreak')(d)),
|
|
||||||
m('section.result.split', require('./result')(d)),
|
|
||||||
m('section.playStreak', require('./playStreak').nb(d)),
|
|
||||||
m('section.playStreak', require('./playStreak').time(d))
|
|
||||||
]);
|
|
||||||
};
|
|
Loading…
Reference in New Issue