mirror of
https://github.com/DragonMinded/bemaniutils.git
synced 2026-05-02 03:25:31 -05:00
395 lines
16 KiB
JavaScript
395 lines
16 KiB
JavaScript
/*** @jsx React.DOM */
|
|
|
|
var valid_charts = ['SPN', 'SPH', 'SPA', 'DPN', 'DPH', 'DPA'].filter(function(val, index) {
|
|
return window.difficulties[index] > 0;
|
|
});
|
|
var pagenav = new History(valid_charts);
|
|
|
|
var top_scores = createReactClass({
|
|
|
|
sortTopScores: function(topscores) {
|
|
var newscores = [[], [], [], [], [], []];
|
|
topscores.map(function(score) {
|
|
newscores[score.chart].push(score);
|
|
}.bind(this));
|
|
return newscores;
|
|
},
|
|
|
|
getInitialViewingState: function(topscores, chart) {
|
|
var index = this.convertChart(chart);
|
|
if (topscores[index].length > 0) {
|
|
var hash = null;
|
|
var maxpoints = 0;
|
|
topscores[index].map(function(topscore) {
|
|
if (topscore.points > maxpoints) {
|
|
hash = this.hashScore(topscore);
|
|
maxpoints = topscore.points;
|
|
}
|
|
}.bind(this));
|
|
return [hash, null, null, null, null];
|
|
} else {
|
|
return [null, null, null, null, null];
|
|
}
|
|
},
|
|
|
|
hashScore: function(topscore) {
|
|
if (topscore.ghost) {
|
|
return topscore.songid + '-' + topscore.chart + '-' + topscore.ghost.join(',');
|
|
} else {
|
|
return topscore.songid + '-' + topscore.chart;
|
|
}
|
|
},
|
|
|
|
getInitialState: function(props) {
|
|
var topscores = this.sortTopScores(window.topscores);
|
|
var chart = pagenav.getInitialState(valid_charts[0]);
|
|
var viewing = this.getInitialViewingState(topscores, chart);
|
|
return {
|
|
topscores: topscores,
|
|
players: window.players,
|
|
chart: chart,
|
|
viewing: viewing,
|
|
};
|
|
},
|
|
|
|
componentDidMount: function() {
|
|
pagenav.onChange(function(chart) {
|
|
var viewing = this.getInitialViewingState(this.state.topscores, chart);
|
|
this.setState({chart: chart, viewing: viewing});
|
|
}.bind(this));
|
|
this.refreshScores();
|
|
},
|
|
|
|
refreshScores: function() {
|
|
AJAX.get(
|
|
Link.get('refresh'),
|
|
function(response) {
|
|
this.setState({
|
|
topscores: this.sortTopScores(response.topscores),
|
|
players: response.players,
|
|
});
|
|
// Refresh every 15 seconds
|
|
setTimeout(this.refreshScores, 15000);
|
|
}.bind(this)
|
|
);
|
|
},
|
|
|
|
convertChart: function(chart) {
|
|
switch(chart) {
|
|
case 'SPN':
|
|
return 0;
|
|
case 'SPH':
|
|
return 1;
|
|
case 'SPA':
|
|
return 2;
|
|
case 'DPN':
|
|
return 3;
|
|
case 'DPH':
|
|
return 4;
|
|
case 'DPA':
|
|
return 5
|
|
default:
|
|
return null;
|
|
}
|
|
},
|
|
|
|
renderGrade: function(chart, topscore) {
|
|
var maxscore = window.notecounts[chart] * 2;
|
|
var percent = topscore.points / maxscore;
|
|
var grade = parseInt(9.0 * percent);
|
|
var grades = [
|
|
"F",
|
|
"F",
|
|
"E",
|
|
"D",
|
|
"C",
|
|
"B",
|
|
"A",
|
|
"AA",
|
|
"AAA",
|
|
"MAX",
|
|
];
|
|
|
|
var hash = this.hashScore(topscore);
|
|
var index = this.state.viewing.indexOf(hash);
|
|
var style = {};
|
|
if (index >= 0) {
|
|
style.color = this.getGhostColors()[index];
|
|
}
|
|
|
|
return (
|
|
<div className="score">
|
|
<Checkbox
|
|
checked={index >= 0}
|
|
onClick={function(event) {
|
|
if (index >= 0) {
|
|
// Remove it if it exists
|
|
var viewing = this.state.viewing;
|
|
viewing[index] = null;
|
|
this.setState({viewing: viewing});
|
|
} else {
|
|
// Add it if it doesn't exist and there's room
|
|
var addindex = this.state.viewing.indexOf(null);
|
|
if (addindex >= 0) {
|
|
var viewing = this.state.viewing;
|
|
viewing[addindex] = hash;
|
|
this.setState({viewing: viewing});
|
|
}
|
|
}
|
|
}.bind(this)}
|
|
/>
|
|
<span style={style}>
|
|
<span className="grade">{grades[grade]}</span>
|
|
<span className="percent">{(percent * 100).toFixed(2)}%</span>
|
|
</span>
|
|
</div>
|
|
);
|
|
},
|
|
|
|
calculateGhost: function(ghost) {
|
|
var total = 0;
|
|
var ghost = ghost.map(function(val) {
|
|
var out = val + total;
|
|
total = total + val;
|
|
return out;
|
|
});
|
|
ghost.unshift(0);
|
|
return ghost;
|
|
},
|
|
|
|
getGhostColors: function() {
|
|
return [
|
|
'rgba(255,99,132,1)',
|
|
'rgba(255,153,0,1)',
|
|
'rgba(153,204,0,1)',
|
|
'rgba(0,204,255,1)',
|
|
'rgba(153,51,255,1)',
|
|
];
|
|
},
|
|
|
|
render: function() {
|
|
var chart = this.convertChart(this.state.chart);
|
|
|
|
// Handle rendering the chart, finding any non-null viewing indexes
|
|
var ghosts = Array(this.state.viewing.length).fill(null);
|
|
var colors = this.getGhostColors();
|
|
var notecounts = null;
|
|
var aaa = null;
|
|
var aa = null;
|
|
var a = null;
|
|
var zero = null;
|
|
|
|
this.state.topscores[chart].map(function(topscore) {
|
|
var index = this.state.viewing.indexOf(this.hashScore(topscore));
|
|
if (index >= 0) {
|
|
ghosts[index] = this.calculateGhost(topscore.ghost);
|
|
}
|
|
}.bind(this));
|
|
|
|
// Filter out to preserve colors at the time of selection
|
|
colors = colors.filter(function(color, index) {
|
|
return ghosts[index] != null;
|
|
});
|
|
ghosts = ghosts.filter(function(ghost) {
|
|
return ghost != null;
|
|
});
|
|
if (ghosts.length > 0) {
|
|
notecounts = window.notecounts[chart] * 2
|
|
aaa = Array(ghosts[0].length).fill(notecounts * (8/9));
|
|
aa = Array(ghosts[0].length).fill(notecounts * (7/9));
|
|
a = Array(ghosts[0].length).fill(notecounts * (6/9));
|
|
zero = Array(ghosts[0].length).fill(0);
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
<div className="section">
|
|
<div className="floating right">{ ghosts.length > 0 ?
|
|
<div className="section">
|
|
<LineGraph
|
|
data={{
|
|
labels: zero,
|
|
datasets: ghosts.map(function(ghost, index) {
|
|
return {
|
|
fill: false,
|
|
data: ghost,
|
|
borderColor: [
|
|
colors[index],
|
|
],
|
|
borderWidth: 2,
|
|
};
|
|
}.bind(this)).concat([
|
|
{
|
|
fill: false,
|
|
data: aaa,
|
|
borderColor: [
|
|
'rgba(0,0,0,0.25)',
|
|
],
|
|
borderWidth: 1,
|
|
},
|
|
{
|
|
fill: false,
|
|
data: aa,
|
|
borderColor: [
|
|
'rgba(0,0,0,0.25)',
|
|
],
|
|
borderWidth: 1,
|
|
},
|
|
{
|
|
fill: false,
|
|
data: a,
|
|
borderColor: [
|
|
'rgba(0,0,0,0.25)',
|
|
],
|
|
borderWidth: 1,
|
|
},
|
|
{
|
|
fill: false,
|
|
data: zero,
|
|
borderColor: [
|
|
'rgba(0,0,0,0.25)',
|
|
],
|
|
borderWidth: 1,
|
|
},
|
|
]),
|
|
}}
|
|
options={{
|
|
scales: {
|
|
xAxes: [{
|
|
display: false,
|
|
}],
|
|
yAxes: [{
|
|
grid: {
|
|
display: false,
|
|
},
|
|
gridLines: {
|
|
display: false,
|
|
},
|
|
ticks: {
|
|
callback: function(tick, index, ticks) {
|
|
switch(index) {
|
|
case 0:
|
|
return 'MAX';
|
|
case 1:
|
|
return 'AAA';
|
|
case 2:
|
|
return 'AA';
|
|
case 3:
|
|
return 'A';
|
|
default:
|
|
return '';
|
|
}
|
|
},
|
|
beginAtZero:true,
|
|
min: 0,
|
|
max: notecounts,
|
|
stepSize: notecounts / 9,
|
|
}
|
|
}],
|
|
},
|
|
elements: {
|
|
point: {
|
|
radius: 0,
|
|
},
|
|
},
|
|
legend: {
|
|
display: false,
|
|
},
|
|
tooltips: {
|
|
enabled: false,
|
|
},
|
|
responsive: false,
|
|
animation: false,
|
|
}}
|
|
width="320"
|
|
height="200"
|
|
/>
|
|
</div> : <div style={{width: '320px', height: '200px'}}></div>
|
|
}</div>
|
|
<div className="left">
|
|
<div className="songname">{window.name}</div>
|
|
<div className="songartist">{window.artist}</div>
|
|
<div className="songgenre">{window.genre}</div>
|
|
<div className="songdifficulty">{window.difficulties[chart]}★</div>
|
|
</div>
|
|
</div>
|
|
<div className="section">
|
|
{valid_charts.map(function(chart) {
|
|
return (
|
|
<Nav
|
|
title={chart}
|
|
active={this.state.chart == chart}
|
|
onClick={function(event) {
|
|
if (this.state.chart == chart) { return; }
|
|
var viewing = this.getInitialViewingState(this.state.topscores, chart);
|
|
this.setState({chart: chart, viewing: viewing});
|
|
pagenav.navigate(chart);
|
|
}.bind(this)}
|
|
/>
|
|
);
|
|
}.bind(this))}
|
|
</div>
|
|
<div className="section">
|
|
<Table
|
|
className="list topscores"
|
|
columns={[
|
|
{
|
|
name: 'DJ Name',
|
|
render: function(topscore) {
|
|
return (
|
|
<a href={Link.get('player', topscore.userid)}>{
|
|
this.state.players[topscore.userid].name
|
|
}</a>
|
|
);
|
|
}.bind(this),
|
|
sort: function(a, b) {
|
|
var an = this.state.players[a.userid].name;
|
|
var bn = this.state.players[b.userid].name;
|
|
return an.localeCompare(bn);
|
|
}.bind(this),
|
|
},
|
|
{
|
|
name: 'Arcade',
|
|
render: function(topscore) { return this.state.players[topscore.userid].arcade; }.bind(this),
|
|
},
|
|
{
|
|
name: 'Status',
|
|
render: function(topscore) { return topscore.status; },
|
|
},
|
|
{
|
|
name: 'Grade',
|
|
render: function(topscore) { return this.renderGrade(chart, topscore); }.bind(this),
|
|
},
|
|
{
|
|
name: 'EX Score',
|
|
render: function(topscore) { return topscore.points; },
|
|
sort: function(a, b) {
|
|
return a.points - b.points;
|
|
},
|
|
reverse: true,
|
|
},
|
|
{
|
|
name: 'Miss Count',
|
|
render: function(topscore) { return topscore.miss_count; },
|
|
sort: function(a, b) {
|
|
return a.miss_count - b.miss_count;
|
|
},
|
|
},
|
|
]}
|
|
defaultsort='EX Score'
|
|
rows={this.state.topscores[chart]}
|
|
key={chart}
|
|
paginate={10}
|
|
emptymessage="There are no scores for this chart."
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
},
|
|
});
|
|
|
|
ReactDOM.render(
|
|
React.createElement(top_scores, null),
|
|
document.getElementById('content')
|
|
);
|