@ -1,9 +1,99 @@
window . onload = async function ( ) {
let all _dates = [ ] ; // Alle Daten für die für min. einen Spieler ein Rang gespeichert ist
let all _rank _yDatasets = [ ] ; // Datasets, also die einzelnen Linien im Graphen, beinhaltet player_points
let all _progress _yDatasets = [ ] ; // Datasets, also die einzelnen Linien im Graphen, beinhaltet die Differenz der aktuellen player_points und der start player_points
let player _points = { } ; // puuid zeigt auf eine Liste von Punkten, welche die y-Koordinaten im Graphen darstellen
let player _pointprogress = { } ; // puuid zeigt auf eine Liste von Punkten, welche die y-Koordinaten im Graphen darstellen
let combined _charts = [ ] ;
let player _charts = [ ] ;
const x _scale = {
display : true ,
type : "timeseries" ,
time : {
parser : "dd.MM.yy HH:mm" ,
tooltipFormat : "dd.MM.yy HH:mm" ,
unit : "day" ,
unitStepSize : 1 ,
displayFormats : {
"day" : "dd.MM.yy" ,
}
} ,
ticks : {
callback : ( value , index , ticks ) => {
let tickdate = new Date ( value ) ;
if ( index === 0 ) return ` ${ tickdate . getDate ( ) } . ${ month _names [ tickdate . getMonth ( ) ] } ` ;
let prev _tickdate = new Date ( ticks [ index - 1 ] . value ) ;
if ( prev _tickdate . getDate ( ) === tickdate . getDate ( ) ) {
return null ;
}
return ` ${ tickdate . getDate ( ) } . ${ month _names [ tickdate . getMonth ( ) ] } ` ;
}
}
}
const zoom _plugin = {
zoom : {
wheel : {
enabled : true ,
} ,
pinch : {
enabled : true ,
} ,
mode : "x" ,
} ,
pan : {
enabled : true ,
mode : "x" ,
} ,
}
const trigger _legend _hover = function ( e , legendItem , legend ) {
if ( legendItem . hidden ) {
return ;
}
legend . chart . data . datasets . forEach ( ( dataset , i ) => {
dataset . backgroundColor = ( legendItem . datasetIndex === i || dataset . backgroundColor . length === 9 ) ? dataset . backgroundColor : dataset . backgroundColor + '3D' ;
dataset . borderColor = ( legendItem . datasetIndex === i || dataset . borderColor . length === 9 ) ? dataset . borderColor : dataset . borderColor + '3D' ;
dataset . borderWidth = legendItem . datasetIndex === i ? 4 : 3 ;
dataset . pointRadius = 2 ;
} ) ;
legend . chart . update ( ) ;
}
const trigger _legend _leave = function ( e , legendItem , legend ) {
legend . chart . data . datasets . forEach ( ( dataset , i ) => {
dataset . backgroundColor = dataset . backgroundColor . length === 9 ? dataset . backgroundColor . slice ( 0 , - 2 ) : dataset . backgroundColor ;
dataset . borderColor = dataset . borderColor . length === 9 ? dataset . borderColor . slice ( 0 , - 2 ) : dataset . borderColor ;
dataset . borderWidth = 3 ;
} ) ;
legend . chart . update ( ) ;
}
const legend _plugin = {
position : "bottom" ,
labels : {
padding : 10 ,
useBorderRadius : true ,
borderRadius : 2 ,
boxWidth : 20 ,
} ,
onHover : trigger _legend _hover ,
onLeave : trigger _legend _leave ,
onClick : function ( e , legendItem , legend ) {
if ( legend . chart . isDatasetVisible ( legendItem . datasetIndex ) ) {
trigger _legend _leave ( e , legendItem , legend ) ;
legend . chart . hide ( legendItem . datasetIndex ) ;
legendItem . hidden = true ;
} else {
legend . chart . show ( legendItem . datasetIndex ) ;
legendItem . hidden = false ;
trigger _legend _hover ( e , legendItem , legend ) ;
}
}
}
window . onload = create _charts ;
async function create _charts ( ) {
combined _charts . forEach ( chart => chart . destroy ( ) ) ;
combined _charts = [ ] ;
player _charts . forEach ( chart => chart . destroy ( ) ) ;
player _charts = [ ] ;
let player _rank _values = { } ;
let player _progress _values = { } ;
let player _entries = { } ; // puuid zeigt auf player entries
let player _entries _byName = { } ; // playername zeigt auf entries (damit im kombinierten Graphen die Tooltips korrekt gerendert werden können)
let player _accounts = { } ; // puuid zeigt auf player account
@ -15,39 +105,28 @@ window.onload = async function(){
. then ( result => {
player _entries = result [ "entries" ] ;
player _accounts = result [ "accounts" ] ;
for ( const puuid in player _entries ) {
// Alle Daten für die Spieler Einträge haben sollen in all_dates
for ( const entry _date in player _entries [ puuid ] ) {
all _dates . push ( entry _date )
}
// Hier schonmal puuids/namen auf leere Arrays setzen, damit später einfach .push verwendet werden kann
player _points [ puuid ] = [ ] ;
player _pointprogress [ puuid ] = [ ] ;
player _entries _byName [ ` ${ player _accounts [ puuid ] [ "gameName" ] } # ${ player _accounts [ puuid ] [ "tagLine" ] } ` ] = [ ] ;
}
// Daten sortieren und Duplicates entfernen
all _dates . sort ( ) ;
all _dates = [ ... new Set ( all _dates ) ] ;
let all _rank _yDatasets = [ ] ; // Datasets, also die einzelnen Linien im Graphen, beinhaltet player_rank_values
let all _progress _yDatasets = [ ] ; // Datasets, also die einzelnen Linien im Graphen, beinhaltet player_progress_values
let color _counter = 0 ;
for ( const puuid in player _entries ) {
player _rank _values [ puuid ] = [ ] ;
player _progress _values [ puuid ] = [ ] ;
player _entries _byName [ ` ${ player _accounts [ puuid ] [ "gameName" ] } # ${ player _accounts [ puuid ] [ "tagLine" ] } ` ] = [ ] ;
let player _start _points = - 1 ;
for ( const date _string of all _dates ) {
// Für alle Player Entries Punktzahl berechnen und in player_points eintragen
for ( const timestamp in player _entries [ puuid ] ) {
// Für alle Player Entries Punktzahl und Punktedifferenz berechnen
// Bei der Gelegenheit auch Entries in player_entries_byName eintragen
if ( date _string in player _entries [ puuid ] ) {
const current _points = rank _to _points ( player _entries [ puuid ] [ date _string ] [ "tier" ] , player _entries [ puuid ] [ date _string ] [ "rank" ] , player _entries [ puuid ] [ date _string ] [ "points" ] ) ;
player _points [ puuid ] . push ( current _points ) ;
player _entries _byName [ ` ${ player _accounts [ puuid ] [ "gameName" ] } # ${ player _accounts [ puuid ] [ "tagLine" ] } ` ] [ date _string ] = player _entries [ puuid ] [ date _string ] ;
if ( player _start _points === - 1 ) {
player _start _points = current _points ;
player _pointprogress [ puuid ] . push ( 0 ) ;
} else {
player _pointprogress [ puuid ] . push ( current _points - player _start _points ) ;
}
const current _points = rank _to _points ( player _entries [ puuid ] [ timestamp ] [ "tier" ] , player _entries [ puuid ] [ timestamp ] [ "rank" ] , player _entries [ puuid ] [ timestamp ] [ "points" ] ) ;
player _rank _values [ puuid ] . push ( { x : parseInt ( timestamp ) * 1000 , y : current _points } ) ;
player _entries _byName [ ` ${ player _accounts [ puuid ] [ "gameName" ] } # ${ player _accounts [ puuid ] [ "tagLine" ] } ` ] [ timestamp ] = player _entries [ puuid ] [ timestamp ] ;
if ( player _start _points === - 1 ) {
player _start _points = current _points ;
player _progress _values [ puuid ] . push ( { x : parseInt ( timestamp ) * 1000 , y : 0 } ) ;
} else {
player _points [ puuid ] . push ( null ) ;
player _pointprogress [ puuid ] . push ( null ) ;
player _progress _values [ puuid ] . push ( { x : parseInt ( timestamp ) * 1000 , y : current _points - player _start _points } ) ;
}
}
// Linie für den Spieler zu Datasets des Graphen hinzufügen
@ -56,24 +135,25 @@ window.onload = async function(){
fill : false ,
borderColor : getColor ( color _counter ) ,
backgroundColor : getColor ( color _counter ) ,
data : player _point s [ puuid ] ,
data : player _rank _value s [ puuid ] ,
spanGaps : true ,
pointHitRadius : 16 ,
} )
all _progress _yDatasets . push ( {
label : ` ${ player _accounts [ puuid ] [ "gameName" ] } # ${ player _accounts [ puuid ] [ "tagLine" ] } ` ,
fill : false ,
borderColor : getColor ( color _counter ) ,
backgroundColor : getColor ( color _counter ) ,
data : player _pointp rogress [ puuid ] ,
data : player _progress _value s [ puuid ] ,
spanGaps : true ,
pointHitRadius : 16 ,
} )
color _counter ++ ;
}
// Graphen erstellen
new Chart ( ` progress-chart-combined ` , {
combined _charts . push ( new Chart ( ` progress-chart-combined ` , {
type : "line" ,
data : {
labels : all _dates ,
datasets : all _rank _yDatasets ,
} ,
options : {
@ -81,15 +161,18 @@ window.onload = async function(){
tooltip : {
callbacks : {
label : function ( context ) {
return format _rank ( player _entries _byName [ context . dataset . label ] [ context . label ] [ "tier" ] , player _entries _byName [ context . dataset . label ] [ context . label ] [ "rank" ] , player _entries _byName [ context . dataset . label ] [ context . label ] [ "points" ] )
return format _rank ( player _entries _byName [ context . dataset . label ] [ context . parsed . x / 1000 ] [ "tier" ] , player _entries _byName [ context . dataset . label ] [ context . parsed . x / 1000 ] [ "rank" ] , player _entries _byName [ context . dataset . label ] [ context . parsed . x / 1000 ] [ "points" ] )
} ,
beforeTitle : function ( context ) {
return context [ 0 ] . dataset . label ;
} ,
}
}
} ,
zoom : zoom _plugin ,
legend : legend _plugin ,
} ,
scales : {
x : x _scale ,
y : {
display : true ,
stepSize : 100 ,
@ -103,11 +186,10 @@ window.onload = async function(){
responsive : true ,
maintainAspectRatio : false ,
}
} ) ;
new Chart ( ` progress-chart-combined-progress ` , {
} ) ) ;
combined _charts . push ( new Chart ( ` progress-chart-combined-progress ` , {
type : "line" ,
data : {
labels : all _dates ,
datasets : all _progress _yDatasets ,
} ,
options : {
@ -115,15 +197,18 @@ window.onload = async function(){
tooltip : {
callbacks : {
label : function ( context ) {
return format _rank ( player _entries _byName [ context . dataset . label ] [ context . label ] [ "tier" ] , player _entries _byName [ context . dataset . label ] [ context . label ] [ "rank" ] , player _entries _byName [ context . dataset . label ] [ context . label ] [ "points" ] )
return format _rank ( player _entries _byName [ context . dataset . label ] [ context . parsed . x / 1000 ] [ "tier" ] , player _entries _byName [ context . dataset . label ] [ context . parsed . x / 1000 ] [ "rank" ] , player _entries _byName [ context . dataset . label ] [ context . parsed . x / 1000 ] [ "points" ] )
} ,
beforeTitle : function ( context ) {
return context [ 0 ] . dataset . label ;
} ,
}
}
} ,
zoom : zoom _plugin ,
legend : legend _plugin ,
} ,
scales : {
x : x _scale ,
y : {
display : true ,
} ,
@ -131,7 +216,7 @@ window.onload = async function(){
responsive : true ,
maintainAspectRatio : false ,
}
} ) ;
} ) ) ;
} )
. catch ( e => console . error ( e ) )
@ -140,23 +225,21 @@ window.onload = async function(){
let puuid = chart . id . split ( "-" ) ;
puuid . splice ( 0 , 2 ) ;
puuid = puuid . join ( "-" ) ;
let xValues = [ ] ;
let yValues = [ ] ;
let values = [ ] ;
for ( const entriesKey in player _entries [ puuid ] ) {
let points = rank _to _points ( player _entries [ puuid ] [ entriesKey ] [ "tier" ] , player _entries [ puuid ] [ entriesKey ] [ "rank" ] , player _entries [ puuid ] [ entriesKey ] [ "points" ] ) ;
xValues . push ( entriesKey ) ;
yValues . push ( points ) ;
values . push ( { x : parseInt ( entriesKey ) * 1000 , y : points } ) ;
}
new Chart ( ` progress-chart- ${ puuid } ` , {
player _charts . push ( new Chart ( ` progress-chart- ${ puuid } ` , {
type : "line" ,
data : {
labels : xValues ,
datasets : [ {
label : ` ${ player _accounts [ puuid ] [ "gameName" ] } # ${ player _accounts [ puuid ] [ "tagLine" ] } ` ,
fill : false ,
borderColor : "rgba(150,150,175)" ,
backgroundColor : "rgba(150,150,175)" ,
data : yValues
data : values ,
pointHitRadius : 16 ,
} ]
} ,
options : {
@ -165,15 +248,17 @@ window.onload = async function(){
tooltip : {
callbacks : {
label : function ( context ) {
return format _rank ( player _entries [ puuid ] [ context . label ] [ "tier" ] , player _entries [ puuid ] [ context . label ] [ "rank" ] , player _entries [ puuid ] [ context . label ] [ "points" ] )
return format _rank ( player _entries [ puuid ] [ context . parsed . x / 1000 ] [ "tier" ] , player _entries [ puuid ] [ context . parsed . x / 1000 ] [ "rank" ] , player _entries [ puuid ] [ context . parsed . x / 1000 ] [ "points" ] )
} ,
beforeTitle : function ( context ) {
return context [ 0 ] . dataset . label ;
} ,
}
}
} ,
zoom : zoom _plugin ,
} ,
scales : {
x : x _scale ,
y : {
display : true ,
stepSize : 100 ,
@ -187,10 +272,9 @@ window.onload = async function(){
responsive : true ,
maintainAspectRatio : false ,
}
} ) ;
} ) ) ;
}
} ;
}
function rank _to _points ( tier , rank , lp ) {
const apex _tiers = ( tier === "MASTER" || tier === "GRANDMASTER" || tier === "CHALLENGER" ) ;
@ -267,12 +351,80 @@ function toggle_combined_chart() {
chart . classList . add ( "closed" ) ;
}
}
function toggle _leaderboard _chart ( ) {
function toggle _leaderboard _chart ( event ) {
if ( this . classList . contains ( "closed" ) ) {
this . classList . remove ( "closed" ) ;
} else {
if ( event . target . nodeName === "CANVAS" ) return ;
this . classList . add ( "closed" ) ;
}
}
document . querySelectorAll ( "button.open-general-graph" ) . forEach ( element => element . addEventListener ( "click" , toggle _combined _chart ) ) ;
document . querySelectorAll ( "button.leaderboard-element" ) . forEach ( element => element . addEventListener ( "click" , toggle _leaderboard _chart ) ) ;
document . querySelectorAll ( "button.leaderboard-element" ) . forEach ( element => element . addEventListener ( "mousedown" , toggle _leaderboard _chart ) ) ;
async function update _leaderboard _entries ( ) {
this . disabled = true ;
this . classList . add ( "button-updating" )
let eventSource = new EventSource ( "./update.php" ) ;
eventSource . addEventListener ( "progress" , e => {
this . style . setProperty ( "--button-loading-bar-width" , ` ${ e . data * 100 } % ` ) ;
} )
eventSource . addEventListener ( "forbidden" , e => {
const currenttime = new Date ( ) ;
const updatetime = new Date ( e . data ) ;
let timediff = new Date ( currenttime - updatetime ) ;
let resttime = new Date ( 600000 - ( currenttime - updatetime ) ) ;
window . alert ( ` Das letzte Update wurde vor ${ format _time _minsec ( timediff ) } durchgeführt. Versuche es in ${ format _time _minsec ( resttime ) } noch einmal ` ) ;
reset _button ( this ) ;
eventSource . close ( ) ;
} )
eventSource . onerror = e => {
window . alert ( ` Beim Update ist ein Fehler aufgetreten. Versuche es später noch einmal ` )
reset _button ( this ) ;
eventSource . close ( ) ;
}
eventSource . addEventListener ( "done" , e => {
reset _button ( this ) ;
eventSource . close ( ) ;
update _leaderboard _elements ( ) ;
} )
function reset _button ( button ) {
button . disabled = false ;
button . style . setProperty ( "--button-loading-bar-width" , ` 0 ` ) ;
button . classList . remove ( "button-updating" ) ;
}
}
document . querySelector ( "button.update-leaderboard" ) . addEventListener ( "click" , update _leaderboard _entries ) ;
function format _time _minsec ( date ) {
let format , trenner = "" , min = "" , nullausgleich = "" ;
if ( date . getMinutes ( ) === 0 ) {
format = " Sekunden" ;
} else {
min = date . getMinutes ( ) ;
format = " Minuten" ;
trenner = ":" ;
if ( date . getSeconds ( ) < 10 ) {
nullausgleich = "0" ;
}
}
return min + trenner + nullausgleich + date . getSeconds ( ) + format ;
}
const month _names = [ "Jan" , "Feb" , "Mär" , "Apr" , "Mai" , "Jun" , "Jul" , "Aug" , "Sep" , "Okt" , "Nov" , "Dez" ] ;
async function update _leaderboard _elements ( ) {
fetch ( ` ./leaderboard_list.php ` , {
method : "GET" ,
} )
. then ( res => res . text ( ) )
. then ( leaderboard _list => {
// replace updated Leaderboard
document . querySelector ( ".leaderboard-list" ) . outerHTML = leaderboard _list ;
// reapply EventListeners
document . querySelectorAll ( "button.leaderboard-element" ) . forEach ( element => element . addEventListener ( "click" , toggle _leaderboard _chart ) ) ;
// recreate charts
create _charts ( ) ;
} )
. catch ( e => console . error ( e ) ) ;
}