Start thinking on room.js: TODO, implement and test challenge / new game HH / abort...
[vchess.git] / public / javascripts / components / room.js
CommitLineData
b6487fb9
BA
1// TODO: main playing hall, chat + online players + current challenges + button "new game"
2/*
3input#modal-newgame.modal(type="checkbox")
4div(role="dialog" aria-labelledby="newGameTxt")
5 .card.smallpad.small-modal
6 label#close-newgame.modal-close(for="modal-newgame")
7 h3#newGameTxt= translations["New game"]
8 p= translations["Waiting for opponent..."]
9*/
a3ab5fdb 10// TODO: my-challenge-list, gérant clicks sur challenges, affichage, réception/émission des infos sur challenges ; de même, my-player-list
2305d34a 11// TODO: si on est en train de jouer une partie, le notifier aux nouveaux connectés
b6487fb9
BA
12/*
13Players + challenges : == "room" home of variant (surligner si nouveau défi perso et pas affichage courant)
14joueurs en ligne (dte),
15Nouvelle partie + défis en temps réel + parties en cours (milieu, tabs),
16chat général (gauche, activé ou non (bool global storage)).
17(cadences base + incrément, corr == incr >= 1jour ou base >= 7j)
18--> correspondance: stocker sur serveur lastMove + peerId + color + movesCount + gameId + variant + timeleft
19quand je poste un lastMove corr, supprimer mon ancien lastMove le cas échéant (tlm l'a eu)
20fin de partie corr: garder maxi nbPlayers lastMove sur serveur, pendant 7 jours (arbitraire)
21*/
a3ab5fdb
BA
22Vue.component('my-room', {
23 props: ["conn","settings"],
24 data: {
25 something: "", //TODO
26 },
27
28});
29
30 case "newgame": //challenge accepted
31 // oppid: opponent socket ID (or DB id if registered)
81da2786
BA
32 this.newGame("human", data.fen, data.color, data.oppid, data.gameid);
33 break;
34
81da2786 35 clickGameSeek: function(e) {
81da2786
BA
36 if (this.mode == "human" && this.score == "*")
37 return; //no newgame while playing
38 if (this.seek)
39 {
40 this.conn.send(JSON.stringify({code:"cancelnewgame"}));
41 this.seek = false;
42 }
43 else
44 this.newGame("human");
45 },
46 clickComputerGame: function(e) {
81da2786
BA
47 if (this.mode == "computer" && this.score == "*"
48 && this.vr.turn != this.mycolor)
49 {
50 // Wait for computer reply first (avoid potential "ghost move" bug)
51 return;
52 }
53 this.newGame("computer");
54 },
81da2786
BA
55 newGame: function(mode, fenInit, color, oppId, gameId) {
56 const fen = fenInit || VariantRules.GenRandInitFen();
57 console.log(fen); //DEBUG
58 if (mode=="human" && !oppId)
59 {
60 const storageVariant = localStorage.getItem("variant");
8d7e2786 61 if (!!storageVariant && storageVariant !== variant.name
81da2786
BA
62 && localStorage["score"] == "*")
63 {
64 return alert(translations["Finish your "] +
65 storageVariant + translations[" game first!"]);
66 }
67 // Send game request and wait..
68 try {
69 this.conn.send(JSON.stringify({code:"newgame", fen:fen, gameid: getRandString() }));
70 } catch (INVALID_STATE_ERR) {
71 return; //nothing achieved
72 }
73 this.seek = true;
74 let modalBox = document.getElementById("modal-newgame");
75 modalBox.checked = true;
76 setTimeout(() => { modalBox.checked = false; }, 2000);
77 return;
78 }
79 const prefix = this.getStoragePrefix(mode);
80 if (mode == "computer")
81 {
82 const storageVariant = localStorage.getItem(prefix+"variant");
83 if (!!storageVariant)
84 {
85 const score = localStorage.getItem(prefix+"score");
8d7e2786 86 if (storageVariant !== variant.name && score == "*")
81da2786
BA
87 {
88 if (!confirm(storageVariant +
89 translations[": unfinished computer game will be erased"]))
90 {
91 return;
92 }
93 }
94 }
95 }
96 else if (mode == "friend")
97 {
98 const storageVariant = localStorage.getItem(prefix+"variant");
99 if (!!storageVariant)
100 {
101 const score = localStorage.getItem(prefix+"score");
8d7e2786 102 if (storageVariant !== variant.name && score == "*")
81da2786
BA
103 {
104 if (!confirm(storageVariant +
105 translations[": current analysis will be erased"]))
106 {
107 return;
108 }
109 }
110 }
111 }
112 this.vr = new VariantRules(fen, []);
113 this.score = "*";
114 this.pgnTxt = ""; //redundant with this.score = "*", but cleaner
115 this.mode = mode;
116 this.incheck = [];
117 this.fenStart = V.ParseFen(fen).position; //this is enough
118 if (mode=="human")
119 {
120 // Opponent found!
121 this.gameId = gameId;
122 this.oppid = oppId;
123 this.oppConnected = true;
124 this.mycolor = color;
125 this.seek = false;
126 if (this.sound >= 1)
127 new Audio("/sounds/newgame.mp3").play().catch(err => {});
128 document.getElementById("modal-newgame").checked = false;
129 }
130 else if (mode == "computer")
131 {
132 this.compWorker.postMessage(["init",this.vr.getFen()]);
133 this.mycolor = (Math.random() < 0.5 ? 'w' : 'b');
134 if (this.mycolor != this.vr.turn)
135 this.playComputerMove();
136 }
137 else if (mode == "friend")
138 this.mycolor = "w"; //convention...
139 //else: problem solving: nothing more to do
140 if (mode != "problem")
141 this.setStorage(); //store game state in case of interruptions
142 },
143 continueGame: function(mode) {
144 this.mode = mode;
145 this.oppid = (mode=="human" ? localStorage.getItem("oppid") : undefined);
146 const prefix = this.getStoragePrefix(mode);
147 this.mycolor = localStorage.getItem(prefix+"mycolor");
148 const moves = JSON.parse(localStorage.getItem(prefix+"moves"));
149 const fen = localStorage.getItem(prefix+"fen");
150 const score = localStorage.getItem(prefix+"score"); //set in "endGame()"
151 this.fenStart = localStorage.getItem(prefix+"fenStart");
152 this.vr = new VariantRules(fen, moves);
153 this.incheck = this.vr.getCheckSquares(this.vr.turn);
154 if (mode == "human")
155 {
156 this.gameId = localStorage.getItem("gameId");
157 // Send ping to server (answer pong if opponent is connected)
158 this.conn.send(JSON.stringify({
159 code:"ping",oppid:this.oppid,gameId:this.gameId}));
160 }
161 else if (mode == "computer")
162 {
163 this.compWorker.postMessage(["init",fen]);
164 if (score == "*" && this.mycolor != this.vr.turn)
165 this.playComputerMove();
166 }
167 //else: nothing special to do in friend mode
168 if (score != "*")
169 {
170 // Small delay required when continuation run faster than drawing page
171 setTimeout(() => this.endGame(score), 100);
172 }
173 },
174
175
a3ab5fdb 176 // TODO: option du bouton "new game" :: seulement pour challenge indiv
81da2786
BA
177 const modalFenEdit = [
178 h('input',
179 {
180 attrs: { "id": "modal-fenedit", type: "checkbox" },
181 "class": { "modal": true },
182 }),
183 h('div',
184 {
185 attrs: { "role": "dialog", "aria-labelledby": "titleFenedit" },
186 },
187 [
188 h('div',
189 {
190 "class": { "card": true, "smallpad": true },
191 },
192 [
193 h('label',
194 {
195 attrs: { "id": "close-fenedit", "for": "modal-fenedit" },
196 "class": { "modal-close": true },
197 }
198 ),
199 h('h3',
200 {
201 attrs: { "id": "titleFenedit" },
202 "class": { "section": true },
203 domProps: { innerHTML: translations["Game state (FEN):"] },
204 }
205 ),
206 h('input',
207 {
208 attrs: {
209 "id": "input-fen",
210 type: "text",
211 value: VariantRules.GenRandInitFen(),
212 },
213 }
214 ),
215 h('button',
216 {
217 on: { click:
218 () => {
219 const fen = document.getElementById("input-fen").value;
220 document.getElementById("modal-fenedit").checked = false;
221 this.newGame("friend", fen);
222 }
223 },
224 domProps: { innerHTML: translations["Ok"] },
225 }
226 ),
227 h('button',
228 {
229 on: { click:
230 () => {
231 document.getElementById("input-fen").value =
232 VariantRules.GenRandInitFen();
233 }
234 },
235 domProps: { innerHTML: translations["Random"] },
236 }
237 ),
238 ]
239 )
240 ]
241 )
242 ];
243 elementArray = elementArray.concat(modalFenEdit);