X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=client%2Fsrc%2Fviews%2FHall.vue;h=ebb4675368f90060e17155bd96af56fcfde805ff;hb=4a2093139089632727de4f510127ef186cab528e;hp=b3172aca7849870edf8d3e4ef2c0a324408d317d;hpb=659a9bd22c88177e203207a406cdb6c9f69139d4;p=vchess.git diff --git a/client/src/views/Hall.vue b/client/src/views/Hall.vue index b3172aca..ebb46753 100644 --- a/client/src/views/Hall.vue +++ b/client/src/views/Hall.vue @@ -15,6 +15,8 @@ main span.variantName {{ curChallToAccept.vname }} span {{ curChallToAccept.cadence }} span {{ st.tr["with"] + " " + curChallToAccept.from.name }} + p.text-center(v-if="!!curChallToAccept.color") + | {{ st.tr["Your color:"] + " " + invColor(curChallToAccept.color) }} .diagram( v-if="!!curChallToAccept.fen" v-html="tchallDiag" @@ -88,7 +90,13 @@ main type="text" v-model="newchallenge.to" ) - fieldset(v-if="st.user.id > 0 && newchallenge.to.length > 0") + fieldset(v-show="st.user.id > 0 && newchallenge.to.length > 0") + label(for="selectColor") {{ st.tr["Color"] }} + select#selectColor(v-model="newchallenge.color") + option(value='') + option(value='w') {{ st.tr["White"] }} + option(value='b') {{ st.tr["Black"] }} + br input#inputFen( placeholder="FEN" @input="trySetNewchallDiag()" @@ -113,14 +121,15 @@ main v-for="sid in Object.keys(people)" v-if="!!people[sid].name" ) - span {{ people[sid].name }} + UserBio.user-bio(:uid="people[sid].id" :uname="people[sid].name") button.player-action( v-if="isGamer(sid)" @click="watchGame(sid)" ) | {{ st.tr["Observe"] }} button.player-action( - v-else-if="isFocusedOnHall(sid)" + v-else-if="st.user.sid != sid" + :class="{focused: isFocusedOnHall(sid)}" @click="challenge(sid)" ) | {{ st.tr["Challenge"] }} @@ -166,7 +175,7 @@ main button.tabbtn#btnClive(@click="setDisplay('c','live',$event)") | {{ st.tr["Live challenges"] }} button.tabbtn#btnCcorr(@click="setDisplay('c','corr',$event)") - | {{ st.tr["Correspondance challenges"] }} + | {{ st.tr["Correspondence challenges"] }} ChallengeList( v-show="cdisplay=='live'" :challenges="filterChallenges('live')" @@ -182,7 +191,7 @@ main button.tabbtn#btnGlive(@click="setDisplay('g','live',$event)") | {{ st.tr["Live games"] }} button.tabbtn#btnGcorr(@click="setDisplay('g','corr',$event)") - | {{ st.tr["Correspondance games"] }} + | {{ st.tr["Correspondence games"] }} GameList( v-show="gdisplay=='live'" :games="filterGames('live')" @@ -212,6 +221,7 @@ import params from "@/parameters"; import { getRandString, shuffle, randInt } from "@/utils/alea"; import { getDiagram } from "@/utils/printDiagram"; import Chat from "@/components/Chat.vue"; +import UserBio from "@/components/UserBio.vue"; import GameList from "@/components/GameList.vue"; import ChallengeList from "@/components/ChallengeList.vue"; import { GameStorage } from "@/utils/gameStorage"; @@ -220,6 +230,7 @@ export default { name: "my-hall", components: { Chat, + UserBio, GameList, ChallengeList }, @@ -238,12 +249,13 @@ export default { infoMessage: "", newchallenge: { fen: "", - vid: parseInt(localStorage.getItem("vid")) || 0, + vid: parseInt(localStorage.getItem("vid"), 10) || 0, to: "", //name of challenged player (if any) + color: '', cadence: localStorage.getItem("cadence") || "", randomness: // Warning: randomness can be 0, then !!randomness is false - (parseInt(localStorage.getItem("challRandomness"))+1 || 3) - 1, + (parseInt(localStorage.getItem("challRandomness"),10)+1 || 3) - 1, // VariantRules object, stored to not interfere with // diagrams of targetted challenges: V: null, @@ -253,7 +265,7 @@ export default { }, focus: true, tchallDiag: "", - curChallToAccept: {from: {}}, + curChallToAccept: { from: {} }, presetChalls: JSON.parse(localStorage.getItem("presetChalls") || "[]"), conn: null, connexionString: "", @@ -299,6 +311,28 @@ export default { const connectAndPoll = () => { this.send("connect"); this.send("pollclientsandgamers"); + if (!!this.$route.query["challenge"]) { + // Automatic challenge sending, for tournaments + this.loadNewchallVariant( + () => { + this.newchallenge = { + fen: "", + vid: + this.st.variants + .find(v => v.name == this.$route.query["variant"]) + .id, + to: this.$route.query["challenge"], + color: this.$route.query["color"] || '', + cadence: this.$route.query["cadence"], + // Tournament: no randomness (TODO: for now at least) + randomness: 0, + memorize: false + }; + this.issueNewChallenge(); + }, + this.$route.query["variant"] + ); + } }; // Initialize connection this.connexionString = @@ -407,7 +441,8 @@ export default { } } ); - } else addChallenges(); + } + else addChallenges(); } } ); @@ -452,9 +487,14 @@ export default { this.focus = false; this.send("losefocus"); }, + invColor: function(c) { + if (c == 'w') return this.st.tr["Black"]; + return this.tr.tr["White"]; + }, partialResetNewchallenge: function() { // Reset potential target and custom FEN: this.newchallenge.to = ""; + this.newchallenge.color = ''; this.newchallenge.fen = ""; this.newchallenge.diag = ""; this.newchallenge.memorize = false; @@ -497,6 +537,7 @@ export default { if (!this.newchallenge.to) { // Reset potential FEN + diagram this.newchallenge.fen = ""; + this.newchallenge.color = ''; this.newchallenge.diag = ""; } }, @@ -522,9 +563,8 @@ export default { }, // o: challenge or game classifyObject: function(o) { - // Consider imports as live games (TODO) - if (!!o.id && !!o.id.toString().match(/^i/)) return "live"; - return o.cadence.indexOf("d") === -1 ? "live" : "corr"; + // No imported games here + return (o.cadence.indexOf("d") >= 0 ? "corr" : "live"); }, setDisplay: function(letter, type, e) { this[letter + "display"] = type; @@ -662,7 +702,8 @@ export default { // For self multi-connects tests: this.newConnect[data.from[0]] = true; this.send("askidentity", { target: data.from[0], page: page }); - } else { + } + else { this.people[data.from[0]].tmpIds[data.from[1]] = { page: page, focus: true }; this.$forceUpdate(); //TODO: shouldn't be required @@ -694,7 +735,8 @@ export default { "all" ); } - } else { + } + else { // Remove the matching live game if now unreachable const gid = data.page.match(/[a-zA-Z0-9]+$/)[0]; // Corr games are always reachable: @@ -859,7 +901,7 @@ export default { this.startNewGame(gameInfo); else { this.infoMessage = - this.st.tr["New correspondance game:"] + " " + + this.st.tr["New correspondence game:"] + " " + "" + "#/game/" + gameInfo.id + ""; document.getElementById("modalInfo").checked = true; @@ -909,7 +951,8 @@ export default { ); }); this.games = this.games.concat(moreGames); - } else this.hasMore = false; + } + else this.hasMore = false; } } ); @@ -950,8 +993,8 @@ export default { } } }, - loadNewchallVariant: async function(cb) { - const vname = this.getVname(this.newchallenge.vid); + loadNewchallVariant: async function(cb, vname) { + vname = vname || this.getVname(this.newchallenge.vid); await import("@/variants/" + vname + ".js") .then((vModule) => { window.V = vModule[vname + "Rules"]; @@ -974,10 +1017,11 @@ export default { ) { const parsedFen = V.ParseFen(this.newchallenge.fen); this.newchallenge.diag = getDiagram({ - position: parsedFen.position, - orientation: parsedFen.turn + position: parsedFen.position + //,orientation: parsedFen.turn }); - } else this.newchallenge.diag = ""; + } + else this.newchallenge.diag = ""; }, newChallFromPreset(pchall) { this.partialResetNewchallenge(); @@ -995,7 +1039,9 @@ export default { if (!this.newchallenge.vid) error = this.st.tr["Please select a variant"]; else if (ctype == "corr" && this.st.user.id <= 0) - error = this.st.tr["Please log in to play correspondance games"]; + error = this.st.tr["Please log in to play correspondence games"]; + else if (!this.newchallenge.to && !!this.newchallenge.color) + error = this.st.tr["Color option only for targeted challenge"]; else if (!!this.newchallenge.to) { if (this.newchallenge.to == this.st.user.name) error = this.st.tr["Self-challenge is forbidden"]; @@ -1005,8 +1051,14 @@ export default { ) { error = this.newchallenge.to + " " + this.st.tr["is not online"]; } + if ( + !!this.newchallenge.color && + !['w', 'b'].includes(this.newchallenge.color) + ) { + error = this.st.tr["Wrong color"]; + } } - if (error) { + if (!!error) { alert(error); return; } @@ -1018,13 +1070,18 @@ export default { } // NOTE: "from" information is not required here let chall = Object.assign({}, this.newchallenge); - // Add only if not already issued (not counting target or FEN): + // Add only if not already issued (not counting FEN): if (this.challenges.some(c => ( c.from.sid == this.st.user.sid || (c.from.id > 0 && c.from.id == this.st.user.id) ) && + ( + (!c.to && !chall.to) || + c.to == chall.to + ) + && c.vid == chall.vid && c.cadence == chall.cadence && c.randomness == chall.randomness @@ -1102,8 +1159,9 @@ export default { if (ctype == "live") { // Live challenges have a random ID finishAddChallenge(null); - } else { - // Correspondance game: send challenge to server + } + else { + // Correspondence game: send challenge to server ajax( "/challenges", "POST", @@ -1141,7 +1199,8 @@ export default { else // Corr challenge: just remove the challenge this.send("deletechallenge_s", { data: { cid: c.id } }); - } else { + } + else { const oppsid = this.getOppsid(c); if (!!oppsid) this.send("refusechallenge", { data: c.id, target: oppsid }); @@ -1165,25 +1224,26 @@ export default { alert(this.st.tr["Please log in to accept corr challenges"]); return; } - c.accepted = true; - await import("@/variants/" + c.vname + ".js") - .then((vModule) => { - window.V = vModule[c.vname + "Rules"]; - if (!!c.to) { - // c.to == this.st.user.name (connected) - if (!!c.fen) { - const parsedFen = V.ParseFen(c.fen); - c.mycolor = V.GetOppCol(parsedFen.turn); - this.tchallDiag = getDiagram({ - position: parsedFen.position, - orientation: c.mycolor - }); + else { + c.accepted = true; + await import("@/variants/" + c.vname + ".js") + .then((vModule) => { + window.V = vModule[c.vname + "Rules"]; + if (!!c.to) { + // c.to == this.st.user.name (connected) + if (!!c.fen) { + const parsedFen = V.ParseFen(c.fen); + this.tchallDiag = getDiagram({ + position: parsedFen.position, + orientation: parsedFen.turn + }); + } + this.curChallToAccept = c; + document.getElementById("modalAccept").checked = true; } - this.curChallToAccept = c; - document.getElementById("modalAccept").checked = true; - } - else this.finishProcessingChallenge(c); - }); + else this.finishProcessingChallenge(c); + }); + } } else { // My challenge @@ -1203,8 +1263,8 @@ export default { launchGame: function(c) { // White player index 0, black player index 1: let players = - !!c.mycolor - ? (c.mycolor == "w" ? [c.seat, c.from] : [c.from, c.seat]) + !!c.color + ? (c.color == "w" ? [c.from, c.seat] : [c.seat, c.from]) : shuffle([c.from, c.seat]); players.forEach(p => { if (!!p["tmpIds"]) delete p["tmpIds"]; @@ -1247,7 +1307,14 @@ export default { if (c.type == "live") { notifyNewgame(); this.startNewGame(gameInfo); - } else { + // Increment game stats counter in DB + ajax( + "/gamestat", + "POST", + { data: { vid: gameInfo.vid } } + ); + } + else { // corr: game only on server ajax( "/games", @@ -1288,23 +1355,22 @@ export default { () => { const myIdx = (game.players[0].sid == this.st.user.sid ? 0 : 1); GameStorage.add(game, (err) => { - // If an error occurred, game is not added: a tab already - // added the game. Maybe a focused one, maybe not. - // We know for sure that it emitted the gong start sound. - // ==> Do not play it again. - if (!err && this.st.settings.sound) - new Audio("/sounds/newgame.flac").play().catch(() => {}); + // If an error occurred, game is not added: the focused tab + // already added the game. if (!this.focus) { + if (this.st.settings.sound) + // This will be played several times if several hidden tabs + // on Hall... TODO: fix that (how ?!) + new Audio("/sounds/newgame.flac").play().catch(() => {}); notify( "New live game", - { body: "vs " + game.players[1-myIdx].name || "@nonymous" } + { body: "vs " + (game.players[1-myIdx].name || "@nonymous") } ); } - this.$router.push( - "/game/" + gameInfo.id + "/?focus=" + this.focus); + this.$router.push("/game/" + gameInfo.id); }); }, - this.focus ? 500 + 1000 * Math.random() : 0 + this.focus ? 0 : 500 + 1000 * Math.random() ); } } @@ -1365,9 +1431,11 @@ div#peopleWrap > .card button.player-action margin-left: 32px + &.focused + background-color: #E6D271 .somethingnew - background-color: #D6EAF8 !important + background-color: #90C4EC !important .tabbtn background-color: #f9faee @@ -1401,6 +1469,9 @@ button.refuseBtn #div2, #div3 margin-top: 0 +.user-bio + display: inline + tr > td &.random-0 background-color: #FF5733