Commit | Line | Data |
---|---|---|
ccd4a2b7 BA |
1 | <template lang="pug"> |
2 | div | |
5b020e73 BA |
3 | input#modalNewgame.modal(type="checkbox") |
4 | div(role="dialog" aria-labelledby="titleFenedit") | |
5 | .card.smallpad | |
6 | label#closeNewgame.modal-close(for="modalNewgame") | |
7 | fieldset | |
8 | label(for="selectVariant") {{ st.tr["Variant"] }} | |
9 | select#selectVariant(v-model="newgameInfo.vid") | |
85e5b5c1 | 10 | option(v-for="v in st.variants" :value="v.id") {{ v.name }} |
5b020e73 BA |
11 | fieldset |
12 | label(for="selectNbPlayers") {{ st.tr["Number of players"] }} | |
13 | select#selectNbPlayers(v-model="newgameInfo.nbPlayers") | |
14 | option(v-show="possibleNbplayers(2)" value="2") 2 | |
15 | option(v-show="possibleNbplayers(3)" value="3") 3 | |
16 | option(v-show="possibleNbplayers(4)" value="4") 4 | |
17 | fieldset | |
18 | label(for="timeControl") Time control (in days) | |
19 | #timeControl | |
20 | input(type="number" v-model="newgameInfo.mainTime" | |
21 | placeholder="Main time") | |
22 | input(type="number" v-model="newgameInfo.increment" | |
23 | placeholder="Increment") | |
24 | fieldset | |
25 | label(for="selectPlayers") {{ st.tr["Play with?"] }} | |
26 | #selectPlayers | |
27 | input(type="text" v-model="newgameInfo.players[0].name") | |
28 | input(v-show="newgameInfo.nbPlayers>=3" type="text" | |
29 | v-model="newgameInfo.players[1].name") | |
30 | input(v-show="newgameInfo.nbPlayers==4" type="text" | |
31 | v-model="newgameInfo.players[2].name") | |
32 | fieldset | |
33 | label(for="inputFen") | |
85e5b5c1 | 34 | | {{ st.tr["FEN (ignored if players fields are blank)"] }} |
5b020e73 BA |
35 | input#inputFen(type="text" v-model="newgameInfo.fen") |
36 | button(@click="newGame") Launch game | |
37 | p TODO: cadence, adversaire (pre-filled if click on name) | |
38 | p cadence 2m+12s ou 7d+1d (m,s ou d,d) --> main, increment | |
39 | p Note: leave FEN blank for random; FEN only for targeted challenge | |
40 | div | |
85e5b5c1 | 41 | ChallengeList(:challenges="challenges" @click-challenge="clickChallenge") |
5b020e73 BA |
42 | div(style="border:1px solid black") |
43 | h3 Online players | |
44 | div(v-for="p in players" @click="challenge(p)") {{ p.name }} | |
45 | button(onClick="doClick('modalNewgame')") New game | |
46 | div | |
47 | .button-group | |
48 | button(@click="gdisplay='live'") Live games | |
49 | button(@click="gdisplay='corr'") Correspondance games | |
85e5b5c1 | 50 | GameList(v-show="gdisplay=='live'" :games="liveGames" |
5b020e73 | 51 | @show-game="showGame") |
85e5b5c1 | 52 | GameList(v-show="gdisplay=='corr'" :games="corrGames" |
5b020e73 | 53 | @show-game="showGame") |
625022fd BA |
54 | </template> |
55 | ||
56 | <script> | |
5b020e73 BA |
57 | // main playing hall: online players + current challenges + button "new game" |
58 | // TODO: si on est en train de jouer une partie, le notifier aux nouveaux connectés | |
59 | /* | |
60 | TODO: surligner si nouveau défi perso et pas affichage courant | |
61 | (cadences base + incrément, corr == incr >= 1jour ou base >= 7j) | |
62 | --> correspondance: stocker sur serveur lastMove + uid + color + movesCount + gameId + variant + timeleft | |
63 | fin de partie corr: supprimer partie du serveur au bout de 7 jours (arbitraire) | |
64 | */ | |
65 | // TODO: au moins l'échange des coups en P2P ? et game chat ? | |
66 | // TODO: objet game, objet challenge ? et player ? | |
67 | import { store } from "@/store"; | |
85e5b5c1 | 68 | import { NbPlayers } from "@/data/nbPlayers"; |
5b020e73 BA |
69 | import GameList from "@/components/GameList.vue"; |
70 | import ChallengeList from "@/components/ChallengeList.vue"; | |
625022fd | 71 | export default { |
cf2343ce | 72 | name: "my-hall", |
5b020e73 BA |
73 | components: { |
74 | GameList, | |
75 | ChallengeList, | |
76 | }, | |
fb54f098 BA |
77 | data: function () { |
78 | return { | |
5b020e73 | 79 | st: store.state, |
fb54f098 BA |
80 | gdisplay: "live", |
81 | liveGames: [], | |
82 | corrGames: [], | |
83 | players: [], //online players | |
84 | challenges: [], //live challenges | |
85 | willPlay: [], //IDs of challenges in which I decide to play (>= 3 players) | |
86 | newgameInfo: { | |
87 | fen: "", | |
88 | vid: 0, | |
89 | nbPlayers: 0, | |
90 | players: [{id:0,name:""},{id:0,name:""},{id:0,name:""}], | |
91 | mainTime: 0, | |
92 | increment: 0, | |
93 | }, | |
94 | }; | |
95 | }, | |
85e5b5c1 BA |
96 | watch: { |
97 | "st.conn": function() { | |
98 | // TODO: ask server for current corr games (all but mines: names, ID, time control) | |
99 | const socketMessageListener = msg => { | |
100 | const data = JSON.parse(msg.data); | |
101 | switch (data.code) | |
102 | { | |
103 | case "newgame": | |
104 | // TODO: new game just started: data contain all informations | |
105 | // (id, players, time control, fenStart ...) | |
106 | break; | |
107 | // TODO: also receive live games summaries (update) | |
108 | // (just players names, time control, and ID + player ID) | |
109 | case "acceptchallenge": | |
110 | // oppid: opponent socket ID (or DB id if registered) | |
111 | if (true) //TODO: if challenge is full | |
112 | this.newGame(data.challenge, data.user); //user.id et user.name | |
113 | break; | |
114 | case "withdrawchallenge": | |
115 | // TODO | |
116 | break; | |
117 | case "cancelchallenge": | |
118 | // TODO | |
119 | break; | |
120 | // TODO: distinguish these (dis)connect events from their analogs in game.js | |
121 | case "connect": | |
122 | this.players.push({name:data.name, id:data.uid}); | |
123 | break; | |
124 | case "disconnect": | |
125 | const pIdx = this.players.findIndex(p => p.id == data.uid); | |
126 | this.players.splice(pIdx); | |
127 | break; | |
128 | } | |
129 | }; | |
130 | const socketCloseListener = () => { | |
131 | this.st.conn.addEventListener('message', socketMessageListener); | |
132 | this.st.conn.addEventListener('close', socketCloseListener); | |
133 | }; | |
134 | this.st.conn.onmessage = socketMessageListener; | |
135 | this.st.conn.onclose = socketCloseListener; | |
136 | }, | |
137 | }, | |
fb54f098 BA |
138 | methods: { |
139 | showGame: function(game) { | |
5b020e73 BA |
140 | // NOTE: if we are an observer, the game will be found in main games list |
141 | // (sent by connected remote players) | |
142 | this.$router.push("/" + game.id) | |
fb54f098 BA |
143 | }, |
144 | challenge: function(player) { | |
145 | this.st.conn.send(JSON.stringify({code:"sendchallenge", oppid:p.id, | |
146 | user:{name:this.st.user.name,id:this.st.user.id}})); | |
147 | }, | |
148 | clickChallenge: function(challenge) { | |
149 | const index = this.challenges.findIndex(c => c.id == challenge.id); | |
150 | const toIdx = challenge.to.findIndex(p => p.id == user.id); | |
151 | const me = {name:user.name,id:user.id}; | |
152 | if (toIdx >= 0) | |
153 | { | |
154 | // It's a multiplayer challenge I accepted: withdraw | |
155 | this.st.conn.send(JSON.stringify({code:"withdrawchallenge", | |
156 | cid:challenge.id, user:me})); | |
157 | this.challenges.to.splice(toIdx, 1); | |
158 | } | |
159 | else if (challenge.from.id == user.id) //it's my challenge: cancel it | |
160 | { | |
161 | this.st.conn.send(JSON.stringify({code:"cancelchallenge", cid:challenge.id})); | |
162 | this.challenges.splice(index, 1); | |
163 | } | |
164 | else //accept a challenge | |
165 | { | |
166 | this.st.conn.send(JSON.stringify({code:"acceptchallenge", | |
167 | cid:challenge.id, user:me})); | |
168 | this.challenges[index].to.push(me); | |
169 | } | |
170 | // TODO: accepter un challenge peut lancer une partie, il | |
171 | // faut alors supprimer challenge + creer partie + la retourner et l'ajouter ici | |
172 | // autres actions: | |
173 | // supprime mon défi | |
174 | // accepte un défi | |
175 | // annule l'acceptation d'un défi (si >= 3 joueurs) | |
176 | // | |
177 | // si pas le mien et FEN speciale :: (charger code variante et) | |
178 | // montrer diagramme + couleur (orienté) | |
179 | }, | |
180 | // user: last person to accept the challenge | |
181 | newGameLive: function(chall, user) { | |
182 | const fen = chall.fen || V.GenRandInitFen(); | |
183 | const game = {}; //TODO: fen, players, time ... | |
184 | //setStorage(game); //TODO | |
185 | game.players.forEach(p => { | |
186 | this.conn.send( | |
187 | JSON.stringify({code:"newgame", oppid:p.id, game:game})); | |
188 | }); | |
189 | if (this.settings.sound >= 1) | |
190 | new Audio("/sounds/newgame.mp3").play().catch(err => {}); | |
191 | }, | |
192 | newGame: function() { | |
193 | const afterRulesAreLoaded = () => { | |
194 | // NOTE: side-effect = set FEN | |
195 | // TODO: (to avoid any cheating option) separate the GenRandInitFen() functions | |
196 | // in separate files, load on server and generate FEN on server. | |
197 | const error = checkChallenge(this.newgameInfo, vname); | |
198 | if (!!error) | |
199 | return alert(error); | |
200 | // Possible (server) error if filled player does not exist | |
201 | ajax( | |
202 | "/challenges/" + this.newgameInfo.vid, | |
203 | "POST", | |
204 | this.newgameInfo, | |
205 | response => { | |
206 | const chall = Object.assign({}, | |
207 | this.newgameInfo, | |
208 | { | |
209 | id: response.cid, | |
210 | uid: user.id, | |
211 | added: Date.now(), | |
212 | vname: vname, | |
213 | }); | |
214 | this.challenges.push(chall); | |
215 | } | |
216 | ); | |
5b020e73 | 217 | // TODO: else, if live game: send infos (socket), and... |
fb54f098 BA |
218 | }; |
219 | const idxInVariants = | |
220 | variantArray.findIndex(v => v.id == this.newgameInfo.vid); | |
221 | const vname = variantArray[idxInVariants].name; | |
222 | const scriptId = vname + "RulesScript"; | |
223 | if (!document.getElementById(scriptId)) | |
224 | { | |
225 | // Load variant rules (only once) | |
226 | var script = document.createElement("script"); | |
227 | script.id = scriptId; | |
228 | script.onload = afterRulesAreLoaded; | |
229 | //script.addEventListener ("load", afterRulesAreLoaded, false); | |
230 | script.src = "/javascripts/variants/" + vname + ".js"; | |
231 | document.body.appendChild(script); | |
232 | } | |
233 | else | |
234 | afterRulesAreLoaded(); | |
235 | }, | |
236 | possibleNbplayers: function(nbp) { | |
237 | if (this.newgameInfo.vid == 0) | |
238 | return false; | |
85e5b5c1 | 239 | const variants = this.st.variants; |
fb54f098 BA |
240 | const idxInVariants = |
241 | variants.findIndex(v => v.id == this.newgameInfo.vid); | |
242 | return NbPlayers[variants[idxInVariants].name].includes(nbp); | |
243 | }, | |
244 | }, | |
85e5b5c1 | 245 | }; |
ccd4a2b7 | 246 | </script> |
85e5b5c1 BA |
247 | |
248 | <style lang="sass"> | |
249 | // TODO | |
250 | </style> |