diff --git a/public/index.html b/public/index.html
index 1e7437f..04173f6 100644
--- a/public/index.html
+++ b/public/index.html
@@ -101,6 +101,11 @@
d="M216 960q-29.7 0-50.85-21.15Q144 917.7 144 888V336h72v552h456v72H216Zm144-144q-29.7 0-50.85-21.15Q288 773.7 288 744V264q0-29.7 21.15-50.85Q330.3 192 360 192h384q29.7 0 50.85 21.15Q816 234.3 816 264v480q0 29.7-21.15 50.85Q773.7 816 744 816H360Zm0-72h384V264H360v480Zm0 0V264v480Z"
/>
+
+
+
diff --git a/public/jeu.css b/public/jeu.css
index 36f7d0e..e2ce549 100644
--- a/public/jeu.css
+++ b/public/jeu.css
@@ -435,7 +435,7 @@ h1 {
}
.stats-numerique-case-valeur {
- font-size: 28px;
+ font-size: 24px;
}
.stats-numerique-case-secondaire {
@@ -477,16 +477,26 @@ h1 {
text-align: start;
}
+#fin-de-partie-panel-partie-veille-area {
+ text-align: start;
+}
+
+#fin-de-partie-panel-resume-bouton,
+#fin-de-partie-panel-stats-bouton,
+#fin-de-partie-panel-reset-bouton {
+ font-size: 1rem;
+ position: relative;
+}
+
#fin-de-partie-panel-resume-bouton,
#fin-de-partie-panel-stats-bouton {
- font-size: 1rem;
margin-left: 1rem;
- position: relative;
}
.bouton-partage-texte {
bottom: 4px;
position: absolute;
+ width: max-content;
}
#config-sauvegarde-area {
diff --git a/ts/copieHelper.ts b/ts/copieHelper.ts
index b4b598f..2d59de5 100644
--- a/ts/copieHelper.ts
+++ b/ts/copieHelper.ts
@@ -29,6 +29,10 @@ export default class CopieHelper {
}
public static creerBoutonPartage(idBouton: string, label?: string): HTMLElement {
+ return this.creerBoutonAvecIcone(idBouton, "#icone-copie", label);
+ }
+
+ public static creerBoutonAvecIcone(idBouton: string, icone: string, label?: string): HTMLElement {
const lien = document.createElement("a");
lien.id = idBouton;
lien.className = "bouton-partage";
@@ -36,7 +40,7 @@ export default class CopieHelper {
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("href", icone);
useSvg.setAttribute("stroke", "var(--couleur-icone)");
useSvg.setAttribute("fill", "var(--couleur-icone)");
svg.appendChild(useSvg);
diff --git a/ts/finDePartiePanel.ts b/ts/finDePartiePanel.ts
index 0e7feb5..a61fc86 100644
--- a/ts/finDePartiePanel.ts
+++ b/ts/finDePartiePanel.ts
@@ -3,6 +3,7 @@ import Configuration from "./entites/configuration";
import LettreResultat from "./entites/lettreResultat";
import { LettreStatut } from "./entites/lettreStatut";
import SauvegardeStats from "./entites/sauvegardeStats";
+import Gestionnaire from "./gestionnaire";
import InstanceConfiguration from "./instanceConfiguration";
import PanelManager from "./panelManager";
import Sauvegardeur from "./sauvegardeur";
@@ -12,6 +13,7 @@ export default class FinDePartiePanel {
private readonly _datePartie: Date;
private readonly _panelManager: PanelManager;
private readonly _statsButton: HTMLElement;
+ private readonly _gestionnaire: Gestionnaire;
private _resumeTexte: string = "";
private _resumeTexteLegacy: string = "";
@@ -19,11 +21,12 @@ export default class FinDePartiePanel {
private _estVictoire: boolean = false;
private _partieEstFinie: boolean = false;
- public constructor(datePartie: Date, panelManager: PanelManager) {
+ public constructor(datePartie: Date, panelManager: PanelManager, gestionnaire: Gestionnaire) {
this._datePartie = new Date(datePartie);
this._datePartie.setHours(0, 0, 0);
this._panelManager = panelManager;
this._statsButton = document.getElementById("configuration-stats-bouton") as HTMLElement;
+ this._gestionnaire = gestionnaire;
this._statsButton.addEventListener(
"click",
@@ -132,6 +135,19 @@ export default class FinDePartiePanel {
";
}
contenu += StatistiquesDisplayer.genererResumeTexte(this._resumeTexteLegacy).outerHTML;
+
+ if (Sauvegardeur.hasPartieVeilleNonTerminee()) {
+ const partieVeilleArea = document.createElement("div");
+ partieVeilleArea.id = "fin-de-partie-panel-partie-veille-area";
+
+ const partieVeilleLabel = document.createElement("div");
+ partieVeilleLabel.innerText = "Il semblerait que vous n'avez pas terminé votre partie d'hier…";
+ partieVeilleArea.appendChild(partieVeilleLabel);
+
+ partieVeilleArea.appendChild(CopieHelper.creerBoutonAvecIcone("fin-de-partie-panel-reset-bouton", "#icone-restaure", "Terminer la partie"));
+
+ contenu += partieVeilleArea.outerHTML;
+ }
}
let stats = Sauvegardeur.chargerSauvegardeStats();
@@ -143,6 +159,19 @@ export default class FinDePartiePanel {
this._panelManager.setClasses(["fin-de-partie-panel"]);
if (this._partieEstFinie) this.attacherPartage();
if (stats) this.attacherPartageStats(stats);
+
+ const resetButton = document.getElementById("fin-de-partie-panel-reset-bouton") as HTMLElement;
+ if (resetButton) {
+ const veille = new Date();
+ veille.setDate(veille.getDate() - 1);
+ resetButton.addEventListener(
+ "click",
+ (() => {
+ this._gestionnaire.chargerPartieAncienne(veille, Sauvegardeur.chargerPartieVeille());
+ this._panelManager.cacherPanel();
+ }).bind(this)
+ );
+ }
this._panelManager.afficherPanel();
}
diff --git a/ts/gestionnaire.ts b/ts/gestionnaire.ts
index d862f48..95fd94a 100644
--- a/ts/gestionnaire.ts
+++ b/ts/gestionnaire.ts
@@ -21,7 +21,7 @@ export default class Gestionnaire {
private _grille: Grille | null = null;
private _input: Input | null = null;
private readonly _reglesPanel: ReglesPanel;
- private readonly _finDePartiePanel: FinDePartiePanel;
+ private _finDePartiePanel: FinDePartiePanel;
private readonly _configurationPanel: ConfigurationPanel;
private readonly _propositions: Array;
private readonly _resultats: Array>;
@@ -65,7 +65,7 @@ export default class Gestionnaire {
this._panelManager = new PanelManager();
this._themeManager = new ThemeManager(this._config);
this._reglesPanel = new ReglesPanel(this._panelManager);
- this._finDePartiePanel = new FinDePartiePanel(this._datePartieEnCours, this._panelManager);
+ this._finDePartiePanel = new FinDePartiePanel(this._datePartieEnCours, this._panelManager, this);
this._configurationPanel = new ConfigurationPanel(this._panelManager, this._audioPanel, this._themeManager);
this.choisirMot(this._idPartieEnCours, this._datePartieEnCours)
@@ -269,4 +269,37 @@ export default class Gestionnaire {
this._reglesPanel.afficher();
}
+
+ public chargerPartieAncienne(datePartie: Date, etatPartie: PartieEnCours): void {
+ let partieEnCours = etatPartie;
+
+ this._idPartieEnCours = this.getIdPartie(partieEnCours);
+
+ if (this._idPartieEnCours !== partieEnCours.idPartie && partieEnCours.idPartie !== undefined) {
+ partieEnCours = new PartieEnCours();
+ }
+
+ if (partieEnCours.datePartie) {
+ this._datePartieEnCours = partieEnCours.datePartie;
+ } else {
+ this._datePartieEnCours = datePartie;
+ }
+ this._dateFinPartie = undefined;
+
+ this._propositions.splice(0);
+ this._resultats.splice(0);
+ this._finDePartiePanel = new FinDePartiePanel(this._datePartieEnCours, this._panelManager, this);
+
+ this.choisirMot(this._idPartieEnCours, this._datePartieEnCours)
+ .then(async (mot) => {
+ this._motATrouver = mot;
+ this._input = new Input(this, this._config, this._motATrouver.length, this._motATrouver[0]);
+ this._panelManager.setInput(this._input);
+ this._grille = new Grille(this._motATrouver.length, this._maxNbPropositions, this._motATrouver[0], this._audioPanel);
+ this._configurationPanel.setInput(this._input);
+ this._compositionMotATrouver = this.decompose(this._motATrouver);
+ await this.chargerPropositions(partieEnCours.propositions);
+ })
+ .catch((raison) => NotificationMessage.ajouterNotification("Aucun mot n'a été trouvé pour aujourd'hui"));
+ }
}
diff --git a/ts/sauvegardeur.ts b/ts/sauvegardeur.ts
index 4b76915..843497c 100644
--- a/ts/sauvegardeur.ts
+++ b/ts/sauvegardeur.ts
@@ -8,6 +8,7 @@ import NotificationMessage from "./notificationMessage";
export default class Sauvegardeur {
private static readonly _cleStats = "statistiques";
private static readonly _clePartieEnCours = "partieEnCours";
+ private static readonly _clePartieVeille = "partieVeille";
private static readonly _cleConfiguration = "configuration";
public static sauvegarderStats(stats: SauvegardeStats): void {
@@ -48,19 +49,54 @@ export default class Sauvegardeur {
}
public static chargerSauvegardePartieEnCours(): PartieEnCours | undefined {
- let dataPartieEnCours = localStorage.getItem(this._clePartieEnCours);
- if (!dataPartieEnCours) return;
-
- let partieEnCours = JSON.parse(dataPartieEnCours) as SauvegardePartie;
let aujourdhui = new Date();
- let datePartieEnCours = new Date(partieEnCours.datePartie);
- if (
- aujourdhui.getDate() !== datePartieEnCours.getDate() ||
- aujourdhui.getMonth() !== datePartieEnCours.getMonth() ||
- aujourdhui.getFullYear() !== datePartieEnCours.getFullYear()
- ) {
- localStorage.removeItem(this._clePartieEnCours);
- return;
+ let partieEnCours: SauvegardePartie;
+ let datePartieEnCours: Date;
+
+ let dataPartieEnCours = localStorage.getItem(this._clePartieEnCours);
+ if (!dataPartieEnCours) {
+ // On regarde si par hasard, on n'a pas la partie du jour dans les infos de la veille
+ const partieVeille = this.getInfoVeille();
+
+ if (
+ partieVeille &&
+ aujourdhui.getDate() === partieVeille.datePartie.getDate() &&
+ aujourdhui.getMonth() === partieVeille.datePartie.getMonth() &&
+ aujourdhui.getFullYear() === partieVeille.datePartie.getFullYear()
+ ) {
+ partieEnCours = partieVeille;
+ datePartieEnCours = partieVeille.datePartie;
+ localStorage.removeItem(this._clePartieVeille);
+ } else {
+ return;
+ }
+ } else {
+ partieEnCours = JSON.parse(dataPartieEnCours) as SauvegardePartie;
+ datePartieEnCours = new Date(partieEnCours.datePartie);
+ if (
+ aujourdhui.getDate() !== datePartieEnCours.getDate() ||
+ aujourdhui.getMonth() !== datePartieEnCours.getMonth() ||
+ aujourdhui.getFullYear() !== datePartieEnCours.getFullYear()
+ ) {
+ // On regarde si par hasard, on n'a pas la partie du jour dans les infos de la veille
+ const partieVeille = this.getInfoVeille();
+
+ if (
+ partieVeille &&
+ aujourdhui.getDate() === partieVeille.datePartie.getDate() &&
+ aujourdhui.getMonth() === partieVeille.datePartie.getMonth() &&
+ aujourdhui.getFullYear() === partieVeille.datePartie.getFullYear()
+ ) {
+ partieEnCours = partieVeille;
+ datePartieEnCours = partieVeille.datePartie;
+ // Et on inverse les données
+ localStorage.setItem(this._clePartieVeille, dataPartieEnCours);
+ } else {
+ localStorage.setItem(this._clePartieVeille, dataPartieEnCours);
+ localStorage.removeItem(this._clePartieEnCours);
+ return;
+ }
+ }
}
let dateFinPartie = partieEnCours.dateFinPartie === undefined ? undefined : new Date(partieEnCours.dateFinPartie);
@@ -72,6 +108,66 @@ export default class Sauvegardeur {
};
}
+ private static getInfoVeille(): SauvegardePartie | undefined {
+ const dataPartieVeille = localStorage.getItem(this._clePartieVeille);
+ if (!dataPartieVeille) return undefined;
+
+ const veille = new Date();
+ veille.setDate(veille.getDate() - 1);
+
+ let partieVeille = JSON.parse(dataPartieVeille) as SauvegardePartie;
+ if (partieVeille.datePartie) partieVeille.datePartie = new Date(partieVeille.datePartie);
+ if (partieVeille.dateFinPartie) partieVeille.dateFinPartie = new Date(partieVeille.dateFinPartie);
+ return partieVeille;
+ }
+
+ public static hasPartieVeilleNonTerminee(): boolean {
+ const partieVeille = this.getInfoVeille();
+ if (!partieVeille) return true;
+
+ const veille = new Date();
+ veille.setDate(veille.getDate() - 1);
+
+ return (
+ veille.getDate() === partieVeille.datePartie.getDate() &&
+ veille.getMonth() === partieVeille.datePartie.getMonth() &&
+ veille.getFullYear() === partieVeille.datePartie.getFullYear() &&
+ !partieVeille.dateFinPartie
+ );
+ }
+
+ public static chargerPartieVeille(): PartieEnCours {
+ const veille = new Date();
+ veille.setDate(veille.getDate() - 1);
+ const partieVeille = this.getInfosPartieVeille(veille);
+ let dateFinPartie = partieVeille.dateFinPartie === undefined ? undefined : new Date(partieVeille.dateFinPartie);
+
+ // On va sauvegarder la partie en cours dans la veille pour ne pas la perde
+ const partieEnCours = localStorage.getItem(this._clePartieEnCours);
+ if (partieEnCours) {
+ localStorage.setItem(this._clePartieVeille, partieEnCours);
+ localStorage.removeItem(this._clePartieEnCours);
+ }
+
+ return {
+ datePartie: new Date(partieVeille.datePartie),
+ dateFinPartie: dateFinPartie,
+ propositions: partieVeille.propositions,
+ idPartie: partieVeille.idPartie,
+ };
+ }
+
+ private static getInfosPartieVeille(veille: Date): SauvegardePartie {
+ const dataPartieVeille = localStorage.getItem(this._clePartieVeille);
+ if (!dataPartieVeille) {
+ const dataPartie = new SauvegardePartie();
+ dataPartie.datePartie = veille;
+ return dataPartie;
+ }
+
+ return JSON.parse(dataPartieVeille) as SauvegardePartie;
+ }
+
public static sauvegarderConfig(config: Configuration): void {
localStorage.setItem(this._cleConfiguration, JSON.stringify(config));
}