minesweeper/src/main/js/HighScores.ts

103 lines
2.9 KiB
TypeScript

import {formatTime} from "./Common";
import {difficulties, Difficulty} from "./Difficulty";
// @ts-ignore
const {Storage, LocalStorage} = window.fwdekker.storage;
/**
* A score obtained by clearing a field.
*/
export type Score = {time: number, deaths: number};
/**
* The highest scores.
*/
export class HighScores {
private static readonly scoresToStore: number = 10;
private readonly storage: Storage;
/**
* Constructs a new container for high scores.
*
* @param storage the underlying object to store high scores in
*/
constructor(storage: Storage = new LocalStorage("/tools/minesweeper//high-scores")) {
this.storage = storage;
}
/**
* Clears all high scores.
*/
clear(): void {
this.storage.clear();
}
/**
* Adds a new high score.
*
* @param difficulty the difficulty to associate the score to
* @param score the score to store
*/
addScore(difficulty: Difficulty, score: Score): void {
const scores = this.storage.getArray(difficulty.name, []);
scores.push(score);
scores.sort((a: Score, b: Score) => {
return Math.floor(a.time / 1000) !== Math.floor(b.time / 1000)
? a.time - b.time
: a.deaths - b.deaths;
});
this.storage.setArray(difficulty.name, scores.slice(0, HighScores.scoresToStore));
}
/**
* Returns all high scores associated with the given difficulty.
*
* @param difficulty the difficulty to return the high scores for
* @returns all high scores associated with the given difficulty
*/
getScores(difficulty: Difficulty): Score[] {
return this.storage.getArray(difficulty.name, []);
}
/**
* Generates an HTML report of all high scores.
*
* @returns an HTML report of all high scores
*/
generateHtmlReport(): string {
let report = "";
for (let i = 0; i < difficulties.length; i++) {
const difficulty = difficulties[i];
report += `<h3>${difficulty.name}</h3>`;
const highScores = this.getScores(difficulty);
if (highScores.length === 0) {
report += "<i>You have no high scores for this difficulty yet.</i><br /><br />";
continue;
}
report += "" +
`<table>
<tr>
<th></th>
<th>Time</th>
<th>Deaths</th>
</tr>`;
for (let j = 0; j < highScores.length; j++) {
const score = highScores[j];
report += "" +
`<tr>
<th>#${j + 1}</th>
<td>${formatTime(Math.floor(score.time / 1000), true, false)}</td>
<td>${score.deaths}</td>
</tr>`;
}
report += "</table>";
}
return report;
}
}