Finished problems implementation. TODO: specify state for Crazyhouse,Grand. Improve...
authorBenjamin Auder <benjamin.auder@somewhere>
Sun, 16 Dec 2018 03:07:08 +0000 (04:07 +0100)
committerBenjamin Auder <benjamin.auder@somewhere>
Sun, 16 Dec 2018 03:07:08 +0000 (04:07 +0100)
13 files changed:
public/javascripts/base_rules.js
public/javascripts/components/game.js
public/javascripts/components/problemSummary.js
public/javascripts/components/problems.js
public/javascripts/utils/datetime.js [new file with mode: 0644]
public/javascripts/variant.js
public/javascripts/variants/Antiking.js
public/javascripts/variants/Checkered.js
public/javascripts/variants/Grand.js
public/javascripts/variants/Loser.js
public/javascripts/variants/Ultima.js
public/javascripts/variants/Wildebeest.js
views/variant.pug

index 5763af7..b44d085 100644 (file)
@@ -50,7 +50,7 @@ class ChessRules
        /////////////////
        // INITIALIZATION
 
-       // fen == "position flags"
+       // fen == "position [flags [turn]]"
        constructor(fen, moves)
        {
                this.moves = moves;
@@ -1107,7 +1107,7 @@ class ChessRules
                return pieces["b"].join("") +
                        "/pppppppp/8/8/8/8/PPPPPPPP/" +
                        pieces["w"].join("").toUpperCase() +
-                       " 1111"; //add flags
+                       " 1111 w"; //add flags + turn
        }
 
        // Return current fen according to pieces+colors state
@@ -1209,14 +1209,11 @@ class ChessRules
        // The score is already computed when calling this function
        getPGN(mycolor, score, fenStart, mode)
        {
-               const zeroPad = x => { return (x<10 ? "0" : "") + x; };
                let pgn = "";
                pgn += '[Site "vchess.club"]<br>';
-               const d = new Date();
                const opponent = mode=="human" ? "Anonymous" : "Computer";
                pgn += '[Variant "' + variant + '"]<br>';
-               pgn += '[Date "' + d.getFullYear() + '-' + (d.getMonth()+1) +
-                       '-' + zeroPad(d.getDate()) + '"]<br>';
+               pgn += '[Date "' + getDate(new Date()) + '"]<br>';
                pgn += '[White "' + (mycolor=='w'?'Myself':opponent) + '"]<br>';
                pgn += '[Black "' + (mycolor=='b'?'Myself':opponent) + '"]<br>';
                pgn += '[FenStart "' + fenStart + '"]<br>';
index 49db618..ded3091 100644 (file)
@@ -1,5 +1,6 @@
 // Game logic on a variant page
 Vue.component('my-game', {
+       props: ["problem"],
        data: function() {
                return {
                        vr: null, //object to check moves, store them, FEN..
@@ -23,6 +24,15 @@ Vue.component('my-game', {
                        sound: parseInt(getCookie("sound", "2")),
                };
        },
+       watch: {
+               problem: function(p, pp) {
+                       // 'problem' prop changed: update board state
+                       // TODO: FEN + turn + flags + rappel instructions / solution on click sous l'échiquier
+                       // TODO: trouver moyen de passer la situation des reserves pour Crazyhouse,
+                       // et l'état des captures pour Grand... bref compléter le descriptif de l'état.
+                       this.newGame("problem", p.fen, p.fen.split(" ")[2]);
+               },
+       },
        render(h) {
                const [sizeX,sizeY] = [V.size.x,V.size.y];
                const smallScreen = (window.innerWidth <= 420);
@@ -1077,7 +1087,7 @@ Vue.component('my-game', {
                                if (this.mycolor == 'b')
                                        setTimeout(this.playComputerMove, 500);
                        }
-                       //else: against a (IRL) friend: nothing more to do
+                       //else: against a (IRL) friend or problem solving: nothing more to do
                },
                playComputerMove: function() {
                        const timeStart = Date.now();
@@ -1130,8 +1140,9 @@ Vue.component('my-game', {
                                this.selectedPiece.style.display = "inline-block";
                                this.selectedPiece.style.zIndex = 3000;
                                let startSquare = this.getSquareFromId(e.target.parentNode.id);
-                               const iCanPlay = this.mode!="idle"
-                                       && (this.mode=="friend" || this.vr.canIplay(this.mycolor,startSquare));
+                               const iCanPlay = this.mode!="idle" &&
+                                       (["friend","problem"].includes(this.mode) ||
+                                       this.vr.canIplay(this.mycolor,startSquare));
                                this.possibleMoves = iCanPlay ? this.vr.getPossibleMovesFrom(startSquare) : [];
                                // Next line add moving piece just after current image
                                // (required for Crazyhouse reserve)
index 48a4253..c0b409d 100644 (file)
@@ -5,7 +5,7 @@ Vue.component('my-problem-summary', {
                <div class="problem col-sm-12" @click="showProblem()">
                        <div class="diagram" v-html="getDiagram(prob.fen)"></div>
                        <div class="problem-instructions" v-html="prob.instructions.substr(0,32)"></div>
-                       <div class="problem-time">{{ timestamp2datetime(prob.added) }}</div>
+                       <div class="problem-time">{{ timestamp2date(prob.added) }}</div>
                </div>
        `,
        methods: {
@@ -17,18 +17,12 @@ Vue.component('my-problem-summary', {
                                turn: fenParts[2],
                        });
                },
-               timestamp2datetime(ts) {
-                       // TODO
-                       return ts;
+               timestamp2date(ts) {
+                       return getDate(new Date(ts));
                },
+               // Propagate "show problem" event to parent component (my-problems)
                showProblem: function() {
-                       alert("show problem");
-                       //..........
-                       //TODO: send event with object prob.fen, prob.instructions, prob.solution
-                       //Event should propagate to game, which set mode=="problem" + other variables
-                       //click on a problem ==> land on variant page with mode==friend, FEN prefilled... ok
-                       // click on problem ==> masque problems, affiche game tab, launch new game Friend with
-                       //   FEN + turn + flags + rappel instructions / solution on click sous l'échiquier
+                       this.$emit('show-problem');
                },
        },
 })
index dbd8340..68830a4 100644 (file)
@@ -9,7 +9,7 @@ Vue.component('my-problems', {
                        <button @click="fetchProblems('backward')">Previous</button>
                        <button @click="fetchProblems('forward')">Next</button>
                        <button @click="showNewproblemModal">New</button>
-                       <my-problem-summary
+                       <my-problem-summary v-on:show-problem="bubbleUp(p)"
                                v-for="(p,idx) in sortedProblems" v-bind:prob="p" v-bind:key="idx">
                        </my-problem-summary>
                        <input type="checkbox" id="modal-newproblem" class="modal">
@@ -45,7 +45,6 @@ Vue.component('my-problems', {
        `,
        computed: {
                sortedProblems: function() {
-                       console.log("call");
                        // Newest problem first
                        return this.problems.sort((p1,p2) => { return p2.added - p1.added; });
                },
@@ -54,6 +53,10 @@ Vue.component('my-problems', {
                },
        },
        methods: {
+               // Propagate "show problem" event to parent component (my-variant)
+               bubbleUp: function(problem) {
+                       this.$emit('show-problem', JSON.stringify(problem));
+               },
                fetchProblems: function(direction) {
                        return; //TODO: re-activate after server side is implemented (see routes/all.js)
                        if (this.problems.length == 0)
diff --git a/public/javascripts/utils/datetime.js b/public/javascripts/utils/datetime.js
new file mode 100644 (file)
index 0000000..b6be6df
--- /dev/null
@@ -0,0 +1,15 @@
+function zeroPad(x)
+{
+       return (x<10 ? "0" : "") + x;
+}
+
+function getDate(d)
+{
+       return d.getFullYear() + '-' + (d.getMonth()+1) + '-' + zeroPad(d.getDate());
+}
+
+function getTime(d)
+{
+       return zeroPad(d.getHours()) + ":" + zeroPad(d.getMinutes()) + ":" +
+               zeroPad(d.getSeconds());
+}
index 2174c50..3aa2f68 100644 (file)
@@ -1,9 +1,9 @@
 new Vue({
        el: "#variantPage",
-       data: { display: "" }, //do not show anything...
-       // TODO: listen event "show problem", avec le probleme stringifié en arg
-       // Alors: display=game, mode=friend, newGame(fen, turn, ...),
-       //   et set Instructions+Soluce
+       data: {
+               display: "", //do not show anything...
+               problem: undefined, //current problem in view
+       },
        methods: {
                toggleDisplay: function(elt) {
                        if (this.display == elt)
@@ -11,5 +11,9 @@ new Vue({
                        else
                                this.display = elt; //show
                },
+               showProblem: function(problemTxt) {
+                       this.problem = JSON.parse(problemTxt);
+                       this.display = "game";
+               },
        },
 });
index 2821f3f..2b07cfb 100644 (file)
@@ -197,10 +197,9 @@ class AntikingRules extends ChessRules
                        + "A" + (antikingPos["w"]<7?7-antikingPos["w"]:"");
                const ranks23_white = (antikingPos["b"]>0?antikingPos["b"]:"") + "a"
                        + (antikingPos["b"]<7?7-antikingPos["b"]:"") + "/PPPPPPPP";
-               let fen = pieces["b"].join("") + "/" + ranks23_black +
+               return pieces["b"].join("") + "/" + ranks23_black +
                        "/8/8/" +
                        ranks23_white + "/" + pieces["w"].join("").toUpperCase() +
-                       " 1111";
-               return fen;
+                       " 1111 w";
        }
 }
index 585d20f..370c689 100644 (file)
@@ -47,15 +47,17 @@ class CheckeredRules extends ChessRules
                return !!flags.match(/^[01]{20,20}$/);
        }
 
-       setFlags(fen)
+       setFlags(fenflags)
        {
-               super.setFlags(fen); //castleFlags
+               super.setFlags(fenflags); //castleFlags
                this.pawnFlags =
                {
-                       "w": new Array(8), //pawns can move 2 squares?
-                       "b": new Array(8)
+                       "w": _.map(_.range(8), i => true), //pawns can move 2 squares?
+                       "b": _.map(_.range(8), i => true)
                };
-               const flags = fen.split(" ")[1].substr(4); //skip first 4 digits, for castle
+               if (!fenflags)
+                       return;
+               const flags = fenflags.substr(4); //skip first 4 digits, for castle
                for (let c of ['w','b'])
                {
                        for (let i=0; i<8; i++)
@@ -238,7 +240,9 @@ class CheckeredRules extends ChessRules
 
        static GenRandInitFen()
        {
-               return ChessRules.GenRandInitFen() + "1111111111111111"; //add 16 pawns flags
+               const randFen = ChessRules.GenRandInitFen();
+               // Add 16 pawns flags:
+               return randFen.replace(" 1111 w", " 11111111111111111111 w");
        }
 
        getFlagsFen()
index cafdada..276acbc 100644 (file)
@@ -275,10 +275,9 @@ class GrandRules extends ChessRules
                        pieces[c][knight2Pos] = 'n';
                        pieces[c][rook2Pos] = 'r';
                }
-               let fen = pieces["b"].join("") +
+               return pieces["b"].join("") +
                        "/pppppppppp/10/10/10/10/10/10/PPPPPPPPPP/" +
                        pieces["w"].join("").toUpperCase() +
-                       " 1111";
-               return fen;
+                       " 1111 w";
        }
 }
index 98bd944..2d60d6e 100644 (file)
@@ -11,7 +11,7 @@ class LoserRules extends ChessRules
                return true; //anything is good: no flags
        }
 
-       setFlags(fen)
+       setFlags(fenflags)
        {
                // No castling, hence no flags; but flags defined for compatibility
                this.castleFlags = { "w":[false,false], "b":[false,false] };
@@ -197,6 +197,6 @@ class LoserRules extends ChessRules
                return pieces["b"].join("") +
                        "/pppppppp/8/8/8/8/PPPPPPPP/" +
                        pieces["w"].join("").toUpperCase() +
-                       " 0000"; //add flags (TODO?!)
+                       " 0000 w"; //add flags (TODO?!)
        }
 }
index d6fecb7..05fba2f 100644 (file)
@@ -45,7 +45,7 @@ class UltimaRules extends ChessRules
                this.epSquares = []; //no en-passant here
        }
 
-       setFlags(fen)
+       setFlags(fenflags)
        {
                // TODO: for compatibility?
                this.castleFlags = {"w":[false,false], "b":[false,false]};
@@ -608,7 +608,7 @@ class UltimaRules extends ChessRules
                return pieces["b"].join("") +
                        "/pppppppp/8/8/8/8/PPPPPPPP/" +
                        pieces["w"].join("").toUpperCase() +
-                       " 0000"; //TODO: flags?!
+                       " 0000 w"; //TODO: flags?!
        }
 
        getFlagsFen()
index dcf2d58..9b07410 100644 (file)
@@ -245,10 +245,9 @@ class WildebeestRules extends ChessRules
                        pieces[c][knight2Pos] = 'n';
                        pieces[c][rook2Pos] = 'r';
                }
-               let fen = pieces["b"].join("") +
+               return pieces["b"].join("") +
                        "/ppppppppppp/11/11/11/11/11/11/PPPPPPPPPPP/" +
                        pieces["w"].join("").toUpperCase() +
-                       " 1111";
-               return fen;
+                       " 1111 w";
        }
 }
index 37bd5e7..b1caabd 100644 (file)
@@ -14,11 +14,12 @@ block content
                        .col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2
                                h4.variantpage-title.text-center(v-on:click="toggleDisplay('game')")
                                        | #{variant} Game
-                               my-game(v-show="display=='game'")
+                               my-game(v-show="display=='game'" v-bind:problem="problem")
                        .col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2
                                h4.variantpage-title.text-center(v-on:click="toggleDisplay('problems')")
                                        | #{variant} Problems
-                               my-problems(v-show="display=='problems'")
+                               my-problems(v-show="display=='problems'"
+                                       v-on:show-problem="showProblem($event)")
 
 block javascripts
        script(src="/javascripts/utils/misc.js")
@@ -27,6 +28,7 @@ block javascripts
        script(src="/javascripts/utils/md5.js")
        script(src="/javascripts/utils/printDiagram.js")
        script(src="/javascripts/utils/ajax.js")
+       script(src="/javascripts/utils/datetime.js")
        script(src="/javascripts/base_rules.js")
        script(src="/javascripts/variants/" + variant + ".js")
        script.