Files
junisaber/src/components/leaderboard.js
2018-12-02 22:20:43 -08:00

145 lines
4.3 KiB
JavaScript

const firebase = require('firebase/app');
require('firebase/firestore');
const NUM_SCORES_DISPLAYED = 10;
/**
* High score with Firebase cloud store.
* Index: challengeId ASC difficulty ASC score DESC time ASC
*/
AFRAME.registerComponent('leaderboard', {
schema: {
apiKey: {type: 'string'},
authDomain: {type: 'string'},
databaseURL: {type: 'string'},
projectId: {type: 'string'},
storageBucket: {type: 'string'},
messagingSenderId: {type: 'string'},
challengeId: {default: ''},
menuSelectedChallengeId: {default: ''},
isVictory: {default: false}
},
init: function () {
this.qualifyingIndex = undefined;
this.scores = [];
this.eventDetail = {scores: this.scores};
this.addEventDetail = {scoreData: undefined, index: undefined};
this.username = localStorage.getItem('supersaberusername') || 'Super Zealot';
this.el.addEventListener('leaderboardusername', evt => {
this.username = evt.detail.value;
localStorage.setItem('supersaberusername', this.username);
});
this.el.addEventListener('leaderboardsubmit', this.addScore.bind(this));
},
update: function (oldData) {
// Initialize Cloud Firestore through Firebase.
if (!firebase.apps.length && this.data.apiKey) {
firebase.initializeApp({
apiKey: this.data.apiKey,
authDomain: this.data.authDomain,
databaseURL: this.data.databaseURL,
projectId: this.data.projectId,
storageBucket: this.data.storageBucket,
messagingSenderId: this.data.messagingSenderId
});
this.firestore = firebase.firestore();
this.firestore.settings({timestampsInSnapshots: true});
this.db = this.firestore.collection('scores');
}
if (!oldData.isVictory && this.data.isVictory) {
this.checkLeaderboardQualify();
}
if (this.data.menuSelectedChallengeId &&
oldData.menuSelectedChallengeId !== this.data.menuSelectedChallengeId) {
this.fetchScores(this.data.menuSelectedChallengeId);
}
if (this.data.challengeId && oldData.challengeId !== this.data.challengeId) {
this.fetchScores(this.data.challengeId);
}
},
addScore: function () {
const state = this.el.sceneEl.systems.state.state;
if (!state.isVictory) { return; }
const scoreData = {
accuracy: state.score.accuracy,
challengeId: state.challenge.id,
score: state.score.score,
username: this.username,
difficulty: state.challenge.difficulty,
time: new Date()
};
this.db.add(scoreData);
this.addEventDetail.scoreData = scoreData;
this.el.emit('leaderboardscoreadded', this.addEventDetail, false);
},
fetchScores: function (challengeId) {
const state = this.el.sceneEl.systems.state.state;
const query = this.db
.where('challengeId', '==', challengeId)
.where(
'difficulty', '==',
state.menuSelectedChallenge.id
? state.menuSelectedChallenge.difficulty
: state.challenge.difficulty)
.orderBy('score', 'desc')
.orderBy('time', 'asc')
.limit(10);
query.get().then(snapshot => {
this.eventDetail.challengeId = challengeId;
this.scores.length = 0;
if (!snapshot.empty) {
snapshot.forEach(score => this.scores.push(score.data()));
}
this.el.sceneEl.emit('leaderboard', this.eventDetail, false);
}).catch(e => {
console.error('[firestore]', e);
});
},
/**
* Is high score?
*/
checkLeaderboardQualify: function () {
const state = this.el.sceneEl.systems.state.state;
const score = state.score.score;
// If less than 10, then automatic high score.
if (this.scores.length < NUM_SCORES_DISPLAYED) {
this.qualifyingIndex = this.scores.length;
this.el.sceneEl.emit('leaderboardqualify', this.scores.length, false);
return;
}
// Check if overtook any existing high score.
for (let i = 0; i < this.scores.length; i++) {
if (score > this.scores[i].score) {
this.qualifyingIndex = i;
this.el.sceneEl.emit('leaderboardqualify', i, false);
return;
}
}
}
});
AFRAME.registerComponent('leaderboard-title', {
schema: {
leaderboardQualified: {default: false}
},
update: function () {
const value = this.data.leaderboardQualified
? 'NEW HIGH SCORE!'
: 'LEADERBOARD';
this.el.setAttribute('text', 'value', value);
}
});