mirror of
https://framagit.org/JonathanMM/sutom.git
synced 2024-05-22 07:36:38 +02:00
Ajout option pour exporter les statistiques
This commit is contained in:
parent
51e43bf38c
commit
d2f035b1ef
|
@ -397,16 +397,16 @@ h1 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
#fin-de-partie-panel-resume-bouton {
|
.bouton-partage {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#fin-de-partie-panel-resume-bouton-icone {
|
.bouton-partage svg {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#fin-de-partie-panel-resume-bouton-texte {
|
.bouton-partage-texte {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,6 +415,14 @@ h1 {
|
||||||
padding-left: 0.5em;
|
padding-left: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#config-sauvegarde-area {
|
||||||
|
text-align: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
#config-sauvegarde-area p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 1024px) {
|
@media (max-width: 1024px) {
|
||||||
#contenu {
|
#contenu {
|
||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { ClavierDisposition } from "./entites/clavierDisposition";
|
||||||
import Input from "./input";
|
import Input from "./input";
|
||||||
import ThemeManager from "./themeManager";
|
import ThemeManager from "./themeManager";
|
||||||
import { Theme } from "./entites/theme";
|
import { Theme } from "./entites/theme";
|
||||||
|
import CopieHelper from "./copieHelper";
|
||||||
|
|
||||||
export default class ConfigurationPanel {
|
export default class ConfigurationPanel {
|
||||||
private readonly _panelManager: PanelManager;
|
private readonly _panelManager: PanelManager;
|
||||||
|
@ -128,6 +129,8 @@ export default class ConfigurationPanel {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
contenu.appendChild(this.genererZoneExportSauvegarde());
|
||||||
|
|
||||||
this._panelManager.setContenuHtmlElement(titre, contenu);
|
this._panelManager.setContenuHtmlElement(titre, contenu);
|
||||||
this._panelManager.setClasses(["config-panel"]);
|
this._panelManager.setClasses(["config-panel"]);
|
||||||
this._panelManager.afficherPanel();
|
this._panelManager.afficherPanel();
|
||||||
|
@ -160,6 +163,52 @@ export default class ConfigurationPanel {
|
||||||
return div;
|
return div;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private genererZoneExportSauvegarde(): HTMLElement {
|
||||||
|
let div = document.createElement("div");
|
||||||
|
div.id = "config-sauvegarde-area";
|
||||||
|
|
||||||
|
const titreSection = document.createElement("h3");
|
||||||
|
titreSection.innerText = "Exporter vos statistiques";
|
||||||
|
div.appendChild(titreSection);
|
||||||
|
|
||||||
|
const explication = document.createElement("p");
|
||||||
|
explication.innerText = "Pour transférer vos statistiques sur un autre navigateur, il est possible de suivre les étapes suivantes :";
|
||||||
|
div.appendChild(explication);
|
||||||
|
|
||||||
|
const listeEtape = document.createElement("ol");
|
||||||
|
|
||||||
|
const etape1 = document.createElement("li");
|
||||||
|
|
||||||
|
const etape1Texte = document.createElement("p");
|
||||||
|
etape1Texte.innerText = "Copiez ce lien à usage unique.";
|
||||||
|
etape1.appendChild(etape1Texte);
|
||||||
|
|
||||||
|
const etape1Input = document.createElement("input");
|
||||||
|
const contenuLien = Sauvegardeur.genererLien();
|
||||||
|
const lien = window.location.origin + window.location.pathname + "#" + btoa("s=" + contenuLien);
|
||||||
|
etape1Input.value = lien;
|
||||||
|
etape1Input.readOnly = true;
|
||||||
|
etape1.appendChild(etape1Input);
|
||||||
|
|
||||||
|
const etape1Bouton = CopieHelper.creerBoutonPartage("config-sauvegarde-bouton");
|
||||||
|
CopieHelper.attacheBoutonCopieLien(etape1Bouton, lien, "Lien copié dans le presse papier.");
|
||||||
|
etape1.appendChild(etape1Bouton);
|
||||||
|
|
||||||
|
listeEtape.appendChild(etape1);
|
||||||
|
|
||||||
|
const etape2 = document.createElement("li");
|
||||||
|
etape2.innerText = "Envoyez le lien vers votre autre appareil.";
|
||||||
|
listeEtape.appendChild(etape2);
|
||||||
|
|
||||||
|
const etape3 = document.createElement("li");
|
||||||
|
etape3.innerText = "Ouvrez ce lien dans votre autre navigateur.";
|
||||||
|
listeEtape.appendChild(etape3);
|
||||||
|
|
||||||
|
div.appendChild(listeEtape);
|
||||||
|
|
||||||
|
return div;
|
||||||
|
}
|
||||||
|
|
||||||
public setInput(input: Input): void {
|
public setInput(input: Input): void {
|
||||||
this._input = input;
|
this._input = input;
|
||||||
}
|
}
|
||||||
|
|
54
ts/copieHelper.ts
Normal file
54
ts/copieHelper.ts
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import NotificationMessage from "./notificationMessage";
|
||||||
|
|
||||||
|
export default class CopieHelper {
|
||||||
|
public static attacheBoutonCopieLien(bouton: HTMLElement, lien: string, messageSucces: string): void {
|
||||||
|
bouton.addEventListener("click", (event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
if (window.navigator.clipboard !== undefined) {
|
||||||
|
return resolve(window.navigator.clipboard.writeText(lien));
|
||||||
|
}
|
||||||
|
|
||||||
|
return reject();
|
||||||
|
})
|
||||||
|
.catch(
|
||||||
|
() =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
if (window.navigator.share !== undefined) return resolve(navigator.share({ text: lien }));
|
||||||
|
|
||||||
|
return reject();
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
|
NotificationMessage.ajouterNotificationPanel(messageSucces, bouton);
|
||||||
|
})
|
||||||
|
.catch((raison) => {
|
||||||
|
NotificationMessage.ajouterNotificationPanel("Votre navigateur n'est pas compatible.", bouton);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static creerBoutonPartage(idBouton: string, label?: string): HTMLElement {
|
||||||
|
const lien = document.createElement("a");
|
||||||
|
lien.id = idBouton;
|
||||||
|
lien.className = "bouton-partage";
|
||||||
|
lien.href = "#";
|
||||||
|
|
||||||
|
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||||
|
const useSvg = document.createElementNS("http://www.w3.org/2000/svg", "use") as SVGUseElement;
|
||||||
|
useSvg.setAttribute("href", "#icone-copie");
|
||||||
|
useSvg.setAttribute("stroke", "var(--couleur-icone)");
|
||||||
|
useSvg.setAttribute("fill", "var(--couleur-icone)");
|
||||||
|
svg.appendChild(useSvg);
|
||||||
|
lien.appendChild(svg);
|
||||||
|
|
||||||
|
if (label) {
|
||||||
|
const texteBouton = document.createElement("span");
|
||||||
|
texteBouton.className = "bouton-partage-texte";
|
||||||
|
texteBouton.innerText = label;
|
||||||
|
lien.appendChild(texteBouton);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lien;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
|
import CopieHelper from "./copieHelper";
|
||||||
import Configuration from "./entites/configuration";
|
import Configuration from "./entites/configuration";
|
||||||
import LettreResultat from "./entites/lettreResultat";
|
import LettreResultat from "./entites/lettreResultat";
|
||||||
import { LettreStatut } from "./entites/lettreStatut";
|
import { LettreStatut } from "./entites/lettreStatut";
|
||||||
import InstanceConfiguration from "./instanceConfiguration";
|
import InstanceConfiguration from "./instanceConfiguration";
|
||||||
import NotificationMessage from "./notificationMessage";
|
|
||||||
import PanelManager from "./panelManager";
|
import PanelManager from "./panelManager";
|
||||||
import Sauvegardeur from "./sauvegardeur";
|
import Sauvegardeur from "./sauvegardeur";
|
||||||
|
|
||||||
|
@ -104,31 +104,8 @@ export default class FinDePartiePanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private attacherPartage(): void {
|
private attacherPartage(): void {
|
||||||
let resumeBouton = document.getElementById("fin-de-partie-panel-resume-bouton") as HTMLElement;
|
const resumeBouton = document.getElementById("fin-de-partie-panel-resume-bouton") as HTMLElement;
|
||||||
resumeBouton.addEventListener("click", (event) => {
|
CopieHelper.attacheBoutonCopieLien(resumeBouton, this._resumeTexte + "\n\nhttps://sutom.nocle.fr", "Résumé copié dans le presse papier.");
|
||||||
event.stopPropagation();
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
if (window.navigator.clipboard !== undefined) {
|
|
||||||
return resolve(window.navigator.clipboard.writeText(this._resumeTexte + "\n\nhttps://sutom.nocle.fr"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return reject();
|
|
||||||
})
|
|
||||||
.catch(
|
|
||||||
() =>
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
if (window.navigator.share !== undefined) return resolve(navigator.share({ text: this._resumeTexte + "\n\nhttps://sutom.nocle.fr" }));
|
|
||||||
|
|
||||||
return reject();
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.then(() => {
|
|
||||||
NotificationMessage.ajouterNotificationPanel("Résumé copié dans le presse-papier.", resumeBouton);
|
|
||||||
})
|
|
||||||
.catch((raison) => {
|
|
||||||
NotificationMessage.ajouterNotificationPanel("Votre navigateur n'est pas compatible.", resumeBouton);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public afficher(): void {
|
public afficher(): void {
|
||||||
|
@ -152,12 +129,10 @@ export default class FinDePartiePanel {
|
||||||
Peut-être feras-tu mieux demain ? \
|
Peut-être feras-tu mieux demain ? \
|
||||||
</p>";
|
</p>";
|
||||||
}
|
}
|
||||||
|
contenu += "<p>Résumé de ta partie − ";
|
||||||
|
contenu += CopieHelper.creerBoutonPartage("fin-de-partie-panel-resume-bouton", "Partager").outerHTML;
|
||||||
contenu +=
|
contenu +=
|
||||||
'<p>Résumé de ta partie − \
|
'</p> \
|
||||||
<a href="#" id="fin-de-partie-panel-resume-bouton"><svg id="fin-de-partie-panel-resume-bouton-icone"> \
|
|
||||||
<use href="#icone-copie" stroke="var(--couleur-icone)" fill="var(--couleur-icone)"></use> \
|
|
||||||
</svg> \
|
|
||||||
<span id="fin-de-partie-panel-resume-bouton-texte">Partager</span></a></p> \
|
|
||||||
<pre id="fin-de-partie-panel-resume">' +
|
<pre id="fin-de-partie-panel-resume">' +
|
||||||
this._resumeTexteLegacy +
|
this._resumeTexteLegacy +
|
||||||
"</pre>";
|
"</pre>";
|
||||||
|
|
|
@ -15,6 +15,7 @@ import ConfigurationPanel from "./configurationPanel";
|
||||||
import AudioPanel from "./audioPanel";
|
import AudioPanel from "./audioPanel";
|
||||||
import ThemeManager from "./themeManager";
|
import ThemeManager from "./themeManager";
|
||||||
import InstanceConfiguration from "./instanceConfiguration";
|
import InstanceConfiguration from "./instanceConfiguration";
|
||||||
|
import LienHelper from "./lienHelper";
|
||||||
|
|
||||||
export default class Gestionnaire {
|
export default class Gestionnaire {
|
||||||
private _grille: Grille | null = null;
|
private _grille: Grille | null = null;
|
||||||
|
@ -83,19 +84,9 @@ export default class Gestionnaire {
|
||||||
}
|
}
|
||||||
|
|
||||||
private getIdPartie(partieEnCours: PartieEnCours) {
|
private getIdPartie(partieEnCours: PartieEnCours) {
|
||||||
if (window.location.hash !== "" && window.location.hash !== "#") {
|
const infoDansLocation = LienHelper.extraireInformation("p");
|
||||||
let hashPart = atob(window.location.hash.substring(1)).split("/");
|
|
||||||
for (let infoPos in hashPart) {
|
|
||||||
let info = hashPart[infoPos];
|
|
||||||
if (!info.includes("=")) continue;
|
|
||||||
let infoPart = info.split("=");
|
|
||||||
let infoKey = infoPart[0];
|
|
||||||
|
|
||||||
if (infoKey !== "p") continue;
|
if (infoDansLocation !== null) return infoDansLocation;
|
||||||
|
|
||||||
return infoPart[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (partieEnCours.idPartie !== undefined) return partieEnCours.idPartie;
|
if (partieEnCours.idPartie !== undefined) return partieEnCours.idPartie;
|
||||||
|
|
||||||
|
@ -120,6 +111,15 @@ export default class Gestionnaire {
|
||||||
}
|
}
|
||||||
|
|
||||||
private enregistrerPartieDansStats(): void {
|
private enregistrerPartieDansStats(): void {
|
||||||
|
// On regarde si c'est le même jour que la dernière partie dans les stats.
|
||||||
|
// Si c'est identique, on ne sauvegarde pas
|
||||||
|
if (
|
||||||
|
this._stats.dernierePartie.getFullYear() === this._datePartieEnCours.getFullYear() &&
|
||||||
|
this._stats.dernierePartie.getMonth() === this._datePartieEnCours.getMonth() &&
|
||||||
|
this._stats.dernierePartie.getDate() === this._datePartieEnCours.getDate()
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
this._stats.partiesJouees++;
|
this._stats.partiesJouees++;
|
||||||
let estVictoire = this._resultats.some((resultat) => resultat.every((item) => item.statut === LettreStatut.BienPlace));
|
let estVictoire = this._resultats.some((resultat) => resultat.every((item) => item.statut === LettreStatut.BienPlace));
|
||||||
if (estVictoire) {
|
if (estVictoire) {
|
||||||
|
|
19
ts/lienHelper.ts
Normal file
19
ts/lienHelper.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
export default class LienHelper {
|
||||||
|
public static extraireInformation(cle: string): string | null {
|
||||||
|
if (window.location.hash === "" || window.location.hash === "#") return null;
|
||||||
|
|
||||||
|
let hashPart = atob(window.location.hash.substring(1)).split("/");
|
||||||
|
for (let infoPos in hashPart) {
|
||||||
|
let info = hashPart[infoPos];
|
||||||
|
if (!info.includes("=")) continue;
|
||||||
|
let infoPart = info.split("=");
|
||||||
|
let infoKey = infoPart[0];
|
||||||
|
|
||||||
|
if (infoKey !== cle) continue;
|
||||||
|
|
||||||
|
return infoPart[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,8 @@ import Configuration from "./entites/configuration";
|
||||||
import PartieEnCours from "./entites/partieEnCours";
|
import PartieEnCours from "./entites/partieEnCours";
|
||||||
import SauvegardePartie from "./entites/sauvegardePartie";
|
import SauvegardePartie from "./entites/sauvegardePartie";
|
||||||
import SauvegardeStats from "./entites/sauvegardeStats";
|
import SauvegardeStats from "./entites/sauvegardeStats";
|
||||||
|
import LienHelper from "./lienHelper";
|
||||||
|
import NotificationMessage from "./notificationMessage";
|
||||||
|
|
||||||
export default class Sauvegardeur {
|
export default class Sauvegardeur {
|
||||||
private static readonly _cleStats = "statistiques";
|
private static readonly _cleStats = "statistiques";
|
||||||
|
@ -13,7 +15,21 @@ export default class Sauvegardeur {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static chargerSauvegardeStats(): SauvegardeStats | undefined {
|
public static chargerSauvegardeStats(): SauvegardeStats | undefined {
|
||||||
let dataStats = localStorage.getItem(this._cleStats);
|
const contenuLocation = LienHelper.extraireInformation("s");
|
||||||
|
|
||||||
|
if (contenuLocation) {
|
||||||
|
const donneesDepuisLien = Sauvegardeur.chargerInformationDepuisLien(contenuLocation);
|
||||||
|
window.location.hash = "";
|
||||||
|
if (donneesDepuisLien) {
|
||||||
|
NotificationMessage.ajouterNotification("Statistiques chargés avec succès.");
|
||||||
|
Sauvegardeur.sauvegarderStats(donneesDepuisLien);
|
||||||
|
return donneesDepuisLien;
|
||||||
|
}
|
||||||
|
|
||||||
|
NotificationMessage.ajouterNotification("Impossible de charger les statistiques depuis le lien.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataStats = localStorage.getItem(this._cleStats);
|
||||||
if (!dataStats) return;
|
if (!dataStats) return;
|
||||||
|
|
||||||
let stats = JSON.parse(dataStats) as SauvegardeStats;
|
let stats = JSON.parse(dataStats) as SauvegardeStats;
|
||||||
|
@ -66,4 +82,68 @@ export default class Sauvegardeur {
|
||||||
let config = JSON.parse(dataConfig) as Configuration;
|
let config = JSON.parse(dataConfig) as Configuration;
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static genererLien(): string {
|
||||||
|
const stats = Sauvegardeur.chargerSauvegardeStats() ?? SauvegardeStats.Default;
|
||||||
|
return [
|
||||||
|
stats.repartition[1],
|
||||||
|
stats.repartition[2],
|
||||||
|
stats.repartition[3],
|
||||||
|
stats.repartition[4],
|
||||||
|
stats.repartition[5],
|
||||||
|
stats.repartition[6],
|
||||||
|
stats.repartition["-"],
|
||||||
|
stats.lettresRepartitions.bienPlace,
|
||||||
|
stats.lettresRepartitions.malPlace,
|
||||||
|
stats.lettresRepartitions.nonTrouve,
|
||||||
|
stats.dernierePartie,
|
||||||
|
].join(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static chargerInformationDepuisLien(contenu: string): SauvegardeStats | null {
|
||||||
|
const [
|
||||||
|
UnCoupString,
|
||||||
|
DeuxCoupsString,
|
||||||
|
TroisCoupsString,
|
||||||
|
QuatreCoupsString,
|
||||||
|
CinqCoupsString,
|
||||||
|
SixCoupsString,
|
||||||
|
PerduString,
|
||||||
|
LettresBienPlaceesString,
|
||||||
|
LettresMalPlaceesString,
|
||||||
|
LettresNonTrouveString,
|
||||||
|
dernierePartie,
|
||||||
|
] = contenu.split(",");
|
||||||
|
|
||||||
|
const UnCoup = parseInt(UnCoupString);
|
||||||
|
const DeuxCoups = parseInt(DeuxCoupsString);
|
||||||
|
const TroisCoups = parseInt(TroisCoupsString);
|
||||||
|
const QuatreCoups = parseInt(QuatreCoupsString);
|
||||||
|
const CinqCoups = parseInt(CinqCoupsString);
|
||||||
|
const SixCoups = parseInt(SixCoupsString);
|
||||||
|
const Perdu = parseInt(PerduString);
|
||||||
|
const LettresBienPlacees = parseInt(LettresBienPlaceesString);
|
||||||
|
const LettresMalPlacees = parseInt(LettresMalPlaceesString);
|
||||||
|
const LettresNonTrouve = parseInt(LettresNonTrouveString);
|
||||||
|
|
||||||
|
return {
|
||||||
|
dernierePartie: new Date(dernierePartie),
|
||||||
|
partiesJouees: UnCoup + DeuxCoups + TroisCoups + QuatreCoups + CinqCoups + SixCoups + Perdu,
|
||||||
|
partiesGagnees: UnCoup + DeuxCoups + TroisCoups + QuatreCoups + CinqCoups + SixCoups,
|
||||||
|
repartition: {
|
||||||
|
1: UnCoup,
|
||||||
|
2: DeuxCoups,
|
||||||
|
3: TroisCoups,
|
||||||
|
4: QuatreCoups,
|
||||||
|
5: CinqCoups,
|
||||||
|
6: SixCoups,
|
||||||
|
"-": Perdu,
|
||||||
|
},
|
||||||
|
lettresRepartitions: {
|
||||||
|
bienPlace: LettresBienPlacees,
|
||||||
|
malPlace: LettresMalPlacees,
|
||||||
|
nonTrouve: LettresNonTrouve,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue