*.wav filter=fat
*.mp3 filter=fat
*.png filter=fat
+*.sqlite filter=fat
--- /dev/null
+create table Variants (
+ name varchar primary key,
+ description text
+);
+insert into Variants values
+ ('Checkered', 'Shared pieces'),
+ ('Zen', 'Reverse captures'),
+ ('Atomic', 'Explosive captures'),
+ ('Chess960', 'Standard rules'),
+ ('Antiking', 'Keep antiking in check'),
+ ('Magnetic', 'Laws of attraction'),
+ ('Alice', 'Both sides of the mirror'),
+ ('Grand', 'Big board'),
+ ('Wildebeest', 'Balanced sliders & leapers'),
+ ('Loser', 'Lose all pieces'),
+ ('Crazyhouse', 'Captures reborn'),
+ ('Switching', 'Exchange pieces positions'),
+ ('Extinction', 'Capture all of a kind'),
+ ('Ultima', 'Exotic captures');
+
+create table Problems (
+ added datetime,
+ variant varchar,
+ fen varchar,
+ instructions text,
+ solution text,
+ foreign key (variant) references Variants(name)
+);
+--PRAGMA foreign_keys = ON;
--- /dev/null
+#$# git-fat 25d1d22208da0bc58bf3076bfe684bbcb98894b2 16384
{
- "name": "vc",
- "version": "0.0.0",
+ "name": "vchess",
+ "version": "0.1.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
}
}
},
+ "array-uniq": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+ "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY="
+ },
"array-unique": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
"upath": "^1.0.5"
}
},
+ "chownr": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
+ "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g=="
+ },
"ci-info": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
"requires": {
"color-name": "1.1.3"
}
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
- "dev": true
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"color-support": {
"version": "1.1.3",
"dev": true
},
"colors": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.2.tgz",
- "integrity": "sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ==",
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz",
+ "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==",
"dev": true
},
"combined-stream": {
"deep-extend": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
- "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
- "dev": true
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
},
"default-compare": {
"version": "1.0.0",
"integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=",
"dev": true
},
+ "detect-libc": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
+ "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
+ },
"doctypes": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz",
"integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk="
},
+ "dom-serializer": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
+ "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=",
+ "requires": {
+ "domelementtype": "~1.1.1",
+ "entities": "~1.1.1"
+ },
+ "dependencies": {
+ "domelementtype": {
+ "version": "1.1.3",
+ "resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
+ "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs="
+ }
+ }
+ },
+ "domelementtype": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
+ },
+ "domhandler": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+ "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+ "requires": {
+ "domelementtype": "1"
+ }
+ },
+ "domutils": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
+ "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
+ "requires": {
+ "dom-serializer": "0",
+ "domelementtype": "1"
+ }
+ },
"dot-prop": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
"is-obj": "^1.0.0"
}
},
- "duplexer": {
- "version": "0.1.1",
- "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
- "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
- "dev": true
- },
"duplexer3": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
"once": "^1.4.0"
}
},
+ "entities": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+ "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
+ },
"error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
},
- "event-stream": {
- "version": "3.3.6",
- "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.6.tgz",
- "integrity": "sha512-dGXNg4F/FgVzlApjzItL+7naHutA3fDqbV/zAZqDDlXTjiMnQmZKu+prImWKszeBM5UQeGvAl3u1wBiKeDh61g==",
- "dev": true,
- "requires": {
- "duplexer": "^0.1.1",
- "flatmap-stream": "^0.1.0",
- "from": "^0.1.7",
- "map-stream": "0.0.7",
- "pause-stream": "^0.0.11",
- "split": "^1.0.1",
- "stream-combiner": "^0.2.2",
- "through": "^2.3.8"
- }
- },
"execa": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
},
"fancy-log": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz",
- "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=",
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz",
+ "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==",
"dev": true,
"requires": {
"ansi-gray": "^0.1.1",
"color-support": "^1.1.3",
+ "parse-node-version": "^1.0.0",
"time-stamp": "^1.0.0"
}
},
}
},
"fined": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz",
- "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.1.tgz",
+ "integrity": "sha512-jQp949ZmEbiYHk3gkbdtpJ0G1+kgtLQBNdP5edFP7Fh+WAYceLQz6yO1SBj72Xkg8GVyTB3bBzAYrHJVh5Xd5g==",
"dev": true,
"requires": {
"expand-tilde": "^2.0.2",
}
},
"flagged-respawn": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz",
- "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=",
- "dev": true
- },
- "flatmap-stream": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/flatmap-stream/-/flatmap-stream-0.1.1.tgz",
- "integrity": "sha512-lAq4tLbm3sidmdCN8G3ExaxH7cUCtP5mgDvrYowsx84dcYkJJ4I28N7gkxA6+YlSXzaGLJYIDEi9WGfXzMiXdw==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz",
+ "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==",
"dev": true
},
"flush-write-stream": {
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
- "from": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
- "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=",
- "dev": true
+ "fs-minipass": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz",
+ "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==",
+ "requires": {
+ "minipass": "^2.2.1"
+ }
},
"fs-mkdirp-stream": {
"version": "1.0.0",
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"aproba": {
"version": "1.2.0",
"balanced-match": {
"version": "1.0.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
"code-point-at": {
"version": "1.1.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"core-util-is": {
"version": "1.0.2",
"inherits": {
"version": "2.0.3",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"ini": {
"version": "1.3.5",
"version": "1.0.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
"version": "3.0.4",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
"minimist": {
"version": "0.0.8",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"minipass": {
"version": "2.2.4",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
"version": "0.5.1",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"minimist": "0.0.8"
}
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"object-assign": {
"version": "4.1.1",
"version": "1.4.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"wrappy": "1"
}
"safe-buffer": {
"version": "5.1.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"safer-buffer": {
"version": "2.1.2",
"version": "1.0.2",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
"version": "3.0.1",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
"wrappy": {
"version": "1.0.2",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"yallist": {
"version": "3.0.2",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
}
}
},
}
},
"glob-watcher": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.1.tgz",
- "integrity": "sha512-fK92r2COMC199WCyGUblrZKhjra3cyVMDiypDdqg1vsSDmexnbYivK1kNR4QItiNXLKmGlqan469ks67RtNa2g==",
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz",
+ "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==",
"dev": true,
"requires": {
+ "anymatch": "^2.0.0",
"async-done": "^1.2.0",
"chokidar": "^2.0.0",
+ "is-negated-glob": "^1.0.0",
"just-debounce": "^1.0.0",
"object.defaults": "^1.1.0"
}
}
},
"glogg": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz",
- "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz",
+ "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==",
"dev": true,
"requires": {
"sparkles": "^1.0.0"
}
},
"gulp-nodemon": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/gulp-nodemon/-/gulp-nodemon-2.4.1.tgz",
- "integrity": "sha512-IZMEfUZggvXvYDCCbb4jq8xMSsS24OltlgL0KhumhDAbZJUHMm3tHEolHbNLLL9704Wm/DgZ5bdFqCb2hXG0bQ==",
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/gulp-nodemon/-/gulp-nodemon-2.4.2.tgz",
+ "integrity": "sha512-r8ShC9yzL3lK5qUsTStMeZRwqLG6t2m4lEBVcfUYzVkiYSeYXu9xYXG5rfvzBOPZOZ2dWugTKr+zeWbnMnzWDA==",
"dev": true,
"requires": {
"colors": "^1.2.1",
- "event-stream": "^3.3.4",
"gulp": "^4.0.0",
- "nodemon": "^1.17.5"
+ "nodemon": "^1.18.7"
}
},
"gulplog": {
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
- "dev": true
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
},
"has-symbols": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz",
"integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w=="
},
+ "htmlparser2": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.0.tgz",
+ "integrity": "sha512-J1nEUGv+MkXS0weHNWVKJJ+UrLfePxRWpN3C9bEi9fLxL2+ggW94DQvgYVXsaT30PGwYRIZKNZXuyMhp3Di4bQ==",
+ "requires": {
+ "domelementtype": "^1.3.0",
+ "domhandler": "^2.3.0",
+ "domutils": "^1.5.1",
+ "entities": "^1.1.1",
+ "inherits": "^2.0.1",
+ "readable-stream": "^3.0.6"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.0.6.tgz",
+ "integrity": "sha512-9E1oLoOWfhSXHGv6QlwXJim7uNzd9EVlWK+21tCU9Ju/kR0/p2AZYPz4qSchgO8PlLIH4FpZYfzwS+rEksZjIg==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
"http-errors": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.1.tgz",
"integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=",
"dev": true
},
+ "ignore-walk": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz",
+ "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==",
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
"import-lazy": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
"ini": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
- "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
- "dev": true
+ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
},
"interpret": {
"version": "1.1.0",
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
"dev": true
},
+ "lodash.escaperegexp": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz",
+ "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c="
+ },
+ "lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
+ },
+ "lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
+ },
"lodash.mergewith": {
"version": "4.6.1",
"resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz",
"resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
"integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0="
},
- "map-stream": {
- "version": "0.0.7",
- "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz",
- "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=",
- "dev": true
- },
"map-visit": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
},
+ "minipass": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz",
+ "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ },
+ "dependencies": {
+ "yallist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
+ "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A=="
+ }
+ }
+ },
+ "minizlib": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz",
+ "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==",
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
"mixin-deep": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz",
}
}
},
+ "needle": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.4.tgz",
+ "integrity": "sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==",
+ "requires": {
+ "debug": "^2.1.2",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
"negotiator": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
}
}
},
+ "node-pre-gyp": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz",
+ "integrity": "sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A==",
+ "requires": {
+ "detect-libc": "^1.0.2",
+ "mkdirp": "^0.5.1",
+ "needle": "^2.2.1",
+ "nopt": "^4.0.1",
+ "npm-packlist": "^1.1.6",
+ "npmlog": "^4.0.2",
+ "rc": "^1.2.7",
+ "rimraf": "^2.6.1",
+ "semver": "^5.3.0",
+ "tar": "^4"
+ },
+ "dependencies": {
+ "nopt": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
+ "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
+ "requires": {
+ "abbrev": "1",
+ "osenv": "^0.1.4"
+ }
+ },
+ "tar": {
+ "version": "4.4.8",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz",
+ "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==",
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.3.4",
+ "minizlib": "^1.1.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.2"
+ }
+ },
+ "yallist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
+ "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A=="
+ }
+ }
+ },
"node-sass": {
"version": "4.10.0",
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.10.0.tgz",
}
},
"nodemon": {
- "version": "1.18.6",
- "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.18.6.tgz",
- "integrity": "sha512-4pHQNYEZun+IkIC2jCaXEhkZnfA7rQe73i8RkdRyDJls/K+WxR7IpI5uNUsAvQ0zWvYcCDNGD+XVtw2ZG86/uQ==",
+ "version": "1.18.9",
+ "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.18.9.tgz",
+ "integrity": "sha512-oj/eEVTEI47pzYAjGkpcNw0xYwTl4XSTUQv2NPQI6PpN3b75PhpuYk3Vb3U80xHCyM2Jm+1j68ULHXl4OR3Afw==",
"dev": true,
"requires": {
"chokidar": "^2.0.4",
"debug": "^3.1.0",
"ignore-by-default": "^1.0.1",
"minimatch": "^3.0.4",
- "pstree.remy": "^1.1.0",
+ "pstree.remy": "^1.1.6",
"semver": "^5.5.0",
"supports-color": "^5.2.0",
"touch": "^3.1.0",
"undefsafe": "^2.0.2",
- "update-notifier": "^2.3.0"
+ "update-notifier": "^2.5.0"
},
"dependencies": {
"debug": {
"once": "^1.3.2"
}
},
+ "npm-bundled": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.5.tgz",
+ "integrity": "sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g=="
+ },
+ "npm-packlist": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.12.tgz",
+ "integrity": "sha512-WJKFOVMeAlsU/pjXuqVdzU0WfgtIBCupkEVwn+1Y0ERAbUfWw8R4GjgVbaKnUjRoD2FoQbHOCbOyT5Mbs9Lw4g==",
+ "requires": {
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1"
+ }
+ },
"npm-run-path": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
"error-ex": "^1.2.0"
}
},
+ "parse-node-version": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.0.tgz",
+ "integrity": "sha512-02GTVHD1u0nWc20n2G7WX/PgdhNFG04j5fi1OkaJzPWLTcf6vh6229Lta1wTmXG/7Dg42tCssgkccVt7qvd8Kg==",
+ "dev": true
+ },
"parse-passwd": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
"pinkie-promise": "^2.0.0"
}
},
- "pause-stream": {
- "version": "0.0.11",
- "resolved": "http://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
- "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=",
- "dev": true,
- "requires": {
- "through": "~2.3"
- }
- },
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
"dev": true
},
+ "postcss": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz",
+ "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==",
+ "requires": {
+ "chalk": "^2.4.1",
+ "source-map": "^0.6.1",
+ "supports-color": "^5.5.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
+ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
"prepend-http": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
"ipaddr.js": "1.8.0"
}
},
- "ps-tree": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.0.tgz",
- "integrity": "sha1-tCGyQUDWID8e08dplrRCewjowBQ=",
- "dev": true,
- "requires": {
- "event-stream": "~3.3.0"
- }
- },
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
"integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ=="
},
"pstree.remy": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.0.tgz",
- "integrity": "sha512-q5I5vLRMVtdWa8n/3UEzZX7Lfghzrg9eG2IKk2ENLSofKRCXVqMvMUHxCKgXNaqH/8ebhBxrqftHWnyTFweJ5Q==",
- "dev": true,
- "requires": {
- "ps-tree": "^1.1.0"
- }
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.6.tgz",
+ "integrity": "sha512-NdF35+QsqD7EgNEI5mkI/X+UwaxVEbQaz9f4IooEmMUv6ZPmlTQYGjBPJGgrlzNdjSvIy4MWMg6Q6vCgBO2K+w==",
+ "dev": true
},
"pug": {
"version": "2.0.3",
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
- "dev": true,
"requires": {
"deep-extend": "^0.6.0",
"ini": "~1.3.0",
"minimist": {
"version": "1.2.0",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
- "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
- "dev": true
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
}
}
},
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
+ "sanitize-html": {
+ "version": "1.19.3",
+ "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.19.3.tgz",
+ "integrity": "sha512-QpIjbF1rhUSQj9V7Wey/gv4DPqOso8KTebaI4rC97p0WCLnTpmhf7BJZUhS83MTtqRvUo8MuXH316CW2Nzd48w==",
+ "requires": {
+ "chalk": "^2.4.1",
+ "htmlparser2": "^3.10.0",
+ "lodash.clonedeep": "^4.5.0",
+ "lodash.escaperegexp": "^4.1.2",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.isstring": "^4.0.1",
+ "lodash.mergewith": "^4.6.1",
+ "postcss": "^7.0.5",
+ "srcset": "^1.0.0",
+ "xtend": "^4.0.1"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
+ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
"sass-graph": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz",
"yargs": "^7.0.0"
}
},
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
+ },
"scss-tokenizer": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz",
"integrity": "sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg=="
},
- "split": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
- "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
- "dev": true,
- "requires": {
- "through": "2"
- }
- },
"split-string": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
"extend-shallow": "^3.0.0"
}
},
+ "sqlite3": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.0.4.tgz",
+ "integrity": "sha512-CO8vZMyUXBPC+E3iXOCc7Tz2pAdq5BWfLcQmOokCOZW5S5sZ/paijiPOCdvzpdP83RroWHYa5xYlVqCxSqpnQg==",
+ "requires": {
+ "nan": "~2.10.0",
+ "node-pre-gyp": "^0.10.3",
+ "request": "^2.87.0"
+ },
+ "dependencies": {
+ "nan": {
+ "version": "2.10.0",
+ "resolved": "http://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
+ "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA=="
+ }
+ }
+ },
+ "srcset": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/srcset/-/srcset-1.0.0.tgz",
+ "integrity": "sha1-pWad4StC87HV6D7QPHEEb8SPQe8=",
+ "requires": {
+ "array-uniq": "^1.0.2",
+ "number-is-nan": "^1.0.0"
+ }
+ },
"sshpk": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz",
"readable-stream": "^2.0.1"
}
},
- "stream-combiner": {
- "version": "0.2.2",
- "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz",
- "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=",
- "dev": true,
- "requires": {
- "duplexer": "~0.1.1",
- "through": "~2.3.4"
- }
- },
"stream-exhaust": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz",
"strip-json-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
- "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
- "dev": true
+ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
},
"supports-color": {
"version": "2.0.0",
"execa": "^0.7.0"
}
},
- "through": {
- "version": "2.3.8",
- "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
- "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
- "dev": true
- },
"through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
}
},
"ws": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.0.tgz",
- "integrity": "sha512-H3dGVdGvW2H8bnYpIDc3u3LH8Wue3Qh+Zto6aXXFzvESkTVT6rAfKR6tR/+coaUvxs8yHtmNV0uioBF62ZGSTg==",
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.2.tgz",
+ "integrity": "sha512-rfUqzvz0WxmSXtJpPMX2EeASXabOrSMk1ruMOV3JBTBjo4ac2lDjGGsbQSyxj8Odhw5fBib8ZKEjDNvgouNKYw==",
"requires": {
"async-limiter": "~1.0.0"
}
"xtend": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
- "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
- "dev": true
+ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
},
"y18n": {
"version": "3.2.1",
"morgan": "~1.9.1",
"node-sass-middleware": "~0.11.0",
"pug": "~2.0.3",
+ "sanitize-html": "^1.19.3",
"serve-favicon": "~2.5.0",
- "ws": "~6.1.0"
+ "sqlite3": "^4.0.4",
+ "ws": "^6.1.2"
},
"devDependencies": {
- "gulp-nodemon": "~2.4.1"
+ "gulp-nodemon": "^2.4.2"
}
}
}),
h('div',
{
- attrs: { "role": "dialog", "aria-labelledby": "modal-eog" },
+ attrs: { "role": "dialog", "aria-labelledby": "eogMessage" },
},
[
h('div',
),
h('h3',
{
+ attrs: { "id": "eogMessage" },
"class": { "section": true },
domProps: { innerHTML: eogMessage },
}
}),
h('div',
{
- attrs: { "role": "dialog", "aria-labelledby": "modal-newgame" },
+ attrs: { "role": "dialog", "aria-labelledby": "newGameTxt" },
},
[
h('div',
),
h('h3',
{
+ attrs: { "id": "newGameTxt" },
"class": { "section": true },
domProps: { innerHTML: "New game" },
}
}),
h('div',
{
- attrs: { "role": "dialog", "aria-labelledby": "modal-fenedit" },
+ attrs: { "role": "dialog", "aria-labelledby": "titleFenedit" },
},
[
h('div',
),
h('h3',
{
+ attrs: { "id": "titleFenedit" },
"class": { "section": true },
domProps: { innerHTML: "Position + flags (FEN):" },
}
}),
h('div',
{
- attrs: { "role": "dialog", "aria-labelledby": "modal-settings" },
+ attrs: { "role": "dialog", "aria-labelledby": "settingsTitle" },
},
[
h('div',
),
h('h3',
{
+ attrs: { "id": "settingsTitle" },
"class": { "section": true },
domProps: { innerHTML: "Preferences" },
}
--- /dev/null
+// Show a problem summary on variant page
+Vue.component('my-problem-summary', {
+ props: ['prob'],
+ template: `
+ <div class="problem col-sm-12">
+ <div class="diagram">
+ {{ getDiagram(prob.fen) }}
+ </div>
+ <div class="problem-instructions">
+ {{ prob.instructions.substr(0,32) }}
+ </div>
+ <div class="problem-time">
+ {{ prob.added }}
+ </div>
+ </div>
+ `,
+})
-//TODO: list problems as FEN (quickly rendered), by date, with possible filtering per variant(?)
-//click on a problem ==> land on variant page with mode==friend, FEN prefilled... ok
-
-// get 10 first problems, and buttons next<>previous send date + "before" or "after"
-// need database: sqlite !
-
-// form "new problem" fen(position/turn/flags[guess]), instructions, solution (mandatory)
-// ==> upload on server in sandbox
-//
-// Atomic rules, atomic game, atomic problems(list drawn position
-// + summary(first chars of instructions) + timedate)... one big Vue ? with components
-//
-// click on problem ==> masque problems, affiche game tab, launch new game Friend with
-// FEN + turn + flags + rappel instructions / solution on click sous l'échiquier
-
Vue.component('my-problems', {
- //props: ['vobj'],
+ data: function () {
+ return {
+ problems: problemArray //initial value
+ };
+ },
template: `
- <div class="variant col-sm-12">
- <p>Hello</p>
+ <div>
+ <button>Previous</button>
+ <button>Next</button>
+ <button @click="showNewproblemModal">New</button>
+ <my-problem-summary
+ v-for="(p,idx) in sortedProblems",
+ v-bind:prob="p",
+ v-bind:key="idx",
+ @click="showProblem(p)"
+ </my-problem-summary>
+ <input type="checkbox" id="modal-newproblem" class="modal">
+ <div role="dialog" aria-labelledby="newProblemTxt">
+ <div class="card newproblem">
+ <label for="modal-newproblem" class="modal-close"></label>
+ <h3 id="newProblemTxt">Add problem</h3>
+ <form @submit.prevent="postNewProblem">
+ <fieldset>
+ <label for="newpbFen">Fen</label>
+ <input type="text" id="newpbFen" placeholder="Position [+ flags [+ turn]]"/>
+ </fieldset>
+ <fieldset>
+ <p class="emphasis">
+ Allowed HTML tags:
+ <p>,<br>,<,ul>,<ol>,<li>
+ </p>
+ <label for="newpbInstructions">Instructions</label>
+ <textarea id="newpbInstructions" placeholder="Explain the problem here"/>
+ <label for="newpbSolution">Solution</label>
+ <textarea id="newpbSolution" placeholder="How to solve the problem?"/>
+ <button class="center-btn">Send</button>
+ </fieldset>
+ <p class="mistake-newproblem">
+ Note: if you made a mistake, please let me know at
+ <a :href="mailErrProblem">contact@vchess.club</a>
+ </p>
+ </form>
+ </div>
+ </div>
</div>
`,
+ computed: {
+ sortedProblems: function() {
+ // Newest problem first
+ return problems.sort((p1,p2) => { return p2.added - p1.added; });
+ },
+ mailErrProblem: function() {
+ return "mailto:contact@vchess.club?subject=[" + variant + " problems] error";
+ },
+ },
+ methods: {
+ fetchProblems: function(direction) {
+ // TODO: ajax call return list of max 10 problems
+ // Do not do anything if no older problems (and store this result in cache!)
+ // TODO: ajax call return list of max 10 problems
+ // Do not do anything if no newer problems
+ },
+ showProblem: function(prob) {
+ //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
+ },
+ showNewproblemModal: function() {
+ document.getElementById("modal-newproblem").checked = true;
+ },
+ postNewProblem: function() {
+ const fen = document.getElementById("newpbFen").value;
+ const instructions = document.getElementById("newpbInstructions").value;
+ const solution = document.getElementById("newpbSolution").value;
+
+ },
+ },
})
template: `<div v-html="content" class="section-content"></div>`,
mounted: function() {
// AJAX request to get rules content (plain text, HTML)
- let xhr = new XMLHttpRequest();
- let self = this;
- xhr.onreadystatechange = function() {
- if (this.readyState == 4 && this.status == 200)
- {
- let replaceByDiag = (match, p1, p2) => { return self.drawDiag(p2); };
- self.content = xhr.responseText.replace(/(fen:)([^:]*):/g, replaceByDiag);
- }
- };
- xhr.open("GET", "/rules/" + variant, true);
- xhr.setRequestHeader('X-Requested-With', "XMLHttpRequest");
- xhr.send();
+ ajax("/rules/" + variant, "GET", response => {
+ let replaceByDiag = (match, p1, p2) => {
+ const args = self.parseFen(p2);
+ return getDiagram(args);
+ };
+ self.content = response.replace(/(fen:)([^:]*):/g, replaceByDiag);
+ }
},
methods: {
- drawDiag: function(fen) {
- let [sizeX,sizeY] = [V.size.x,V.size.y];
- let fenParts = fen.split(" ");
- // Obtain array of pieces images names
- let board = VariantRules.GetBoard(fenParts[0]);
- let orientation = "w";
- if (fenParts.length >= 2)
- orientation = fenParts[1];
- let markArray = [];
- if (fenParts.length >= 3)
- {
- let marks_str = fenParts[2];
- // Turn (human) marks into coordinates
- markArray = doubleArray(sizeX, sizeY, false);
- let marks = marks_str.split(",");
- for (let i=0; i<marks.length; i++)
- {
- var res = /^([a-z]+)([0-9]+)$/i.exec(marks[i]);
- let x = sizeX - parseInt(res[2]); //white at bottom, so counting is reversed
- let y = res[1].charCodeAt(0)-97; //always one char: max 26, big enough
- markArray[x][y] = true;
- }
- }
- let boardDiv = "";
- let [startX,startY,inc] = orientation == 'w'
- ? [0, 0, 1]
- : [sizeX-1, sizeY-1, -1];
- for (let i=startX; i>=0 && i<sizeX; i+=inc)
- {
- boardDiv += "<div class='row'>";
- for (let j=startY; j>=0 && j<sizeY; j+=inc)
- {
- boardDiv += "<div class='board board" + sizeY + " " +
- ((i+j)%2==0 ? "light-square-diag" : "dark-square-diag") + "'>";
- if (board[i][j] != VariantRules.EMPTY)
- {
- boardDiv += "<img src='/images/pieces/" +
- VariantRules.getPpath(board[i][j]) + ".svg' class='piece'/>";
- }
- if (markArray.length>0 && markArray[i][j])
- boardDiv += "<img src='/images/mark.svg' class='mark-square'/>";
- boardDiv += "</div>";
- }
- boardDiv += "</div>";
- }
- return boardDiv;
+ parseFen(fen) {
+ const fenParts = fen.split(" ");
+ return {
+ position: fenParts[0],
+ marks: fenParts[1],
+ orientation: fenParts[2],
+ };
},
},
})
--- /dev/null
+// From JSON (encoded string values!) to "arg1=...&arg2=..."
+function toQueryString(data)
+{
+ let data_str = "";
+ Object.keys(data).forEach(k => {
+ data_str += k + "=" + data[k] + "&";
+ });
+ return data_str.slice(0, -1); //remove last "&"
+}
+
+// data, error: optional
+function ajax(url, method, data, success, error)
+{
+ let xhr = new XMLHttpRequest();
+ if (typeof(data) === "function") //no data
+ {
+ error = success;
+ success = data;
+ data = {};
+ }
+ if (!error)
+ error = errmsg => { alert(errmsg); };
+
+ xhr.onreadystatechange = function() {
+ if (this.readyState == 4 && this.status == 200)
+ {
+ try {
+ let res_json = JSON.parse(xhr.responseText);
+ if (!res_json.errmsg)
+ success(res_json);
+ else
+ error(res_json.errmsg);
+ } catch (e) {
+ // Plain text (e.g. for rules retrieval)
+ success(xhr.responseText);
+ }
+ }
+ };
+
+ if (["GET","DELETE"].includes(method) && !!data)
+ {
+ // Append query params to URL
+ url += "/?" + toQueryString(data);
+ }
+
+ xhr.open(method, url, true);
+ xhr.setRequestHeader('X-Requested-With', "XMLHttpRequest");
+ if (["POST","PUT"].includes(method))
+ {
+ xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
+ xhr.send(JSON.stringify(data));
+ }
+ else
+ xhr.send();
+}
--- /dev/null
+// Assuming V(ariantRules) class is loaded.
+// args: object with position (mandatory), orientation, marks (optional)
+function getDiagram(args)
+{
+ const [sizeX,sizeY] = [V.size.x,V.size.y];
+ // Obtain array of pieces images names
+ const board = VariantRules.GetBoard(args.position);
+ const orientation = args.orientation || "w";
+ let markArray = [];
+ if (!!args.marks)
+ {
+ // Turn (human) marks into coordinates
+ markArray = doubleArray(sizeX, sizeY, false);
+ let squares = args.marks.split(",");
+ for (let i=0; i<squares.length; i++)
+ {
+ const res = /^([a-z]+)([0-9]+)$/i.exec(squares[i]);
+ const x = sizeX - parseInt(res[2]); //white at bottom, so counting is reversed
+ const y = res[1].charCodeAt(0)-97; //always one char: max 26, big enough
+ markArray[x][y] = true;
+ }
+ }
+ let boardDiv = "";
+ const [startX,startY,inc] = orientation == 'w'
+ ? [0, 0, 1]
+ : [sizeX-1, sizeY-1, -1];
+ for (let i=startX; i>=0 && i<sizeX; i+=inc)
+ {
+ boardDiv += "<div class='row'>";
+ for (let j=startY; j>=0 && j<sizeY; j+=inc)
+ {
+ boardDiv += "<div class='board board" + sizeY + " " +
+ ((i+j)%2==0 ? "light-square-diag" : "dark-square-diag") + "'>";
+ if (board[i][j] != V.EMPTY)
+ {
+ boardDiv += "<img src='/images/pieces/" +
+ V.getPpath(board[i][j]) + ".svg' class='piece'/>";
+ }
+ if (!!args.marks && markArray[i][j])
+ boardDiv += "<img src='/images/mark.svg' class='mark-square'/>";
+ boardDiv += "</div>";
+ }
+ boardDiv += "</div>";
+ }
+ return boardDiv;
+}
#fen-div > p
margin-left: 0
margin-right: 0
+
+.newproblem input, .newproblem textarea
+ width: 100%
+
+.emphasis
+ font-style: italic
+
+#newpbInstructions
+ margin-bottom: var(--universal-margin);
+
+.center-btn
+ margin-left: 40%
+
+//TODO?
+.center-inline
+ text-align: center
+.center-block
+ margin-left: auto
+ margin-right: auto
+
+.mistake-newproblem
+ color: #663300
-var express = require('express');
-var router = express.Router();
-var createError = require('http-errors');
-
-const Variants = require("../variants");
+let express = require('express');
+let router = express.Router();
+const createError = require('http-errors');
+const sqlite3 = require('sqlite3');//.verbose();
+const db = new sqlite3.Database('db/vchess.sqlite');
+const sanitizeHtml = require('sanitize-html');
// Home
router.get('/', function(req, res, next) {
- res.render('index', {
- title: 'club',
- variantArray: Variants, //JSON.stringify(Variants)
+ db.serialize(function() {
+ db.all("SELECT * FROM Variants", (err,variants) => {
+ if (!!err)
+ return next(err);
+ res.render('index', {
+ title: 'club',
+ variantArray: variants, //JSON.stringify(variants)
+ });
+ });
});
});
// Variant
router.get("/:vname([a-zA-Z0-9]+)", (req,res,next) => {
const vname = req.params["vname"];
- if (!Variants.some(v => { return (v.name == vname); }))
- return next(createError(404));
- res.render('variant', {
- title: vname + ' Variant',
- variant: vname,
+ db.serialize(function() {
+ db.all("SELECT * FROM Variants WHERE name='" + vname + "'", (err,variant) => {
+ if (!!err)
+ return next(err);
+ if (!variant || variant.length==0)
+ return next(createError(404));
+ db.all("SELECT * FROM Problems WHERE variant='" + vname + "'",
+ (err2,problems) => {
+ if (!!err2)
+ return next(err2);
+ res.render('variant', {
+ title: vname + ' Variant',
+ variant: vname,
+ problemArray: problems,
+ });
+ }
+ );
+ });
});
});
// Load a rules page (AJAX)
router.get("/rules/:variant([a-zA-Z0-9]+)", (req,res) => {
- res.render("rules/" + req.params["variant"]);
+ if (!req.xhr)
+ return res.json({errmsg: "Unauthorized access"});
+ res.render("rules/" + req.params["variant"]);
+});
+
+// Fetch 10 previous or next problems (AJAX)
+router.get("/problems/:variant([a-zA-Z0-9]+)", (req,res) => {
+ if (!req.xhr)
+ return res.json({errmsg: "Unauthorized access"});
+ // TODO: next or previous: in params + timedate (of current oldest or newest)
});
+// Upload a problem (AJAX)
+router.post("/problems/:variant([a-zA-Z0-9]+)", (req,res) => {
+ if (!req.xhr)
+ return res.json({errmsg: "Unauthorized access"});
+ const vname = req.params["variant"];
+
+ // TODO: get parameters and sanitize them
+ sanitizeHtml(req.body["fen"]); // [/a-z0-9 ]*
+ sanitizeHtml(req.body["instructions"]);
+ db.serialize(function() {
+ let stmt = db.prepare("INSERT INTO Problems VALUES (?,?,?,?,?)");
+ stmt.run(timestamp, vname, fen, instructions, solution);
+ stmt.finalize();
+ });
+ res.json({});
+});
+
+
module.exports = router;
const url = require('url');
-const Variants = require("./variants");
+const sqlite3 = require('sqlite3');
+const db = new sqlite3.Database('db/vchess.sqlite');
module.exports = function(wss) {
-
- let clients = { "index": {} };
- let games = {}; //pending games (player sid)
- for (const v of Variants)
- clients[v.name] = {};
-
-// // Safety counter (TODO: is it necessary ?)
-// setInterval(() => {
-// Object.keys(clients).forEach(k => {
-// Object.keys(clients[k]).forEach(ck => {
-// if (!clients[k][ck] || clients[k][ck].readyState != 1)
-// delete clients[k][ck];
-// });
-// });
-// }, 60000); //every minute (will be lowered if a lot of users...)
-
- // No-op function as a callback when sending messages
- const noop = () => { };
-
- wss.on("connection", (socket, req) => {
- const params = new URL("http://localhost" + req.url).searchParams;
- const sid = params.get("sid");
- const page = params.get("page");
- // Ignore duplicate connections:
- if (!!clients[page][sid])
- {
- socket.send(JSON.stringify({code:"duplicate"}));
- return;
- }
- clients[page][sid] = socket;
- if (page == "index")
- {
- // Send counting info
- const countings = {};
- for (const v of Variants)
- countings[v.name] = Object.keys(clients[v.name]).length;
- socket.send(JSON.stringify({code:"counts",counts:countings}));
- }
- else
- {
- // Send to every client connected on index an update message for counts
- Object.keys(clients["index"]).forEach( k => {
- clients["index"][k].send(JSON.stringify({code:"increase",vname:page}), noop);
- });
- // Also notify potential opponents: hit all clients which check if sid corresponds
- Object.keys(clients[page]).forEach( k => {
- clients[page][k].send(JSON.stringify({code:"connect",id:sid}), noop);
- });
- socket.on("message", objtxt => {
- let obj = JSON.parse(objtxt);
- switch (obj.code)
+ db.serialize(function() {
+ db.all("SELECT * FROM Variants", (err,variants) => {
+ let clients = { "index": {} };
+ let games = {}; //pending games (player sid)
+ for (const v of variants)
+ clients[v.name] = {};
+ // No-op function as a callback when sending messages
+ const noop = () => { };
+ wss.on("connection", (socket, req) => {
+ const params = new URL("http://localhost" + req.url).searchParams;
+ const sid = params.get("sid");
+ const page = params.get("page");
+ // Ignore duplicate connections:
+ if (!!clients[page][sid])
{
- case "newmove":
- if (!!clients[page][obj.oppid])
- {
- clients[page][obj.oppid].send(
- JSON.stringify({code:"newmove",move:obj.move}), noop);
- }
- break;
- case "ping":
- if (!!clients[page][obj.oppid])
- socket.send(JSON.stringify({code:"pong"}));
- break;
- case "lastate":
- if (!!clients[page][obj.oppid])
- {
- const oppId = obj.oppid;
- obj.oppid = sid; //I'm oppid for my opponent
- clients[page][oppId].send(JSON.stringify(obj), noop);
- }
- break;
- case "newgame":
- if (!!games[page])
+ socket.send(JSON.stringify({code:"duplicate"}));
+ return;
+ }
+ clients[page][sid] = socket;
+ if (page == "index")
+ {
+ // Send counting info
+ const countings = {};
+ for (const v of variants)
+ countings[v.name] = Object.keys(clients[v.name]).length;
+ socket.send(JSON.stringify({code:"counts",counts:countings}));
+ }
+ else
+ {
+ // Send to every client connected on index an update message for counts
+ Object.keys(clients["index"]).forEach( k => {
+ clients["index"][k].send(
+ JSON.stringify({code:"increase",vname:page}), noop);
+ });
+ // Also notify potential opponents:
+ // hit all clients which check if sid corresponds
+ Object.keys(clients[page]).forEach( k => {
+ clients[page][k].send(JSON.stringify({code:"connect",id:sid}), noop);
+ });
+ socket.on("message", objtxt => {
+ let obj = JSON.parse(objtxt);
+ switch (obj.code)
{
- // Start a new game
- const oppId = games[page]["id"];
- const fen = games[page]["fen"];
- delete games[page];
- const mycolor = Math.random() < 0.5 ? 'w' : 'b';
- socket.send(
- JSON.stringify({code:"newgame",fen:fen,oppid:oppId,color:mycolor}));
- if (!!clients[page][oppId])
- {
- clients[page][oppId].send(
- JSON.stringify(
- {code:"newgame",fen:fen,oppid:sid,color:mycolor=="w"?"b":"w"}),
- noop);
- }
+ case "newmove":
+ if (!!clients[page][obj.oppid])
+ {
+ clients[page][obj.oppid].send(
+ JSON.stringify({code:"newmove",move:obj.move}), noop);
+ }
+ break;
+ case "ping":
+ if (!!clients[page][obj.oppid])
+ socket.send(JSON.stringify({code:"pong"}));
+ break;
+ case "lastate":
+ if (!!clients[page][obj.oppid])
+ {
+ const oppId = obj.oppid;
+ obj.oppid = sid; //I'm oppid for my opponent
+ clients[page][oppId].send(JSON.stringify(obj), noop);
+ }
+ break;
+ case "newgame":
+ if (!!games[page])
+ {
+ // Start a new game
+ const oppId = games[page]["id"];
+ const fen = games[page]["fen"];
+ delete games[page];
+ const mycolor = Math.random() < 0.5 ? 'w' : 'b';
+ socket.send(JSON.stringify(
+ {code:"newgame",fen:fen,oppid:oppId,color:mycolor}));
+ if (!!clients[page][oppId])
+ {
+ clients[page][oppId].send(
+ JSON.stringify(
+ {code:"newgame",fen:fen,oppid:sid,color:mycolor=="w"?"b":"w"}),
+ noop);
+ }
+ }
+ else
+ games[page] = {id:sid, fen:obj.fen}; //wait for opponent
+ break;
+ case "cancelnewgame": //if a user cancel his seek
+ delete games[page];
+ break;
+ case "resign":
+ if (!!clients[page][obj.oppid])
+ clients[page][obj.oppid].send(JSON.stringify({code:"resign"}), noop);
+ break;
}
- else
- games[page] = {id:sid, fen:obj.fen}; //wait for opponent
- break;
- case "cancelnewgame": //if a user cancel his seek
- delete games[page];
- break;
- case "resign":
- if (!!clients[page][obj.oppid])
- clients[page][obj.oppid].send(JSON.stringify({code:"resign"}), noop);
- break;
+ });
}
- });
- }
- socket.on("close", () => {
- delete clients[page][sid];
- // Remove potential pending game
- if (!!games[page] && games[page]["id"] == sid)
- delete games[page];
- if (page != "index")
- {
- // Send to every client connected on index an update message for counts
- Object.keys(clients["index"]).forEach( k => {
- clients["index"][k].send(JSON.stringify({code:"decrease",vname:page}), noop);
+ socket.on("close", () => {
+ delete clients[page][sid];
+ // Remove potential pending game
+ if (!!games[page] && games[page]["id"] == sid)
+ delete games[page];
+ if (page != "index")
+ {
+ // Send to every client connected on index an update message for counts
+ Object.keys(clients["index"]).forEach( k => {
+ clients["index"][k].send(
+ JSON.stringify({code:"decrease",vname:page}), noop);
+ });
+ }
+ // Also notify potential opponents:
+ // hit all clients which check if sid corresponds
+ Object.keys(clients[page]).forEach( k => {
+ clients[page][k].send(JSON.stringify({code:"disconnect",id:sid}), noop);
+ });
});
- }
- // Also notify potential opponents: hit all clients which check if sid corresponds
- Object.keys(clients[page]).forEach( k => {
- clients[page][k].send(JSON.stringify({code:"disconnect",id:sid}), noop);
});
});
});
+++ /dev/null
-module.exports = [
- { "name": "Checkered", "description": "Shared pieces" },
- { "name": "Zen", "description": "Reverse captures" },
- { "name": "Atomic", "description": "Explosive captures" },
- { "name": "Chess960", "description": "Standard rules" },
- { "name": "Antiking", "description": "Keep antiking in check" },
- { "name": "Magnetic", "description": "Laws of attraction" },
- { "name": "Alice", "description": "Both sides of the mirror" },
- { "name": "Grand", "description": "Big board" },
- { "name": "Wildebeest", "description": "Balanced sliders & leapers" },
- { "name": "Loser", "description": "Lose all pieces" },
- { "name": "Crazyhouse", "description": "Captures reborn" },
- { "name": "Switching", "description": "Exchange pieces positions" },
- { "name": "Extinction", "description": "Capture all of a kind" },
- { "name": "Ultima", "description": "Non-standard captures" },
-];
block javascripts
script.
const variantArray = !{JSON.stringify(variantArray)};
- //JSON.parse("!{variantArray}".replace(/\"/g,'"'));
script(src="/javascripts/utils/misc.js")
script(src="/javascripts/utils/socket_url.js")
script(src="/javascripts/components/variantSummary.js")
figure.diagram-container
.diagram
- | fen:k7/2p5/5q2/2b5/4N3/2R3r1/3P4/7K w f6,d6,c5,f2,g3,g5:
+ | fen:k7/2p5/5q2/2b5/4N3/2R3r1/3P4/7K f6,d6,c5,f2,g3,g5:
figcaption Possible knight moves from e4.
h4 Bishops
p
| Orthodox rules apply, with only one change:
- | every time you capture a piece, your "reserve" of waiting pieces is augmented
- | with this figure. At every move, you may choose to land one of your reserve
- | pieces anywhere on the board (except last rank for pawns),
+ | every time a piece is captured, the capturer "reserve" of waiting pieces is
+ | augmented with this figure. At every move, you may choose to land one of your
+ | reserve pieces anywhere on the board (except last rank for pawns),
| instead of playing a regular move.
+p.
+ Move notation: an arobase '@' indicate piece landing. For example B@d4 means
+ a bishop rebirth on d4 square, and @f3 is a pawn landing on f3.
+
+figure.diagram-container
+ .diagram
+ | fen:qnbrkbnr/ppNppp1p/2p2p2/8/8/5N2/P1PPPPPP/BRNQKBNR:
+ figcaption After 1.b3 Nf6 2.Bxf6 gxf6 3.Nf3 c6?? 4.N@c7#
+
p.
Note: when a promoted pawn is captured, capturing it put a pawn in the reserve,
not the promoted piece. This is to allow to gain material on last rank without
| Switching must involves two different units.
| Switching while the king is under check is not allowed.
+p.
+ Notation: a switch move is marked by the capital letter 'S' followed by
+ the exchanged squares. Example in diagram: Sb8c8
+
figure.diagram-container
.diagram
| fen:1RB3k1/5ppp/8/8/8/8/8/K7:
| All other pieces capture passively: they land on a free square and captured
| units are determined by some characteristics of the movement.
-p Note: the immobilizer does not capture.
+p Note 1: the immobilizer does not capture.
+
+p.
+ Note 2: for passive captures, a 'X' is added at the end of the move notation,
+ to indicate that something was taken (replaying the game is necessary to know where).
h4 Pawns/Pincers
script(src="/javascripts/utils/socket_url.js")
script(src="/javascripts/utils/array.js")
script(src="/javascripts/utils/md5.js")
+ script(src="/javascripts/utils/printDiagram.js")
+ script(src="/javascripts/utils/ajax.js")
script(src="/javascripts/base_rules.js")
script(src="/javascripts/variants/" + variant + ".js")
script.
const VariantRules = #{variant}Rules;
const V = VariantRules; //because this variable is often used
const variant = "#{variant}";
+ const problemArray = !{JSON.stringify(problemArray)};
script(src="/javascripts/components/rules.js")
script(src="/javascripts/components/game.js")
+ script(src="/javascripts/components/problemSummary.js")
script(src="/javascripts/components/problems.js")
script(src="/javascripts/variant.js")