feat(plugins/community/chess): add plugin (#1215) [skip ci]
This commit is contained in:
1
.github/actions/spelling/excludes.txt
vendored
1
.github/actions/spelling/excludes.txt
vendored
@@ -52,3 +52,4 @@ ignore$
|
|||||||
^\Qsource/templates/terminal/fonts.css\E$
|
^\Qsource/templates/terminal/fonts.css\E$
|
||||||
^\Qsource/templates/terminal/partials/screenshot.ejs\E$
|
^\Qsource/templates/terminal/partials/screenshot.ejs\E$
|
||||||
^\Qtests/mocks/api/github/rest/emojis/get.mjs\E$
|
^\Qtests/mocks/api/github/rest/emojis/get.mjs\E$
|
||||||
|
^\Qtests/mocks/api/axios/get/lichess.mjs\E$
|
||||||
|
|||||||
3
.github/actions/spelling/expect.txt
vendored
3
.github/actions/spelling/expect.txt
vendored
@@ -174,6 +174,7 @@ libxml
|
|||||||
libxmljs
|
libxmljs
|
||||||
libxss
|
libxss
|
||||||
libxtst
|
libxtst
|
||||||
|
lichess
|
||||||
linux
|
linux
|
||||||
lng
|
lng
|
||||||
localhost
|
localhost
|
||||||
@@ -236,6 +237,8 @@ params
|
|||||||
patchnote
|
patchnote
|
||||||
pdated
|
pdated
|
||||||
pened
|
pened
|
||||||
|
PGN
|
||||||
|
Pgn
|
||||||
PGP
|
PGP
|
||||||
playcount
|
playcount
|
||||||
playlists
|
playlists
|
||||||
|
|||||||
4
.github/actions/spelling/patterns.txt
vendored
4
.github/actions/spelling/patterns.txt
vendored
@@ -90,3 +90,7 @@ place_id: ".*"
|
|||||||
|
|
||||||
# ignore long runs of a single character:
|
# ignore long runs of a single character:
|
||||||
\b([A-Za-z])\g{-1}{3,}\b
|
\b([A-Za-z])\g{-1}{3,}\b
|
||||||
|
|
||||||
|
# Chess patterns
|
||||||
|
\brnbqkbnr\b
|
||||||
|
\bRNBQKBNR\b
|
||||||
|
|||||||
BIN
.github/readme/imgs/plugin_chess_lichess_token_0.png
vendored
Normal file
BIN
.github/readme/imgs/plugin_chess_lichess_token_0.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
BIN
.github/readme/imgs/plugin_chess_lichess_token_1.png
vendored
Normal file
BIN
.github/readme/imgs/plugin_chess_lichess_token_1.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
BIN
.github/readme/imgs/plugin_chess_lichess_token_2.png
vendored
Normal file
BIN
.github/readme/imgs/plugin_chess_lichess_token_2.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 59 KiB |
2
.github/scripts/files/examples.yml
vendored
2
.github/scripts/files/examples.yml
vendored
@@ -12,6 +12,8 @@ on:
|
|||||||
required: true
|
required: true
|
||||||
METRICS_TOKEN_PERSONAL:
|
METRICS_TOKEN_PERSONAL:
|
||||||
required: true
|
required: true
|
||||||
|
CHESS_TOKEN:
|
||||||
|
required: true
|
||||||
PAGESPEED_TOKEN:
|
PAGESPEED_TOKEN:
|
||||||
required: true
|
required: true
|
||||||
GOOGLE_MAP_TOKEN:
|
GOOGLE_MAP_TOKEN:
|
||||||
|
|||||||
14
package-lock.json
generated
14
package-lock.json
generated
@@ -19,6 +19,7 @@
|
|||||||
"@primer/css": "^20.4.3",
|
"@primer/css": "^20.4.3",
|
||||||
"@primer/octicons": "^17.5.0",
|
"@primer/octicons": "^17.5.0",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
|
"chess.js": "*",
|
||||||
"clipboard": "^2.0.11",
|
"clipboard": "^2.0.11",
|
||||||
"color": "^4.2.3",
|
"color": "^4.2.3",
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.7.4",
|
||||||
@@ -57,6 +58,7 @@
|
|||||||
"libxmljs2": "^0.30.1"
|
"libxmljs2": "^0.30.1"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
|
"chess.js": "^1.0.0-alpha.0",
|
||||||
"gifencoder": "^2.0.1",
|
"gifencoder": "^2.0.1",
|
||||||
"libxmljs2": "^0.30.1",
|
"libxmljs2": "^0.30.1",
|
||||||
"node-chartist": "^1.0.5"
|
"node-chartist": "^1.0.5"
|
||||||
@@ -3125,6 +3127,12 @@
|
|||||||
"entities": "^4.3.0"
|
"entities": "^4.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/chess.js": {
|
||||||
|
"version": "1.0.0-alpha.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chess.js/-/chess.js-1.0.0-alpha.0.tgz",
|
||||||
|
"integrity": "sha512-nwEDlNEOZR/FaKW1DZLYtjgJrtAlxBW/6Fp4Hk8QXqpCCLrXweOU6/vKfJ/jNHT2gPqasxi0/ZPslcWAAdzozg==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/chownr": {
|
"node_modules/chownr": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
||||||
@@ -12435,6 +12443,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"chess.js": {
|
||||||
|
"version": "1.0.0-alpha.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chess.js/-/chess.js-1.0.0-alpha.0.tgz",
|
||||||
|
"integrity": "sha512-nwEDlNEOZR/FaKW1DZLYtjgJrtAlxBW/6Fp4Hk8QXqpCCLrXweOU6/vKfJ/jNHT2gPqasxi0/ZPslcWAAdzozg==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"chownr": {
|
"chownr": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
||||||
|
|||||||
@@ -81,6 +81,7 @@
|
|||||||
"transform": {}
|
"transform": {}
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
|
"chess.js": "^1.0.0-alpha.0",
|
||||||
"gifencoder": "^2.0.1",
|
"gifencoder": "^2.0.1",
|
||||||
"libxmljs2": "^0.30.1",
|
"libxmljs2": "^0.30.1",
|
||||||
"node-chartist": "^1.0.5"
|
"node-chartist": "^1.0.5"
|
||||||
|
|||||||
@@ -1043,6 +1043,30 @@
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
: null),
|
: null),
|
||||||
|
//Chess
|
||||||
|
...(set.plugins.enabled.chess
|
||||||
|
? ({
|
||||||
|
chess: {
|
||||||
|
platform: options["chess.platform"] || "(chess platform)",
|
||||||
|
meta: {
|
||||||
|
Event: "Casual Correspondence game",
|
||||||
|
Date: faker.date.recent().toISOString().substring(0, 10),
|
||||||
|
White: options["chess.user"],
|
||||||
|
Black: faker.internet.userName(),
|
||||||
|
WhiteElo: faker.datatype.number(3000),
|
||||||
|
BlackElo: faker.datatype.number(3000),
|
||||||
|
},
|
||||||
|
animation: { size: 40, delay: 3, duration: 0.6 },
|
||||||
|
result: { white: faker.datatype.number(3), get black() { return this.white + faker.helpers.arrayElement([-1, +1]) } },
|
||||||
|
moves: [
|
||||||
|
{color: "w", piece: "p", from: "f2", to: "f4", san: "f4", flags: "b"},
|
||||||
|
{color: "b", piece: "p", from: "c7", to: "c5", san: "c5", flags: "b"},
|
||||||
|
{color: "w", piece: "p", from: "e2", to: "e4", san: "e4", flags: "b"},
|
||||||
|
{color: "b", piece: "p", from: "d7", to: "d6", san: "d6", flags: "n"},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
})
|
||||||
|
: null),
|
||||||
//Activity
|
//Activity
|
||||||
...(set.plugins.enabled.activity
|
...(set.plugins.enabled.activity
|
||||||
? ({
|
? ({
|
||||||
|
|||||||
12
source/plugins/community/chess/README.md
Normal file
12
source/plugins/community/chess/README.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<!--header-->
|
||||||
|
<!--/header-->
|
||||||
|
|
||||||
|
## ➡️ Available options
|
||||||
|
|
||||||
|
<!--options-->
|
||||||
|
<!--/options-->
|
||||||
|
|
||||||
|
## ℹ️ Examples workflows
|
||||||
|
|
||||||
|
<!--examples-->
|
||||||
|
<!--/examples-->
|
||||||
10
source/plugins/community/chess/examples.yml
Normal file
10
source/plugins/community/chess/examples.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
- name: Last chess game from lichess.org
|
||||||
|
uses: lowlighter/metrics@latest
|
||||||
|
with:
|
||||||
|
filename: metrics.plugin.chess.svg
|
||||||
|
token: NOT_NEEDED
|
||||||
|
base: ""
|
||||||
|
plugin_chess: yes
|
||||||
|
plugin_chess_token: ${{ secrets.CHESS_TOKEN }}
|
||||||
|
plugin_chess_platform: lichess.org
|
||||||
|
|
||||||
48
source/plugins/community/chess/index.mjs
Normal file
48
source/plugins/community/chess/index.mjs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
//Imports
|
||||||
|
import { Chess } from "chess.js"
|
||||||
|
|
||||||
|
//Setup
|
||||||
|
export default async function({login, q, imports, data, account}, {enabled = false, token = "", extras = false} = {}) {
|
||||||
|
//Plugin execution
|
||||||
|
try {
|
||||||
|
//Check if plugin is enabled and requirements are met
|
||||||
|
if ((!q.chess) || (!imports.metadata.plugins.chess.enabled(enabled, {extras})))
|
||||||
|
return null
|
||||||
|
|
||||||
|
//Load inputs
|
||||||
|
const {user, platform, animation} = imports.metadata.plugins.chess.inputs({data, account, q})
|
||||||
|
for (const [key, defaulted] of Object.entries({size:40, delay:1, duration:4})) {
|
||||||
|
if (Number.isNaN(Number(animation[key])))
|
||||||
|
animation[key] = defaulted
|
||||||
|
if (animation[key] < 0)
|
||||||
|
animation[key] = defaulted
|
||||||
|
}
|
||||||
|
|
||||||
|
//Fetch PGN
|
||||||
|
console.debug(`metrics/compute/${login}/plugins > chess > fetching last game from ${platform}`)
|
||||||
|
let PGN
|
||||||
|
switch (platform) {
|
||||||
|
case "lichess.org":
|
||||||
|
PGN = (await imports.axios.get(`https://lichess.org/api/games/user/${user}?max=1`, {headers: {Authorization: `Bearer ${token}`}})).data
|
||||||
|
break
|
||||||
|
case "":
|
||||||
|
throw {error: {message: "Unspecified platform"}}
|
||||||
|
default:
|
||||||
|
throw {error: {message: `Unsupported platform "${platform}"`}}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Parse PGN
|
||||||
|
const board = new Chess()
|
||||||
|
board.loadPgn(PGN)
|
||||||
|
const moves = board.history({verbose: true})
|
||||||
|
const meta = board.header()
|
||||||
|
const result = Object.fromEntries(meta.Result.split("-").map((score, i) => [i ? "black" : "white", Number(score)]))
|
||||||
|
|
||||||
|
//Results
|
||||||
|
return {platform, meta, moves, animation, result}
|
||||||
|
}
|
||||||
|
//Handle errors
|
||||||
|
catch (error) {
|
||||||
|
throw imports.format.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
61
source/plugins/community/chess/metadata.yml
Normal file
61
source/plugins/community/chess/metadata.yml
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
name: ♟️ Chess
|
||||||
|
category: community
|
||||||
|
description: |
|
||||||
|
This plugin displays the last game you played on a supported chess platform.
|
||||||
|
disclaimer: |
|
||||||
|
This plugin is not affiliated, associated, authorized, endorsed by, or in any way officially connected with any of the supported provider.
|
||||||
|
All product and company names are trademarks™ or registered® trademarks of their respective holders.
|
||||||
|
examples:
|
||||||
|
default: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.chess.svg
|
||||||
|
authors:
|
||||||
|
- lowlighter
|
||||||
|
supports:
|
||||||
|
- user
|
||||||
|
- organization
|
||||||
|
- repository
|
||||||
|
scopes: []
|
||||||
|
inputs:
|
||||||
|
|
||||||
|
plugin_chess:
|
||||||
|
description: |
|
||||||
|
Enable chess plugin
|
||||||
|
type: boolean
|
||||||
|
default: no
|
||||||
|
|
||||||
|
plugin_chess_token:
|
||||||
|
description: |
|
||||||
|
Chess platform token
|
||||||
|
type: token
|
||||||
|
default: ""
|
||||||
|
extras:
|
||||||
|
- metrics.api.chess.any
|
||||||
|
|
||||||
|
plugin_chess_user:
|
||||||
|
description: |
|
||||||
|
AniList login
|
||||||
|
type: string
|
||||||
|
default: .user.login
|
||||||
|
preset: no
|
||||||
|
|
||||||
|
plugin_chess_platform:
|
||||||
|
description: |
|
||||||
|
Chess platform
|
||||||
|
type: string
|
||||||
|
default: ""
|
||||||
|
values:
|
||||||
|
- lichess.org
|
||||||
|
|
||||||
|
plugin_chess_animation:
|
||||||
|
description: |
|
||||||
|
Animation settings
|
||||||
|
|
||||||
|
- `size` is the size of a single chessboard square in pixels (board will be 8 times larger)
|
||||||
|
- `delay` is the delay before starting animation (in seconds)
|
||||||
|
- `duration` is the duration of the animation of a move (in seconds)
|
||||||
|
type: json
|
||||||
|
default: |
|
||||||
|
{
|
||||||
|
"size": 40,
|
||||||
|
"delay": 3,
|
||||||
|
"duration": 0.6
|
||||||
|
}
|
||||||
@@ -37,6 +37,7 @@
|
|||||||
"achievements",
|
"achievements",
|
||||||
"screenshot",
|
"screenshot",
|
||||||
"code",
|
"code",
|
||||||
|
"chess",
|
||||||
"sponsors",
|
"sponsors",
|
||||||
"poopmap",
|
"poopmap",
|
||||||
"fortune"
|
"fortune"
|
||||||
|
|||||||
194
source/templates/classic/partials/chess.ejs
Normal file
194
source/templates/classic/partials/chess.ejs
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
<% if (plugins.chess) { %>
|
||||||
|
<section>
|
||||||
|
<h2 class="field">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M1.5 3.25c0-.966.784-1.75 1.75-1.75h2.5c.966 0 1.75.784 1.75 1.75v2.5A1.75 1.75 0 015.75 7.5h-2.5A1.75 1.75 0 011.5 5.75v-2.5zM3.25 3a.25.25 0 00-.25.25v2.5c0 .138.112.25.25.25h2.5A.25.25 0 006 5.75v-2.5A.25.25 0 005.75 3h-2.5zM1.5 10.25c0-.966.784-1.75 1.75-1.75h2.5c.966 0 1.75.784 1.75 1.75v2.5a1.75 1.75 0 01-1.75 1.75h-2.5a1.75 1.75 0 01-1.75-1.75v-2.5zM3.25 10a.25.25 0 00-.25.25v2.5c0 .138.112.25.25.25h2.5a.25.25 0 00.25-.25v-2.5a.25.25 0 00-.25-.25h-2.5zM8.5 3.25c0-.966.784-1.75 1.75-1.75h2.5c.966 0 1.75.784 1.75 1.75v2.5a1.75 1.75 0 01-1.75 1.75h-2.5A1.75 1.75 0 018.5 5.75v-2.5zM10.25 3a.25.25 0 00-.25.25v2.5c0 .138.112.25.25.25h2.5a.25.25 0 00.25-.25v-2.5a.25.25 0 00-.25-.25h-2.5zM8.5 10.25c0-.966.784-1.75 1.75-1.75h2.5c.966 0 1.75.784 1.75 1.75v2.5a1.75 1.75 0 01-1.75 1.75h-2.5a1.75 1.75 0 01-1.75-1.75v-2.5zm1.75-.25a.25.25 0 00-.25.25v2.5c0 .138.112.25.25.25h2.5a.25.25 0 00.25-.25v-2.5a.25.25 0 00-.25-.25h-2.5z"></path></svg>
|
||||||
|
Last chess game
|
||||||
|
</h2>
|
||||||
|
<% if (plugins.chess.error) { %>
|
||||||
|
<div class="row">
|
||||||
|
<section>
|
||||||
|
<div class="field error">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M2.343 13.657A8 8 0 1113.657 2.343 8 8 0 012.343 13.657zM6.03 4.97a.75.75 0 00-1.06 1.06L6.94 8 4.97 9.97a.75.75 0 101.06 1.06L8 9.06l1.97 1.97a.75.75 0 101.06-1.06L9.06 8l1.97-1.97a.75.75 0 10-1.06-1.06L8 6.94 6.03 4.97z"></path></svg>
|
||||||
|
<%= plugins.chess.error.message %>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<% } else { %>
|
||||||
|
<div class="row largeable-align-start">
|
||||||
|
<section class="largeable-column-fields">
|
||||||
|
<div class="field">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M2.002 2.725a.75.75 0 01.797-.699C8.79 2.42 13.58 7.21 13.974 13.201a.75.75 0 11-1.497.098 10.502 10.502 0 00-9.776-9.776.75.75 0 01-.7-.798zM2 13a1 1 0 112 0 1 1 0 01-2 0zm.84-5.95a.75.75 0 00-.179 1.489c2.509.3 4.5 2.291 4.8 4.8a.75.75 0 101.49-.178A7.003 7.003 0 002.838 7.05z"></path></svg>
|
||||||
|
From <%= plugins.chess.platform %>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M10.5 5a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0zm.061 3.073a4 4 0 10-5.123 0 6.004 6.004 0 00-3.431 5.142.75.75 0 001.498.07 4.5 4.5 0 018.99 0 .75.75 0 101.498-.07 6.005 6.005 0 00-3.432-5.142z"></path></svg>
|
||||||
|
<%= plugins.chess.meta["White"] %> <% if (plugins.chess.meta["WhiteElo"]) { %>(<%= plugins.chess.meta["WhiteElo"] %> ELO)<% } %>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<% if (plugins.chess.result.white > plugins.chess.result.black) { %>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M3.217 6.962A3.75 3.75 0 010 3.25v-.5C0 1.784.784 1 1.75 1h1.356c.228-.585.796-1 1.462-1h6.864a1.57 1.57 0 011.462 1h1.356c.966 0 1.75.784 1.75 1.75v.5a3.75 3.75 0 01-3.217 3.712 5.014 5.014 0 01-2.771 3.117l.144 1.446c.005.05.03.12.114.204.086.087.217.17.373.227.283.103.618.274.89.568.285.31.467.723.467 1.226v.75h1.25a.75.75 0 110 1.5H2.75a.75.75 0 010-1.5H4v-.75c0-.503.182-.916.468-1.226.27-.294.606-.465.889-.568a1.03 1.03 0 00.373-.227c.084-.085.109-.153.114-.204l.144-1.446a5.014 5.014 0 01-2.77-3.117zM3 2.5H1.75a.25.25 0 00-.25.25v.5c0 .98.626 1.813 1.5 2.122V2.5zm4.457 7.97l-.12 1.204c-.093.925-.858 1.47-1.467 1.691a.764.764 0 00-.3.176c-.037.04-.07.093-.07.21v.75h5v-.75c0-.117-.033-.17-.07-.21a.763.763 0 00-.3-.176c-.609-.221-1.374-.766-1.466-1.69l-.12-1.204a5.052 5.052 0 01-1.087 0zM13 5.373V2.5h1.25a.25.25 0 01.25.25v.5A2.25 2.25 0 0113 5.372zM4.5 1.568c0-.037.03-.068.068-.068h6.864c.037 0 .068.03.068.068V5.5a3.5 3.5 0 11-7 0V1.568z"></path></svg>
|
||||||
|
<% } else { %>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M8 5.5a2.5 2.5 0 100 5 2.5 2.5 0 000-5zM4 8a4 4 0 118 0 4 4 0 01-8 0z"></path></svg>
|
||||||
|
<% } %>
|
||||||
|
<%= plugins.chess.result.white %> victor<%= s(plugins.chess.result.white, "y") %>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="largeable-column-fields">
|
||||||
|
<div class="field">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M4.75 0a.75.75 0 01.75.75V2h5V.75a.75.75 0 011.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0113.25 16H2.75A1.75 1.75 0 011 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 014.75 0zm0 3.5h8.5a.25.25 0 01.25.25V6h-11V3.75a.25.25 0 01.25-.25h2zm-2.25 4v6.75c0 .138.112.25.25.25h10.5a.25.25 0 00.25-.25V7.5h-11z"></path></svg>
|
||||||
|
<%= plugins.chess.meta["Date"] %>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="M4.243 4.757a3.757 3.757 0 115.851 3.119 6.006 6.006 0 013.9 5.339.75.75 0 01-.715.784H2.721a.75.75 0 01-.714-.784 6.006 6.006 0 013.9-5.34 3.753 3.753 0 01-1.664-3.118z"></path></svg>
|
||||||
|
<%= plugins.chess.meta["Black"] %> <% if (plugins.chess.meta["BlackElo"]) { %>(<%= plugins.chess.meta["BlackElo"] %> ELO)<% } %>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<% if (plugins.chess.result.black > plugins.chess.result.white) { %>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M3.217 6.962A3.75 3.75 0 010 3.25v-.5C0 1.784.784 1 1.75 1h1.356c.228-.585.796-1 1.462-1h6.864a1.57 1.57 0 011.462 1h1.356c.966 0 1.75.784 1.75 1.75v.5a3.75 3.75 0 01-3.217 3.712 5.014 5.014 0 01-2.771 3.117l.144 1.446c.005.05.03.12.114.204.086.087.217.17.373.227.283.103.618.274.89.568.285.31.467.723.467 1.226v.75h1.25a.75.75 0 110 1.5H2.75a.75.75 0 010-1.5H4v-.75c0-.503.182-.916.468-1.226.27-.294.606-.465.889-.568a1.03 1.03 0 00.373-.227c.084-.085.109-.153.114-.204l.144-1.446a5.014 5.014 0 01-2.77-3.117zM3 2.5H1.75a.25.25 0 00-.25.25v.5c0 .98.626 1.813 1.5 2.122V2.5zm4.457 7.97l-.12 1.204c-.093.925-.858 1.47-1.467 1.691a.764.764 0 00-.3.176c-.037.04-.07.093-.07.21v.75h5v-.75c0-.117-.033-.17-.07-.21a.763.763 0 00-.3-.176c-.609-.221-1.374-.766-1.466-1.69l-.12-1.204a5.052 5.052 0 01-1.087 0zM13 5.373V2.5h1.25a.25.25 0 01.25.25v.5A2.25 2.25 0 0113 5.372zM4.5 1.568c0-.037.03-.068.068-.068h6.864c.037 0 .068.03.068.068V5.5a3.5 3.5 0 11-7 0V1.568z"></path></svg>
|
||||||
|
<% } else { %>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8z"></path></svg>
|
||||||
|
<% } %>
|
||||||
|
<%= plugins.chess.result.black %> victor<%= s(plugins.chess.result.black, "y") %>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chess-board">
|
||||||
|
<% {
|
||||||
|
//Utilities functions
|
||||||
|
const pieces = {
|
||||||
|
w: {p: "♙", r: "♖", n: "♘", b: "♗", q: "♕", k: "♔"},
|
||||||
|
b: {p: "♟︎", r: "♜", n: "♞", b: "♝", q: "♛", k: "♚"},
|
||||||
|
}
|
||||||
|
const init = ["rnbqkbnr", "pppppppp", "", "", "", "", "PPPPPPPP", "RNBQKBNR"]
|
||||||
|
const column = p => ["a", "b", "c", "d", "e", "f", "g", "h"].indexOf(p[0])
|
||||||
|
const row = p => ["8", "7", "6", "5", "4", "3", "2", "1"].indexOf(p[1])
|
||||||
|
const animation = plugins.chess.animation
|
||||||
|
const size = animation.size
|
||||||
|
|
||||||
|
//Empty board
|
||||||
|
for (let i = 0; i < 8; i++) { %>
|
||||||
|
<div class="chess-row">
|
||||||
|
<% for (let j = 0; j < 8; j++) { %>
|
||||||
|
<div class="chess-square <%= (i + j) % 2 ? 'black' : 'white' %>"></div>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
<% }
|
||||||
|
|
||||||
|
//Initial board state
|
||||||
|
for (let i = 0; i < init.length; i++) { for (let j = 0; j < init[i].length; j++) {
|
||||||
|
const color = /[A-Z]/.test(init[i][j]) ? "w" : "b", piece = init[i][j].toLocaleLowerCase() %>
|
||||||
|
<div class="chess-move">
|
||||||
|
<div class="init" style="left: <%= j*size %>px; top: <%= i*size %>px;"><%- pieces[color][piece] %></div>
|
||||||
|
</div>
|
||||||
|
<% }}
|
||||||
|
|
||||||
|
//Draw moves
|
||||||
|
const moves = plugins.chess.moves
|
||||||
|
for (let i = 0; i < moves.length; i++) { const {color, piece, from, to} = moves[i] %>
|
||||||
|
<div class="chess-move chess-move-<%= i %>">
|
||||||
|
<div class="from" style="left: <%= column(from)*size %>px; top: <%= row(from)*size %>px;"><%- pieces[color][piece] %></div>
|
||||||
|
<div class="to" style="left: <%= column(from)*size %>px; top: <%= row(from)*size %>px;"><%- pieces[color][piece] %></div>
|
||||||
|
<style>
|
||||||
|
@keyframes chess-move-<%= i %>-from {
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
color: transparent;
|
||||||
|
background-color: <%= (row(from)+column(from))%2 ? "#C5A076" : "#ECDAB9" %>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.chess-move-<%= i %> .from {
|
||||||
|
animation-name: chess-move-<%= i %>-from;
|
||||||
|
animation-delay: <%= i * animation.duration + animation.delay %>s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes chess-move-<%= i %>-to {
|
||||||
|
1% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
99% {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
background-color: <%= (row(to)+column(to))%2 ? "#C5A076" : "#ECDAB9" %>;
|
||||||
|
left: <%= column(to)*size %>px;
|
||||||
|
top: <%= row(to)*size %>px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.chess-move-<%= i %> .to {
|
||||||
|
animation-name: chess-move-<%= i %>-to;
|
||||||
|
animation-delay: <%= i * animation.duration + animation.delay %>s;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
<style>
|
||||||
|
.chess-board {
|
||||||
|
width: <%= 8*size %>px;
|
||||||
|
height: <%= 8*size %>px;
|
||||||
|
position: relative;
|
||||||
|
margin: 6px auto 0;
|
||||||
|
}
|
||||||
|
.chess-square, .chess-move .from, .chess-move .to, .chess-move .init {
|
||||||
|
width: <%= size %>px;
|
||||||
|
height: <%= size %>px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.chess-square.white {
|
||||||
|
background-color: #ECDAB9;
|
||||||
|
}
|
||||||
|
.chess-square.black {
|
||||||
|
background-color: #C5A076;
|
||||||
|
}
|
||||||
|
.chess-clock {
|
||||||
|
width: <%= 8*size %>px;
|
||||||
|
height: 4px;
|
||||||
|
margin: auto;
|
||||||
|
background-color: #58A6FF40;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
.chess-clock .chess-time {
|
||||||
|
width: 0%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #58A6FF;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
animation-name: chess-clock;
|
||||||
|
animation-delay: <%= animation.delay %>s;
|
||||||
|
animation-duration: <%= moves.length*animation.duration %>s;
|
||||||
|
animation-timing-function: linear;
|
||||||
|
}
|
||||||
|
@keyframes chess-clock {
|
||||||
|
100% {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.chess-move {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
.chess-move .from, .chess-move .to, .chess-move .init {
|
||||||
|
position: absolute;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: <%= 0.8*size %>px;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.chess-move .init {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
.chess-move .to {
|
||||||
|
animation-duration: <%= animation.duration %>s;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
<div class="chess-clock">
|
||||||
|
<div class="chess-time"></div>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
</section>
|
||||||
|
<% } %>
|
||||||
30
tests/mocks/api/axios/get/lichess.mjs
Normal file
30
tests/mocks/api/axios/get/lichess.mjs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/**Mocked data */
|
||||||
|
export default function({faker, url, options, login = faker.internet.userName()}) {
|
||||||
|
//Wakatime api
|
||||||
|
if (/^https:..lichess.org.api.games.user.*$/.test(url)) {
|
||||||
|
console.debug(`metrics/compute/mocks > mocking lichess api result > ${url}`)
|
||||||
|
return ({
|
||||||
|
status: 200,
|
||||||
|
data: `
|
||||||
|
[Event "It (cat.17)"]
|
||||||
|
[Site "Wijk aan Zee (Netherlands)"]
|
||||||
|
[Date "1999.??.??"]
|
||||||
|
[Round "?"]
|
||||||
|
[White "Garry Kasparov"]
|
||||||
|
[Black "Veselin Topalov"]
|
||||||
|
[Result "1-0"]
|
||||||
|
|
||||||
|
1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. Be3 Bg7 5. Qd2 c6 6. f3 b5 7. Nge2 Nbd7 8. Bh6
|
||||||
|
Bxh6 9. Qxh6 Bb7 10. a3 e5 11. O-O-O Qe7 12. Kb1 a6 13. Nc1 O-O-O 14. Nb3 exd4
|
||||||
|
15. Rxd4 c5 16. Rd1 Nb6 17. g3 Kb8 18. Na5 Ba8 19. Bh3 d5 20. Qf4+ Ka7 21. Rhe1
|
||||||
|
d4 22. Nd5 Nbxd5 23. exd5 Qd6 24. Rxd4 cxd4 25. Re7+ Kb6 26. Qxd4+ Kxa5 27. b4+
|
||||||
|
Ka4 28. Qc3 Qxd5 29. Ra7 Bb7 30. Rxb7 Qc4 31. Qxf6 Kxa3 32. Qxa6+ Kxb4 33. c3+
|
||||||
|
Kxc3 34. Qa1+ Kd2 35. Qb2+ Kd1 36. Bf1 Rd2 37. Rd7 Rxd7 38. Bxc4 bxc4 39. Qxh8
|
||||||
|
Rd3 40. Qa8 c3 41. Qa4+ Ke1 42. f4 f5 43. Kc1 Rd2 44. Qa7 1-0`.trim()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -11,5 +11,6 @@
|
|||||||
"TWITTER_TOKEN":"MOCKED_TOKEN",
|
"TWITTER_TOKEN":"MOCKED_TOKEN",
|
||||||
"GOOGLE_MAP_TOKEN": "MOCKED_TOKEN",
|
"GOOGLE_MAP_TOKEN": "MOCKED_TOKEN",
|
||||||
"STOCK_TOKEN":"MOCKED_TOKEN",
|
"STOCK_TOKEN":"MOCKED_TOKEN",
|
||||||
|
"CHESS_TOKEN":"MOCKED_TOKEN",
|
||||||
"POOPMAP_TOKEN":"MOCKED_TOKEN"
|
"POOPMAP_TOKEN":"MOCKED_TOKEN"
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user