2020-03-06 01:02:07 +01:00
|
|
|
class ScoreStorage{
|
|
|
|
constructor(){
|
|
|
|
this.scores = {}
|
2020-03-16 20:49:18 +01:00
|
|
|
this.scoresP2 = {}
|
|
|
|
this.requestP2 = new Set()
|
|
|
|
this.requestedP2 = new Set()
|
2020-03-07 02:48:30 +01:00
|
|
|
this.songTitles = {}
|
2020-03-06 01:02:07 +01:00
|
|
|
this.difficulty = ["oni", "ura", "hard", "normal", "easy"]
|
|
|
|
this.scoreKeys = ["points", "good", "ok", "bad", "maxCombo", "drumroll"]
|
|
|
|
this.crownValue = ["", "silver", "gold"]
|
|
|
|
}
|
2020-03-14 05:50:04 +01:00
|
|
|
load(strings, loadFailed){
|
|
|
|
var scores = {}
|
|
|
|
var scoreStrings = {}
|
|
|
|
if(loadFailed){
|
|
|
|
try{
|
|
|
|
var localScores = localStorage.getItem("saveFailed")
|
|
|
|
if(localScores){
|
|
|
|
scoreStrings = JSON.parse(localScores)
|
|
|
|
}
|
|
|
|
}catch(e){}
|
|
|
|
}else if(strings){
|
|
|
|
scoreStrings = this.prepareStrings(strings)
|
2020-03-13 03:34:54 +01:00
|
|
|
}else if(account.loggedIn){
|
|
|
|
return
|
|
|
|
}else{
|
|
|
|
try{
|
|
|
|
var localScores = localStorage.getItem("scoreStorage")
|
|
|
|
if(localScores){
|
2020-03-14 05:50:04 +01:00
|
|
|
scoreStrings = JSON.parse(localScores)
|
2020-03-13 03:34:54 +01:00
|
|
|
}
|
|
|
|
}catch(e){}
|
|
|
|
}
|
2020-03-14 05:50:04 +01:00
|
|
|
for(var hash in scoreStrings){
|
|
|
|
var scoreString = scoreStrings[hash]
|
2020-03-06 01:02:07 +01:00
|
|
|
var songAdded = false
|
|
|
|
if(typeof scoreString === "string" && scoreString){
|
|
|
|
var diffArray = scoreString.split(";")
|
|
|
|
for(var i in this.difficulty){
|
|
|
|
if(diffArray[i]){
|
|
|
|
var crown = parseInt(diffArray[i].slice(0, 1)) || 0
|
|
|
|
var score = {
|
|
|
|
crown: this.crownValue[crown] || ""
|
|
|
|
}
|
|
|
|
var scoreArray = diffArray[i].slice(1).split(",")
|
|
|
|
for(var j in this.scoreKeys){
|
|
|
|
var name = this.scoreKeys[j]
|
|
|
|
var value = parseInt(scoreArray[j], 36) || 0
|
|
|
|
if(value < 0){
|
|
|
|
value = 0
|
|
|
|
}
|
|
|
|
score[name] = value
|
|
|
|
}
|
|
|
|
if(!songAdded){
|
2020-03-14 05:50:04 +01:00
|
|
|
scores[hash] = {title: null}
|
2020-03-06 01:02:07 +01:00
|
|
|
songAdded = true
|
|
|
|
}
|
2020-03-14 05:50:04 +01:00
|
|
|
scores[hash][this.difficulty[i]] = score
|
2020-03-06 01:02:07 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-03-14 05:50:04 +01:00
|
|
|
if(loadFailed){
|
|
|
|
for(var hash in scores){
|
|
|
|
for(var i in this.difficulty){
|
|
|
|
var diff = this.difficulty[i]
|
|
|
|
if(scores[hash][diff]){
|
|
|
|
this.add(hash, diff, scores[hash][diff], true, this.songTitles[hash] || null).then(() => {
|
|
|
|
localStorage.removeItem("saveFailed")
|
|
|
|
}, () => {})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
this.scores = scores
|
|
|
|
this.scoreStrings = scoreStrings
|
|
|
|
}
|
|
|
|
if(strings){
|
|
|
|
this.load(false, true)
|
|
|
|
}
|
2020-03-06 01:02:07 +01:00
|
|
|
}
|
2020-03-13 04:19:26 +01:00
|
|
|
prepareScores(scores){
|
|
|
|
var output = []
|
|
|
|
for (var k in scores) {
|
2020-03-13 04:54:27 +01:00
|
|
|
output.push({'hash': k, 'score': scores[k]})
|
2020-03-13 04:19:26 +01:00
|
|
|
}
|
|
|
|
return output
|
|
|
|
}
|
2020-03-13 06:32:53 +01:00
|
|
|
prepareStrings(scores){
|
|
|
|
var output = {}
|
|
|
|
for(var k in scores){
|
|
|
|
output[scores[k].hash] = scores[k].score
|
|
|
|
}
|
|
|
|
return output
|
|
|
|
}
|
2020-03-25 22:56:49 +01:00
|
|
|
save(){
|
2020-03-07 02:48:30 +01:00
|
|
|
for(var hash in this.scores){
|
|
|
|
this.writeString(hash)
|
2020-03-06 01:02:07 +01:00
|
|
|
}
|
|
|
|
this.write()
|
2020-03-13 03:34:54 +01:00
|
|
|
return this.sendToServer({
|
2020-03-13 04:19:26 +01:00
|
|
|
scores: this.prepareScores(this.scoreStrings),
|
2020-03-13 03:34:54 +01:00
|
|
|
is_import: true
|
|
|
|
})
|
2020-03-06 01:02:07 +01:00
|
|
|
}
|
|
|
|
write(){
|
2020-03-13 03:34:54 +01:00
|
|
|
if(!account.loggedIn){
|
|
|
|
try{
|
|
|
|
localStorage.setItem("scoreStorage", JSON.stringify(this.scoreStrings))
|
|
|
|
}catch(e){}
|
|
|
|
}
|
2020-03-06 01:02:07 +01:00
|
|
|
}
|
2020-03-07 02:48:30 +01:00
|
|
|
writeString(hash){
|
|
|
|
var score = this.scores[hash]
|
2020-03-06 01:02:07 +01:00
|
|
|
var diffArray = []
|
|
|
|
var notEmpty = false
|
|
|
|
for(var i = this.difficulty.length; i--;){
|
|
|
|
var diff = this.difficulty[i]
|
|
|
|
if(score[diff]){
|
|
|
|
var scoreArray = []
|
|
|
|
var crown = this.crownValue.indexOf(score[diff].crown).toString()
|
|
|
|
for(var j in this.scoreKeys){
|
|
|
|
var name = this.scoreKeys[j]
|
|
|
|
var value = score[diff][name]
|
|
|
|
value = Math.floor(value).toString(36)
|
|
|
|
scoreArray.push(value)
|
|
|
|
}
|
|
|
|
diffArray.unshift(crown + scoreArray.join(","))
|
|
|
|
notEmpty = true
|
|
|
|
}else if(notEmpty){
|
|
|
|
diffArray.unshift("")
|
|
|
|
}
|
|
|
|
}
|
2020-03-07 02:48:30 +01:00
|
|
|
this.scoreStrings[hash] = diffArray.join(";")
|
2020-03-06 01:02:07 +01:00
|
|
|
}
|
2020-03-07 02:48:30 +01:00
|
|
|
titleHash(song){
|
|
|
|
if(song in this.songTitles){
|
|
|
|
return this.songTitles[song]
|
|
|
|
}else{
|
|
|
|
return song
|
|
|
|
}
|
|
|
|
}
|
|
|
|
get(song, difficulty, isHash){
|
2020-03-06 01:02:07 +01:00
|
|
|
if(!song){
|
|
|
|
return this.scores
|
2020-03-07 02:48:30 +01:00
|
|
|
}else{
|
|
|
|
var hash = isHash ? song : this.titleHash(song)
|
2020-03-06 01:02:07 +01:00
|
|
|
if(difficulty){
|
2020-03-07 02:48:30 +01:00
|
|
|
if(hash in this.scores){
|
|
|
|
return this.scores[hash][difficulty]
|
|
|
|
}
|
2020-03-06 01:02:07 +01:00
|
|
|
}else{
|
2020-03-07 02:48:30 +01:00
|
|
|
return this.scores[hash]
|
2020-03-06 01:02:07 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-03-16 20:49:18 +01:00
|
|
|
getP2(song, difficulty, isHash){
|
|
|
|
if(!song){
|
|
|
|
return this.scoresP2
|
|
|
|
}else{
|
|
|
|
var hash = isHash ? song : this.titleHash(song)
|
|
|
|
if(!(hash in this.scoresP2) && !this.requestP2.has(hash) && !this.requestedP2.has(hash)){
|
|
|
|
this.requestP2.add(hash)
|
|
|
|
this.requestedP2.add(hash)
|
|
|
|
}
|
|
|
|
if(difficulty){
|
|
|
|
if(hash in this.scoresP2){
|
|
|
|
return this.scoresP2[hash][difficulty]
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
return this.scoresP2[hash]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-03-14 05:50:04 +01:00
|
|
|
add(song, difficulty, scoreObject, isHash, setTitle, saveFailed){
|
2020-03-07 02:48:30 +01:00
|
|
|
var hash = isHash ? song : this.titleHash(song)
|
|
|
|
if(!(hash in this.scores)){
|
|
|
|
this.scores[hash] = {}
|
|
|
|
}
|
2020-03-16 20:49:18 +01:00
|
|
|
if(difficulty){
|
|
|
|
if(setTitle){
|
|
|
|
this.scores[hash].title = setTitle
|
|
|
|
}
|
|
|
|
this.scores[hash][difficulty] = scoreObject
|
|
|
|
}else{
|
|
|
|
this.scores[hash] = scoreObject
|
|
|
|
if(setTitle){
|
|
|
|
this.scores[hash].title = setTitle
|
|
|
|
}
|
2020-03-06 01:02:07 +01:00
|
|
|
}
|
2020-03-07 02:48:30 +01:00
|
|
|
this.writeString(hash)
|
2020-03-06 01:02:07 +01:00
|
|
|
this.write()
|
2020-03-14 05:50:04 +01:00
|
|
|
if(saveFailed){
|
|
|
|
var failedScores = {}
|
|
|
|
try{
|
|
|
|
var localScores = localStorage.getItem("saveFailed")
|
|
|
|
if(localScores){
|
|
|
|
failedScores = JSON.parse(localScores)
|
|
|
|
}
|
|
|
|
}catch(e){}
|
|
|
|
if(!(hash in failedScores)){
|
|
|
|
failedScores[hash] = {}
|
|
|
|
}
|
|
|
|
failedScores[hash] = this.scoreStrings[hash]
|
|
|
|
try{
|
|
|
|
localStorage.setItem("saveFailed", JSON.stringify(failedScores))
|
|
|
|
}catch(e){}
|
|
|
|
return Promise.reject()
|
|
|
|
}else{
|
|
|
|
var obj = {}
|
|
|
|
obj[hash] = this.scoreStrings[hash]
|
|
|
|
return this.sendToServer({
|
|
|
|
scores: this.prepareScores(obj)
|
|
|
|
}).catch(() => this.add(song, difficulty, scoreObject, isHash, setTitle, true))
|
|
|
|
}
|
2020-03-06 01:02:07 +01:00
|
|
|
}
|
2020-03-16 20:49:18 +01:00
|
|
|
addP2(song, difficulty, scoreObject, isHash, setTitle){
|
|
|
|
var hash = isHash ? song : this.titleHash(song)
|
|
|
|
if(!(hash in this.scores)){
|
|
|
|
this.scoresP2[hash] = {}
|
|
|
|
}
|
|
|
|
if(difficulty){
|
|
|
|
if(setTitle){
|
|
|
|
this.scoresP2[hash].title = setTitle
|
|
|
|
}
|
|
|
|
this.scoresP2[hash][difficulty] = scoreObject
|
|
|
|
}else{
|
|
|
|
this.scoresP2[hash] = scoreObject
|
|
|
|
if(setTitle){
|
|
|
|
this.scoresP2[hash].title = setTitle
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-03-06 01:02:07 +01:00
|
|
|
template(){
|
|
|
|
var template = {crown: ""}
|
|
|
|
for(var i in this.scoreKeys){
|
|
|
|
var name = this.scoreKeys[i]
|
|
|
|
template[name] = 0
|
|
|
|
}
|
|
|
|
return template
|
|
|
|
}
|
2020-03-07 02:48:30 +01:00
|
|
|
remove(song, difficulty, isHash){
|
|
|
|
var hash = isHash ? song : this.titleHash(song)
|
|
|
|
if(hash in this.scores){
|
2020-03-06 01:02:07 +01:00
|
|
|
if(difficulty){
|
2020-03-07 02:48:30 +01:00
|
|
|
if(difficulty in this.scores[hash]){
|
|
|
|
delete this.scores[hash][difficulty]
|
2020-03-06 01:02:07 +01:00
|
|
|
var noDiff = true
|
|
|
|
for(var i in this.difficulty){
|
2020-03-07 02:48:30 +01:00
|
|
|
if(this.scores[hash][this.difficulty[i]]){
|
2020-03-06 01:02:07 +01:00
|
|
|
noDiff = false
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(noDiff){
|
2020-03-07 02:48:30 +01:00
|
|
|
delete this.scores[hash]
|
|
|
|
delete this.scoreStrings[hash]
|
2020-03-06 01:02:07 +01:00
|
|
|
}else{
|
2020-03-07 02:48:30 +01:00
|
|
|
this.writeString(hash)
|
2020-03-06 01:02:07 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}else{
|
2020-03-07 02:48:30 +01:00
|
|
|
delete this.scores[hash]
|
|
|
|
delete this.scoreStrings[hash]
|
2020-03-06 01:02:07 +01:00
|
|
|
}
|
|
|
|
this.write()
|
2020-03-13 03:34:54 +01:00
|
|
|
this.sendToServer({
|
2020-03-13 04:19:26 +01:00
|
|
|
scores: this.prepareScores(this.scoreStrings),
|
2020-03-13 03:34:54 +01:00
|
|
|
is_import: true
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sendToServer(obj, retry){
|
|
|
|
if(account.loggedIn){
|
2020-03-17 05:20:03 +01:00
|
|
|
return loader.getCsrfToken().then(token => {
|
|
|
|
var request = new XMLHttpRequest()
|
|
|
|
request.open("POST", "api/scores/save")
|
|
|
|
var promise = pageEvents.load(request).then(response => {
|
|
|
|
if(request.status !== 200){
|
|
|
|
return Promise.reject()
|
|
|
|
}
|
|
|
|
}).catch(() => {
|
|
|
|
if(retry){
|
|
|
|
this.scoreSaveFailed = true
|
|
|
|
account.loggedIn = false
|
|
|
|
delete account.username
|
|
|
|
delete account.displayName
|
|
|
|
this.load()
|
|
|
|
pageEvents.send("logout")
|
|
|
|
return Promise.reject()
|
|
|
|
}else{
|
|
|
|
return new Promise(resolve => {
|
|
|
|
setTimeout(() => {
|
|
|
|
resolve()
|
|
|
|
}, 3000)
|
|
|
|
}).then(() => this.sendToServer(obj, true))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
request.setRequestHeader("Content-Type", "application/json;charset=UTF-8")
|
|
|
|
request.setRequestHeader("X-CSRFToken", token)
|
|
|
|
request.send(JSON.stringify(obj))
|
|
|
|
return promise
|
2020-03-13 03:34:54 +01:00
|
|
|
})
|
|
|
|
}else{
|
|
|
|
return Promise.resolve()
|
2020-03-06 01:02:07 +01:00
|
|
|
}
|
|
|
|
}
|
2020-03-16 20:49:18 +01:00
|
|
|
eventLoop(){
|
|
|
|
if(p2.session && this.requestP2.size){
|
|
|
|
var req = []
|
|
|
|
this.requestP2.forEach(hash => {
|
|
|
|
req.push(hash)
|
|
|
|
})
|
|
|
|
this.requestP2.clear()
|
|
|
|
if(req.length){
|
|
|
|
p2.send("getcrowns", req)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
clearP2(){
|
|
|
|
this.scoresP2 = {}
|
|
|
|
this.requestP2.clear()
|
|
|
|
this.requestedP2.clear()
|
|
|
|
}
|
2020-03-06 01:02:07 +01:00
|
|
|
}
|