chesspal 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli/cli.js +6 -6
- package/dist/commands/{analyse-game.d.ts → analysis/analyse.d.ts} +2 -2
- package/dist/commands/{analyse-game.js → analysis/analyse.js} +7 -11
- package/dist/commands/{annotate-game.d.ts → analysis/annotate.d.ts} +1 -1
- package/dist/commands/{annotate-game.js → analysis/annotate.js} +6 -9
- package/dist/commands/{delete-review.d.ts → analysis/delete-review.d.ts} +1 -1
- package/dist/commands/{delete-review.js → analysis/delete-review.js} +5 -5
- package/dist/commands/analysis/index.d.ts +4 -0
- package/dist/commands/analysis/index.js +5 -0
- package/dist/commands/{study-games.d.ts → analysis/study-games.d.ts} +1 -1
- package/dist/commands/{study-games.js → analysis/study-games.js} +4 -5
- package/dist/commands/{agents.d.ts → answers/agents.d.ts} +4 -4
- package/dist/commands/{agents.js → answers/agents.js} +13 -9
- package/dist/commands/{clock.d.ts → answers/clock.d.ts} +2 -2
- package/dist/commands/{clock.js → answers/clock.js} +2 -2
- package/dist/commands/{drawings.d.ts → answers/drawings.d.ts} +1 -1
- package/dist/commands/{drawings.js → answers/drawings.js} +1 -1
- package/dist/commands/answers/index.d.ts +12 -0
- package/dist/commands/answers/index.js +14 -0
- package/dist/commands/{lead-input.d.ts → answers/lead-input.d.ts} +1 -1
- package/dist/commands/{lead-input.js → answers/lead-input.js} +1 -1
- package/dist/commands/{answer-lines.d.ts → answers/lines.d.ts} +2 -2
- package/dist/commands/{answer-lines.js → answers/lines.js} +4 -4
- package/dist/commands/{opening-book.d.ts → answers/opening-book.d.ts} +1 -1
- package/dist/commands/{opening-book.js → answers/opening-book.js} +3 -3
- package/dist/commands/{play-move.d.ts → answers/play-move.d.ts} +2 -2
- package/dist/commands/{play-move.js → answers/play-move.js} +3 -3
- package/dist/commands/{say.d.ts → answers/say.d.ts} +3 -3
- package/dist/commands/{say.js → answers/say.js} +4 -4
- package/dist/commands/{speech.js → answers/speech.js} +1 -1
- package/dist/commands/{study.d.ts → answers/study.d.ts} +3 -3
- package/dist/commands/{study.js → answers/study.js} +3 -3
- package/dist/commands/{game-summary.d.ts → answers/summary.d.ts} +2 -2
- package/dist/commands/{game-summary.js → answers/summary.js} +4 -4
- package/dist/commands/{view.d.ts → answers/view.d.ts} +1 -1
- package/dist/commands/{ai-move.d.ts → game/ai-move.d.ts} +2 -2
- package/dist/commands/{ai-move.js → game/ai-move.js} +6 -11
- package/dist/commands/{coach.d.ts → game/coach.d.ts} +1 -1
- package/dist/commands/{coach.js → game/coach.js} +7 -13
- package/dist/commands/{draw-offer.d.ts → game/draw-offer.d.ts} +1 -1
- package/dist/commands/{draw-offer.js → game/draw-offer.js} +4 -4
- package/dist/commands/{end-game.d.ts → game/end.d.ts} +2 -2
- package/dist/commands/{end-game.js → game/end.js} +5 -9
- package/dist/commands/{export-game.d.ts → game/export.d.ts} +1 -1
- package/dist/commands/{export-game.js → game/export.js} +4 -4
- package/dist/commands/game/index.d.ts +11 -0
- package/dist/commands/game/index.js +13 -0
- package/dist/commands/{levels.d.ts → game/levels.d.ts} +3 -3
- package/dist/commands/{levels.js → game/levels.js} +3 -3
- package/dist/commands/{look.d.ts → game/look.d.ts} +3 -4
- package/dist/commands/{look.js → game/look.js} +5 -10
- package/dist/commands/{new-game.d.ts → game/new.d.ts} +3 -4
- package/dist/commands/{new-game.js → game/new.js} +17 -13
- package/dist/commands/{page-link.d.ts → game/page-link.d.ts} +1 -1
- package/dist/commands/{player-move.d.ts → game/player-move.d.ts} +2 -2
- package/dist/commands/{player-move.js → game/player-move.js} +4 -8
- package/dist/commands/{ponder.d.ts → game/ponder.d.ts} +3 -3
- package/dist/commands/{ponder.js → game/ponder.js} +6 -9
- package/dist/commands/{position.d.ts → game/position.d.ts} +2 -2
- package/dist/commands/{position.js → game/position.js} +5 -7
- package/dist/commands/{status.d.ts → game/status.d.ts} +2 -4
- package/dist/commands/{status.js → game/status.js} +12 -17
- package/dist/commands/index.d.ts +6 -17
- package/dist/commands/index.js +11 -38
- package/dist/commands/{delete-game.d.ts → profiles/delete-game.d.ts} +1 -1
- package/dist/commands/{delete-game.js → profiles/delete-game.js} +3 -3
- package/dist/commands/profiles/index.d.ts +4 -0
- package/dist/commands/profiles/index.js +5 -0
- package/dist/commands/{past-games.d.ts → profiles/past-games.d.ts} +1 -1
- package/dist/commands/{past-games.js → profiles/past-games.js} +5 -5
- package/dist/commands/{profiles.d.ts → profiles/profiles.d.ts} +7 -7
- package/dist/commands/{profiles.js → profiles/profiles.js} +4 -4
- package/dist/commands/{ratings.d.ts → profiles/ratings.d.ts} +1 -1
- package/dist/commands/{ratings.js → profiles/ratings.js} +2 -2
- package/dist/commands/{context.js → registry/context.js} +2 -2
- package/dist/commands/registry/index.d.ts +2 -0
- package/dist/commands/registry/index.js +3 -0
- package/dist/commands/setup/index.d.ts +2 -0
- package/dist/commands/setup/index.js +3 -0
- package/dist/commands/{init.d.ts → setup/init.d.ts} +1 -1
- package/dist/commands/{init.js → setup/init.js} +2 -3
- package/dist/commands/{instructions.d.ts → setup/instructions.d.ts} +2 -2
- package/dist/commands/{instructions.js → setup/instructions.js} +3 -3
- package/dist/commands/{ai-say.d.ts → talk/ai-say.d.ts} +2 -3
- package/dist/commands/{ai-say.js → talk/ai-say.js} +5 -9
- package/dist/commands/talk/index.d.ts +2 -0
- package/dist/commands/talk/index.js +3 -0
- package/dist/commands/{player-say.d.ts → talk/player-say.d.ts} +1 -1
- package/dist/commands/{player-say.js → talk/player-say.js} +4 -4
- package/dist/page/app/app.js +53 -21
- package/dist/page/app/served.js +15 -3
- package/dist/page/avatars/torretta.js +10 -3
- package/dist/page/dialogs/dialogs.css +10 -0
- package/dist/page/dialogs/profiles.js +1 -5
- package/dist/page/dialogs/settings.js +18 -4
- package/dist/page/game/column.js +1 -1
- package/dist/page/game/game.css +26 -3
- package/dist/page/guide/blocks.js +13 -2
- package/dist/page/guide/credits.js +6 -0
- package/dist/page/guide/drawings/analysis.js +13 -0
- package/dist/page/guide/drawings/drawings.css +329 -0
- package/dist/page/guide/drawings/drawings.js +15 -0
- package/dist/page/guide/drawings/game.js +15 -0
- package/dist/page/guide/drawings/helps.js +13 -0
- package/dist/page/guide/drawings/how-it-works.js +13 -0
- package/dist/page/guide/drawings/parts.js +103 -0
- package/dist/page/guide/drawings/players.js +19 -0
- package/dist/page/guide/drawings/talk.js +9 -0
- package/dist/page/guide/en.md +39 -25
- package/dist/page/guide/guide.css +123 -91
- package/dist/page/guide/guide.js +47 -25
- package/dist/page/guide/it.md +39 -25
- package/dist/page/guide/markdown.js +5 -0
- package/dist/page/helps/helps.css +201 -88
- package/dist/page/helps/helps.js +50 -31
- package/dist/page/helps/view.js +13 -3
- package/dist/page/{guide/foot.js → layout/footer.js} +7 -8
- package/dist/page/layout/header.js +5 -3
- package/dist/page/layout/layout.css +114 -10
- package/dist/page/layout/window.js +6 -26
- package/dist/page/main.js +1 -1
- package/dist/page/pieces/pieces.js +5 -2
- package/dist/page/style.css +1 -0
- package/dist/page/table/table.css +69 -0
- package/dist/page/table/update.js +82 -0
- package/dist/page/table/window.js +6 -5
- package/dist/page/talk/chat.css +6 -6
- package/dist/page/talk/talk.css +17 -67
- package/dist/page/talk/talk.js +6 -6
- package/dist/page/talk/voice.js +12 -0
- package/dist/page/text.js +78 -20
- package/dist/page/theme.css +2 -0
- package/dist/server/{bell.js → bell/bell.js} +17 -4
- package/dist/server/bell/index.d.ts +1 -0
- package/dist/server/bell/index.js +2 -0
- package/dist/server/{caller.d.ts → mcp/caller.d.ts} +1 -1
- package/dist/server/{caller.js → mcp/caller.js} +1 -1
- package/dist/server/mcp/index.d.ts +1 -0
- package/dist/server/mcp/index.js +2 -0
- package/dist/server/{mcp.d.ts → mcp/mcp.d.ts} +1 -1
- package/dist/server/{mcp.js → mcp/mcp.js} +9 -9
- package/dist/server/page/attach.js +8 -3
- package/dist/server/page/game.js +19 -3
- package/dist/server/page/http.d.ts +1 -1
- package/dist/server/page/index.d.ts +3 -0
- package/dist/server/page/index.js +3 -0
- package/dist/server/page/page.d.ts +12 -3
- package/dist/server/page/page.js +26 -5
- package/dist/server/page/table.d.ts +7 -1
- package/dist/server/page/table.js +79 -3
- package/dist/server/page/update.d.ts +18 -0
- package/dist/server/page/update.js +40 -0
- package/dist/server/table/browser.d.ts +1 -1
- package/dist/server/table/browser.js +1 -1
- package/dist/server/table/hosts/chats.d.ts +1 -1
- package/dist/server/table/hosts/chats.js +2 -2
- package/dist/server/table/hosts/index.d.ts +1 -1
- package/dist/server/table/hosts/index.js +1 -1
- package/dist/server/table/hosts/play.d.ts +8 -1
- package/dist/server/table/hosts/play.js +40 -4
- package/dist/server/table/hosts/seat.d.ts +5 -1
- package/dist/server/table/hosts/seat.js +1 -1
- package/dist/server/table/index.d.ts +3 -2
- package/dist/server/table/index.js +3 -2
- package/dist/server/table/launch.d.ts +5 -2
- package/dist/server/table/launch.js +6 -3
- package/dist/server/table/link.d.ts +1 -1
- package/dist/server/table/link.js +3 -3
- package/dist/server/table/table.d.ts +4 -5
- package/dist/server/table/table.js +15 -12
- package/dist/server/table/update.d.ts +17 -0
- package/dist/server/table/update.js +77 -0
- package/dist/sites/index.d.ts +1 -1
- package/dist/sites/index.js +2 -2
- package/dist/version.d.ts +4 -0
- package/dist/version.js +12 -1
- package/package.json +1 -1
- /package/dist/commands/{speech.d.ts → answers/speech.d.ts} +0 -0
- /package/dist/commands/{view.js → answers/view.js} +0 -0
- /package/dist/commands/{page-link.js → game/page-link.js} +0 -0
- /package/dist/commands/{context.d.ts → registry/context.d.ts} +0 -0
- /package/dist/commands/{registry.d.ts → registry/registry.d.ts} +0 -0
- /package/dist/commands/{registry.js → registry/registry.js} +0 -0
- /package/dist/server/{bell.d.ts → bell/bell.d.ts} +0 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "preact/jsx-runtime";
|
|
2
|
+
// A newer Chesspal (D-108): on the table's page the header's mark opens this window, which installs it between games; the table and its chat then start
|
|
3
|
+
// again from it, and the page loads again by itself.
|
|
4
|
+
import { useEffect, useState } from "preact/hooks";
|
|
5
|
+
import { Dialog } from "../dialogs/dialog.js";
|
|
6
|
+
/**
|
|
7
|
+
* The window that installs the newer Chesspal: its button waits while a game goes on and while npm installs; installed, the table waits for the game to
|
|
8
|
+
* end; when npm fails, a cross and the commands to type.
|
|
9
|
+
*/
|
|
10
|
+
export function UpdateDialog({ open, version, current, installing, installed, going, chat, name, onClose, text }) {
|
|
11
|
+
const [sent, setSent] = useState(false);
|
|
12
|
+
const [answer, setAnswer] = useState(undefined);
|
|
13
|
+
useEffect(() => setAnswer(undefined), [open]);
|
|
14
|
+
const words = text.update;
|
|
15
|
+
// Once npm has installed it the table closes to start again: the page waits for it, and loads again.
|
|
16
|
+
const waiting = installing || (sent && answer === undefined) || (answer?.installed === true && !installed);
|
|
17
|
+
const failed = answer?.installed === false;
|
|
18
|
+
const install = async () => {
|
|
19
|
+
setSent(true);
|
|
20
|
+
setAnswer(undefined);
|
|
21
|
+
setAnswer(await askToInstall(text, name));
|
|
22
|
+
setSent(false);
|
|
23
|
+
};
|
|
24
|
+
const stopped = waiting || installed || going;
|
|
25
|
+
return (_jsxs(Dialog, { open: open, title: words.title, onClose: onClose, text: text, children: [_jsxs("p", { class: "note update-offer", children: [words.offer(version, current), chat === "held" ? ` ${words.chatAgain(name)}` : chat === "byHand" ? ` ${words.byHand(name)}` : ""] }), _jsx("button", { class: `command${failed ? "" : " primary"}`, type: "button", "aria-disabled": stopped, onClick: stopped ? undefined : () => void install(), children: words.install }), _jsx("p", { class: "chat-state update-state", role: "status", children: waiting
|
|
26
|
+
? (_jsxs(_Fragment, { children: [_jsx("span", { class: "spinner", "aria-hidden": "true" }), words.installing(version)] }))
|
|
27
|
+
: installed
|
|
28
|
+
? words.installed
|
|
29
|
+
: answer?.refused ?? (going ? words.whilePlaying : null) }), failed
|
|
30
|
+
? (_jsxs("div", { class: "update-failed", role: "alert", children: [_jsxs("p", { children: [_jsx("span", { class: "update-cross", "aria-hidden": "true", children: "\u2715" }), " ", words.failed] }), _jsx("code", { children: "npm install -g chesspal" }), _jsx("code", { children: "chesspal" })] }))
|
|
31
|
+
: null] }));
|
|
32
|
+
}
|
|
33
|
+
/** The header's mark of a newer Chesspal, on the table's page: it opens the window that installs it; while npm installs, or the table waits, it spins. */
|
|
34
|
+
export function UpdateMark({ version, installing, onOpen, text }) {
|
|
35
|
+
const title = installing ? text.update.installing(version) : text.update.mark(version);
|
|
36
|
+
return (_jsx("button", { class: "icon-button update-button", type: "button", title: title, "aria-label": title, "aria-haspopup": "dialog", onClick: onOpen, children: installing ? _jsx("span", { class: "spinner", "aria-hidden": "true" }) : (_jsxs("svg", { class: "icon", viewBox: "0 0 24 24", "aria-hidden": "true", children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("path", { d: "M12 16.5V7.5M8 11.5L12 7.5L16 11.5" })] })) }));
|
|
37
|
+
}
|
|
38
|
+
/** On a chat's own page, the strip with the command that installs the newer Chesspal; its × hides it until a newer one still is out. */
|
|
39
|
+
export function UpdateNotice({ version, name, text }) {
|
|
40
|
+
const [hidden, setHidden] = useState(hiddenVersion);
|
|
41
|
+
if (hidden === version) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
const hide = () => {
|
|
45
|
+
rememberHidden(version);
|
|
46
|
+
setHidden(version);
|
|
47
|
+
};
|
|
48
|
+
return (_jsxs("p", { class: "outdated update-notice", role: "status", children: [_jsxs("span", { children: [text.update.notice(version, name), _jsx("code", { children: "npm install -g chesspal" })] }), _jsx("button", { class: "icon-button", type: "button", title: text.update.hide, "aria-label": text.update.hide, onClick: hide, children: _jsx("svg", { class: "icon", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { d: "M6 6L18 18M18 6L6 18" }) }) })] }));
|
|
49
|
+
}
|
|
50
|
+
const hiddenKey = "chesspal-update-hidden";
|
|
51
|
+
function hiddenVersion() {
|
|
52
|
+
try {
|
|
53
|
+
return localStorage.getItem(hiddenKey) ?? undefined;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// A browser that keeps nothing for the page: the strip shows.
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function rememberHidden(version) {
|
|
61
|
+
try {
|
|
62
|
+
localStorage.setItem(hiddenKey, version);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// Hidden as long as the page.
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async function askToInstall(text, name) {
|
|
69
|
+
try {
|
|
70
|
+
const response = await fetch("/api/table/update", { method: "POST", headers: { "Content-Type": "application/json" }, body: "{}" });
|
|
71
|
+
const body = (await response.json());
|
|
72
|
+
if (response.ok) {
|
|
73
|
+
return { installed: body.installed === true };
|
|
74
|
+
}
|
|
75
|
+
const known = body.refusal === undefined ? undefined : text.refused[body.refusal];
|
|
76
|
+
return { refused: known?.(0, name) ?? body.error ?? response.statusText };
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// The table closed to start again before its answer came.
|
|
80
|
+
return { installed: true };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -2,8 +2,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
|
|
|
2
2
|
import { useEffect, useState } from "preact/hooks";
|
|
3
3
|
import { Dialog } from "../dialogs/dialog.js";
|
|
4
4
|
import { checkIcon } from "../dialogs/profiles.js";
|
|
5
|
-
/** The chat's window: closed once a chat opens or starts again, the page then saying where it stands. */
|
|
6
|
-
export function ChatDialog({ open, table, settings, onChange, name, onClose, text }) {
|
|
5
|
+
/** The chat's window: closed once a chat opens or starts again, the page then saying where it stands; `review` when it opened to have a game analysed. */
|
|
6
|
+
export function ChatDialog({ open, review = false, table, settings, onChange, name, onClose, text }) {
|
|
7
7
|
const [sending, setSending] = useState(false);
|
|
8
8
|
const [failed, setFailed] = useState(false);
|
|
9
9
|
useEffect(() => setFailed(false), [open]);
|
|
@@ -25,20 +25,21 @@ export function ChatDialog({ open, table, settings, onChange, name, onClose, tex
|
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
27
|
// While a chat opens or waits to start again, the rows wait too, and the note says why.
|
|
28
|
+
const chooseNote = review ? words.reviewChoose : words.choose;
|
|
28
29
|
const note = installed.length === 0
|
|
29
30
|
? words.install(name)
|
|
30
31
|
: busy
|
|
31
|
-
? chatState(table, name, text) ??
|
|
32
|
+
? chatState(table, name, text) ?? chooseNote
|
|
32
33
|
: byHand
|
|
33
34
|
? words.byHand(name)
|
|
34
35
|
: table.chat
|
|
35
36
|
? words.restartHint
|
|
36
|
-
:
|
|
37
|
+
: chooseNote;
|
|
37
38
|
const offersChoices = installed.some((host) => host.models.length > 0 || host.efforts.length > 0);
|
|
38
39
|
// The chat at the table started with other choices than the ones kept now: its row starts it again with these, else it only closes the window.
|
|
39
40
|
const started = table.held ? table.started : undefined;
|
|
40
41
|
const changed = (host) => started !== undefined && (chosen(host, "model", settings) !== (started.model ?? "") || chosen(host, "effort", settings) !== (started.effort ?? ""));
|
|
41
|
-
return (_jsxs(Dialog, { open: open, title: words.title, onClose: onClose, text: text, children: [_jsx("p", { class: "note", children: note }), _jsxs("div", { class: "chat-hosts", role: "group", "aria-label": words.title, children: [offersChoices
|
|
42
|
+
return (_jsxs(Dialog, { open: open, title: review ? words.reviewTitle : words.title, onClose: onClose, text: text, children: [_jsx("p", { class: "note", children: note }), _jsxs("div", { class: "chat-hosts", role: "group", "aria-label": review ? words.reviewTitle : words.title, children: [offersChoices
|
|
42
43
|
? (_jsxs("div", { class: "chat-head", "aria-hidden": "true", children: [_jsx("span", {}), _jsx("span", { children: words.model }), _jsx("span", { children: words.effort })] }))
|
|
43
44
|
: null, installed.map((host) => {
|
|
44
45
|
const atTable = table.chat && table.host === host.name;
|
package/dist/page/talk/chat.css
CHANGED
|
@@ -5,15 +5,13 @@
|
|
|
5
5
|
max-height: none;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
/*
|
|
8
|
+
/* Under the AI's note, with no line between them (Stefano) */
|
|
9
9
|
.talk.studied > section > .chat {
|
|
10
10
|
display: flex;
|
|
11
11
|
flex-direction: column;
|
|
12
12
|
flex: 1 1 auto;
|
|
13
13
|
min-height: 0;
|
|
14
14
|
margin-top: 12px;
|
|
15
|
-
padding-top: 10px;
|
|
16
|
-
border-top: 1px solid var(--line);
|
|
17
15
|
}
|
|
18
16
|
|
|
19
17
|
.chat > .compose {
|
|
@@ -49,9 +47,11 @@
|
|
|
49
47
|
|
|
50
48
|
.flipped .talk.studied > section > .chat {
|
|
51
49
|
margin: 0 0 12px;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* Turned round, the note's room goes under its bubbles, which would touch the AI's card or the note that no chat listens (Zoe) */
|
|
53
|
+
.flipped .talk.studied .ai-note {
|
|
54
|
+
margin: 0 0 12px;
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
package/dist/page/talk/talk.css
CHANGED
|
@@ -233,65 +233,6 @@
|
|
|
233
233
|
background: var(--say);
|
|
234
234
|
}
|
|
235
235
|
|
|
236
|
-
.me {
|
|
237
|
-
position: relative;
|
|
238
|
-
flex: none;
|
|
239
|
-
padding: 0;
|
|
240
|
-
border: 0;
|
|
241
|
-
border-radius: 50%;
|
|
242
|
-
background: none;
|
|
243
|
-
line-height: 0;
|
|
244
|
-
cursor: pointer;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
.me-cover {
|
|
248
|
-
position: absolute;
|
|
249
|
-
inset: 0;
|
|
250
|
-
display: grid;
|
|
251
|
-
place-items: center;
|
|
252
|
-
border-radius: 50%;
|
|
253
|
-
background: rgba(0, 0, 0, 0.45);
|
|
254
|
-
color: #fff;
|
|
255
|
-
opacity: 0;
|
|
256
|
-
transition: opacity 0.12s;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
.me-cover .icon {
|
|
260
|
-
width: 45%;
|
|
261
|
-
height: 45%;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
.me:hover .me-cover,
|
|
265
|
-
.me:focus-visible .me-cover {
|
|
266
|
-
opacity: 1;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
/* Where nothing hovers, a camera in the corner says the picture changes */
|
|
270
|
-
.me-badge {
|
|
271
|
-
position: absolute;
|
|
272
|
-
right: -2px;
|
|
273
|
-
bottom: -2px;
|
|
274
|
-
display: none;
|
|
275
|
-
place-items: center;
|
|
276
|
-
width: 18px;
|
|
277
|
-
height: 18px;
|
|
278
|
-
border-radius: 50%;
|
|
279
|
-
background: var(--accent);
|
|
280
|
-
color: var(--on-accent);
|
|
281
|
-
box-shadow: 0 0 0 2px var(--card);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
.me-badge .icon {
|
|
285
|
-
width: 12px;
|
|
286
|
-
height: 12px;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
@media (hover: none) {
|
|
290
|
-
.me-badge {
|
|
291
|
-
display: grid;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
236
|
.profile-name {
|
|
296
237
|
display: inline-flex;
|
|
297
238
|
align-items: center;
|
|
@@ -369,6 +310,15 @@
|
|
|
369
310
|
}
|
|
370
311
|
}
|
|
371
312
|
|
|
313
|
+
/* Its bust on a player's card: a disc of the player's picture's colour, which cuts what falls out of it */
|
|
314
|
+
.torretta.bust {
|
|
315
|
+
clip-path: circle(50%);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.torretta .back {
|
|
319
|
+
fill: var(--say);
|
|
320
|
+
}
|
|
321
|
+
|
|
372
322
|
.torretta .shade {
|
|
373
323
|
fill: var(--torretta-shade);
|
|
374
324
|
}
|
|
@@ -701,23 +651,23 @@
|
|
|
701
651
|
overflow-wrap: anywhere;
|
|
702
652
|
}
|
|
703
653
|
|
|
704
|
-
/* Only the note's
|
|
654
|
+
/* Only the note's first bubble has a tail, pointing up at the Torretta beside the AI's name, the board turned round or not (Stefano) */
|
|
705
655
|
.ai-note > .say::before,
|
|
706
656
|
.ai-note > .say::after {
|
|
707
657
|
content: none;
|
|
708
658
|
}
|
|
709
659
|
|
|
710
|
-
.ai-note > .
|
|
660
|
+
.ai-note > .who + .say::before {
|
|
711
661
|
content: "";
|
|
712
662
|
position: absolute;
|
|
713
663
|
left: 8px;
|
|
714
|
-
|
|
664
|
+
top: -9px;
|
|
715
665
|
border: 10px solid transparent;
|
|
716
|
-
border-
|
|
717
|
-
border-
|
|
666
|
+
border-top: 0;
|
|
667
|
+
border-bottom-color: var(--say);
|
|
718
668
|
}
|
|
719
669
|
|
|
720
|
-
.ai-note > .
|
|
670
|
+
.ai-note > .who + .say {
|
|
721
671
|
margin-top: 4px;
|
|
722
672
|
}
|
|
723
673
|
|
|
@@ -866,8 +816,8 @@
|
|
|
866
816
|
margin: 0 0 var(--between);
|
|
867
817
|
}
|
|
868
818
|
|
|
869
|
-
.ai-block:has(> .asleep) .say::before,
|
|
870
|
-
.ai-block:has(> .asleep) .say::after {
|
|
819
|
+
.ai-block:has(> .asleep) .says .say::before,
|
|
820
|
+
.ai-block:has(> .asleep) .says .say::after {
|
|
871
821
|
content: none;
|
|
872
822
|
}
|
|
873
823
|
|
package/dist/page/talk/talk.js
CHANGED
|
@@ -16,10 +16,10 @@ export function AiWords({ words, newestFirst, voice }) {
|
|
|
16
16
|
return (_jsx("ol", { ref: list, class: "says", "aria-live": "polite", children: inOrder(words.map((word, index) => (_jsx("li", { class: "say", style: aged(words.length - 1 - index), children: _jsx(Marked, { text: word }) }, index))), newestFirst) }));
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
|
-
* The AI's word on the move shown of a game in analysis (D-69), in a bubble
|
|
19
|
+
* The AI's word on the move shown of a game in analysis (D-69), in a bubble under the Torretta beside the AI's name, pointing up at it: the move, its badge by name,
|
|
20
20
|
* and its note when it wrote one; read out as the player steps through the game. The Torretta and the name stay when the move has no word.
|
|
21
21
|
*/
|
|
22
|
-
export function AiNote({ ply, opening, closing, summary, reviewing, name, by, mood, voice, text }) {
|
|
22
|
+
export function AiNote({ ply, opening, closing, summary, reviewing, onComplete, name, by, mood, voice, text }) {
|
|
23
23
|
// On a move of the book without the AI's note, the AI reports what the book says: the opening in the title, the variation under it.
|
|
24
24
|
const book = ply?.review?.note === undefined ? opening : undefined;
|
|
25
25
|
const shown = ply?.review ?? (book === undefined ? undefined : { badge: "book" });
|
|
@@ -32,10 +32,10 @@ export function AiNote({ ply, opening, closing, summary, reviewing, name, by, mo
|
|
|
32
32
|
}
|
|
33
33
|
return hush;
|
|
34
34
|
}, [spoken, voice]);
|
|
35
|
-
// The Torretta stays in sight through the whole analysis,
|
|
36
|
-
return (_jsxs("div", { class: "ai-note", "aria-live": "polite", children: [ply === undefined || shown === undefined ? null : (_jsxs("p", { class: `say move-note ${shown.badge ?? ""}`, children: [_jsxs("span", { class: "head", children: [shown.badge === undefined ? _jsx(NoteIcon, {}) : _jsx(BadgeIcon, { badge: shown.badge }), _jsxs("b", { children: [_jsxs("span", { class: "visually-hidden", children: [ply.number, ply.side === "white" ? "." : "...", ply.san] }), _jsxs("span", { "aria-hidden": "true", children: [_jsxs("span", { class: "move-number", children: [ply.number, ply.side === "white" ? "." : "..."] }), _jsx(Figurines, { san: ply.san, side: ply.side })] })] }), " ", title] }), note === undefined ? null : (_jsx("span", { class: "note", children: _jsx(Marked, { text: note }) })), shown.arrows === undefined && shown.squares === undefined ? null : _jsx(Legend, { review: shown, words: text.drawn })] })), summary === undefined ? null : _jsx(GameReview, { by: name, summary: summary, text: text }), closing === undefined ? null : (_jsx("p", { class: "say closing", children: _jsx(Marked, { text: closing }) })), reviewing === true
|
|
35
|
+
// The Torretta stays in sight through the whole analysis, over its bubbles, which show only where it wrote something.
|
|
36
|
+
return (_jsxs("div", { class: "ai-note", "aria-live": "polite", children: [_jsxs("p", { class: "who", children: [_jsx(Torretta, { size: 36, mood: mood }), _jsxs("span", { class: "signed", children: [name, by === undefined ? null : _jsx("small", { children: signature(by.annotator, by.effort) })] })] }), ply === undefined || shown === undefined ? null : (_jsxs("p", { class: `say move-note ${shown.badge ?? ""}`, children: [_jsxs("span", { class: "head", children: [shown.badge === undefined ? _jsx(NoteIcon, {}) : _jsx(BadgeIcon, { badge: shown.badge }), _jsxs("b", { children: [_jsxs("span", { class: "visually-hidden", children: [ply.number, ply.side === "white" ? "." : "...", ply.san] }), _jsxs("span", { "aria-hidden": "true", children: [_jsxs("span", { class: "move-number", children: [ply.number, ply.side === "white" ? "." : "..."] }), _jsx(Figurines, { san: ply.san, side: ply.side })] })] }), " ", title] }), note === undefined ? null : (_jsx("span", { class: "note", children: _jsx(Marked, { text: note }) })), shown.arrows === undefined && shown.squares === undefined ? null : _jsx(Legend, { review: shown, words: text.drawn })] })), summary === undefined ? null : _jsx(GameReview, { by: name, summary: summary, text: text }), closing === undefined ? null : (_jsx("p", { class: "say closing", children: _jsx(Marked, { text: closing }) })), reviewing === true
|
|
37
37
|
? (_jsxs("p", { class: "say reviewing", children: [_jsx("span", { class: "spinner", "aria-hidden": "true" }), text.reviewing(name)] }))
|
|
38
|
-
: null, _jsxs("p", { class: "
|
|
38
|
+
: null, onComplete === undefined ? null : (_jsxs("p", { class: "say incomplete", children: [_jsx("span", { role: "status", children: text.incomplete }), _jsx("button", { type: "button", title: text.completeHint, "aria-label": text.completeHint, onClick: onComplete, children: text.complete })] }))] }));
|
|
39
39
|
}
|
|
40
40
|
/** The squares and moves in the AI's words, such as e3, Cxe4, 7.Nd4 or O-O: in bold, as the player looks for them on the board. */
|
|
41
41
|
export function Marked({ text }) {
|
|
@@ -94,7 +94,7 @@ export function Compose({ lines, newestFirst, spent, draft, onDraft, onSend, can
|
|
|
94
94
|
* whoever moves and a dot on the Torretta when the AI spoke meanwhile.
|
|
95
95
|
*/
|
|
96
96
|
export function TalkFaces({ name, aiPicture, you, picture, ai, player, aiMoves, playerMoves, unread, text }) {
|
|
97
|
-
return (_jsxs("div", { class: "faces", children: [_jsx(RailPlayer, { place: "ai", picture: aiPicture ?? _jsx(Torretta, { size: 40 }), name: name, ...(ai === undefined ? {} : { side: text.sides[ai] }), moves: aiMoves, unread: unread }), _jsx(RailPlayer, { place: "you", picture: picture, name: you, ...(player === undefined ? {} : { side: text.sides[player] }), moves: playerMoves })] }));
|
|
97
|
+
return (_jsxs("div", { class: "faces", children: [_jsx(RailPlayer, { place: "ai", picture: aiPicture ?? _jsx(Torretta, { size: 40, bust: true }), name: name, ...(ai === undefined ? {} : { side: text.sides[ai] }), moves: aiMoves, unread: unread }), _jsx(RailPlayer, { place: "you", picture: picture, name: you, ...(player === undefined ? {} : { side: text.sides[player] }), moves: playerMoves })] }));
|
|
98
98
|
}
|
|
99
99
|
/** The move a line of the player's was written on, 14.♘f3, small at the line's head: a press shows it on the board again (Zoe). */
|
|
100
100
|
function ShownMove({ move, onShow, text }) {
|
package/dist/page/talk/voice.js
CHANGED
|
@@ -28,6 +28,18 @@ export function hush() {
|
|
|
28
28
|
speechSynthesis.cancel();
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
+
/** Whether the browser has a voice for the language: without one the words cannot be read. */
|
|
32
|
+
export function hasVoice(language) {
|
|
33
|
+
return typeof speechSynthesis !== "undefined" && readerFor(language) !== undefined;
|
|
34
|
+
}
|
|
35
|
+
/** Calls the listener whenever the browser's voices change, since Chrome lists them late: what it returns stops it. */
|
|
36
|
+
export function onVoices(listener) {
|
|
37
|
+
if (typeof speechSynthesis === "undefined") {
|
|
38
|
+
return () => undefined;
|
|
39
|
+
}
|
|
40
|
+
speechSynthesis.addEventListener("voiceschanged", listener);
|
|
41
|
+
return () => speechSynthesis.removeEventListener("voiceschanged", listener);
|
|
42
|
+
}
|
|
31
43
|
/**
|
|
32
44
|
* The words with each move the AI wrote said in words, since a voice reads ♟g4 as "chess pawn g4": ♞xf6+, Nxf6+, exd5, O-O, e8=♛. A square alone, e4,
|
|
33
45
|
* stays as it is; a pawn's move becomes words only with its figurine, a capture, a promotion or a check, and without the file it takes from.
|
package/dist/page/text.js
CHANGED
|
@@ -29,6 +29,7 @@ const english = {
|
|
|
29
29
|
theme: "Light or dark theme",
|
|
30
30
|
sounds: "Sounds",
|
|
31
31
|
voice: "Read the AI's words aloud",
|
|
32
|
+
noVoice: "This browser has no voice for this language: add one in your system's settings",
|
|
32
33
|
saidMove: (move) => moveInWords(englishMoveWords, move),
|
|
33
34
|
newGame: "New game",
|
|
34
35
|
offerDraw: "Offer a draw",
|
|
@@ -86,7 +87,7 @@ const english = {
|
|
|
86
87
|
saveMoves: "PGN",
|
|
87
88
|
saveMovesHint: "The moves alone, to open on Lichess or chess.com",
|
|
88
89
|
noGameNow: "No game in progress",
|
|
89
|
-
analysing: "Analysis
|
|
90
|
+
analysing: "Analysis",
|
|
90
91
|
badges: {
|
|
91
92
|
brilliant: "Brilliant",
|
|
92
93
|
great: "Great move",
|
|
@@ -114,6 +115,9 @@ const english = {
|
|
|
114
115
|
mated: (side) => `${side === "white" ? "White" : "Black"} is mated`,
|
|
115
116
|
},
|
|
116
117
|
reviewing: (name) => `${name} is going over the game…`,
|
|
118
|
+
incomplete: "Analysis not complete",
|
|
119
|
+
complete: "Complete it",
|
|
120
|
+
completeHint: "Complete the analysis",
|
|
117
121
|
you: "You",
|
|
118
122
|
ai: "AI",
|
|
119
123
|
sides: { white: "White", black: "Black" },
|
|
@@ -147,6 +151,20 @@ const english = {
|
|
|
147
151
|
boardLabel: (turn, lastMove) => `Chessboard, ${english.toMove(turn)}${lastMove === undefined ? "" : `, last move ${lastMove}`}`,
|
|
148
152
|
clearChat: (name) => `Before a new game, clear your chat with ${name}: in the window where you opened ${name}, not here, write /clear, then a message such as "new game". A clean chat plays faster.`,
|
|
149
153
|
outdated: (name) => `Chesspal has been updated, but this folder still has its old files: close the chat with ${name}, run chesspal init in this folder, and open a new chat.`,
|
|
154
|
+
update: {
|
|
155
|
+
mark: (version) => `Chesspal ${version} is out: update`,
|
|
156
|
+
title: "Update Chesspal",
|
|
157
|
+
offer: (version, current) => `Chesspal ${version} is out${current === undefined ? "" : `; this is ${current}`}. The table installs it and starts again by itself.`,
|
|
158
|
+
chatAgain: (name) => `The chat with ${name} starts again too, clean.`,
|
|
159
|
+
byHand: (name) => `You opened the chat with ${name} yourself: afterwards, close it and open a new one.`,
|
|
160
|
+
whilePlaying: "A game is going on: finish it, then update.",
|
|
161
|
+
install: "Update",
|
|
162
|
+
installing: (version) => `Installing ${version}…`,
|
|
163
|
+
installed: "Installed: the table starts again by itself once the game is over.",
|
|
164
|
+
failed: "Chesspal was not updated: close the chat, then type in a terminal, one after the other:",
|
|
165
|
+
notice: (version, name) => `Chesspal ${version} is out: close the chat with ${name}, type this command in a terminal, then open a new chat.`,
|
|
166
|
+
hide: "Hide until the next version",
|
|
167
|
+
},
|
|
150
168
|
offline: (name) => `${name} is not connected. Write it a message in the window where you opened ${name}, not in this page's chat: the page connects again by itself.`,
|
|
151
169
|
startClocks: "Start",
|
|
152
170
|
thinking: { move: "Thinking about its move", ponder: "Thinking while you play" },
|
|
@@ -155,6 +173,8 @@ const english = {
|
|
|
155
173
|
table: {
|
|
156
174
|
title: "Who are you playing?",
|
|
157
175
|
choose: "Choose the chat to play with: it opens in a window of its own, to keep open.",
|
|
176
|
+
reviewTitle: "Who reviews the game?",
|
|
177
|
+
reviewChoose: "Choose the chat that reviews the game: it opens in a window of its own, to keep open.",
|
|
158
178
|
restartHint: "Choose the model and effort, then press Claude Code or Codex: the chat starts again, clean, in the same window, once it has ended its answer. The game stays as it is.",
|
|
159
179
|
byHand: (name) => `You opened this chat yourself: change ${name}'s model with /model in its window, or close it and open one from here, with the choices below.`,
|
|
160
180
|
noChat: "No chat at the table: choose one",
|
|
@@ -190,6 +210,8 @@ const english = {
|
|
|
190
210
|
"profile-game": () => english.profile.whilePlaying,
|
|
191
211
|
"game-going": () => "A game is going on: finish it before you bring another to analyse.",
|
|
192
212
|
"pgn-unreadable": () => "Chesspal cannot read this PGN: check you copied the whole game, its tags and its moves.",
|
|
213
|
+
"update-game": () => english.update.whilePlaying,
|
|
214
|
+
"update-chat": (most, name) => `${name} is answering: update once it has done.`,
|
|
193
215
|
},
|
|
194
216
|
piece: (letter, side) => `${side} ${englishNames[letter]}`,
|
|
195
217
|
taken: (pieces, ahead) => `Pieces taken: ${pieces.length === 0 ? "none" : pieces.join(", ")}${ahead > 0 ? `; ahead by ${ahead}` : ""}`,
|
|
@@ -247,7 +269,6 @@ const english = {
|
|
|
247
269
|
back: "Back",
|
|
248
270
|
yourProfile: "Your profile",
|
|
249
271
|
editProfile: "Edit your profile",
|
|
250
|
-
yourPicture: "Your picture: edit your profile",
|
|
251
272
|
avatars: { "short-hair": "Short hair", bun: "Bun", glasses: "Glasses", beanie: "Beanie", beard: "Beard", curls: "Curls", moustache: "Moustache", "silver-bob": "Silver bob", cat: "Cat", owl: "Owl" },
|
|
252
273
|
whilePlaying: "Finish the game, or resign, before changing player.",
|
|
253
274
|
accounts: "Do you play on Lichess, Chess.com or in FIDE tournaments?",
|
|
@@ -352,25 +373,29 @@ const english = {
|
|
|
352
373
|
backward: ["Backward pawns", "A pawn left behind the pawns beside it, with the square in front of it attacked by an enemy pawn."],
|
|
353
374
|
passed: ["Passed pawns", "No enemy pawn in front of it, on its file or the files beside it."],
|
|
354
375
|
islands: ["Pawn islands", "Groups of pawns on neighbouring files, apart from each other."],
|
|
376
|
+
openFiles: ["Open files", "Files with no pawn of either side."],
|
|
355
377
|
halfOpen: ["Half-open files", "Files with enemy pawns and none of one's own."],
|
|
356
378
|
heavyOnFiles: ["Rooks and queens on open files", "Rooks and queens on open or half-open files."],
|
|
357
379
|
onSeventh: ["Rooks and queens on the seventh", "Rooks and queens on the enemy's second rank: the seventh for White, the second for Black."],
|
|
358
380
|
outposts: ["Outposts", "Squares on one's ranks 4 to 6, defended by a pawn, that no enemy pawn can ever attack."],
|
|
359
381
|
bishopPair: ["Bishop pair", "Both bishops still on the board."],
|
|
360
|
-
space: ["Space
|
|
382
|
+
space: ["Space", "How many squares of the enemy's half one's pieces attack."],
|
|
361
383
|
undeveloped: ["Minor pieces not developed", "Knights and bishops still on their first squares."],
|
|
362
384
|
castled: ["Castling", "How it castled; a dash while it still can, a cross once the king or the rooks have moved."],
|
|
363
385
|
kingAttacks: ["Enemy attacks around the king", "How many enemy attacks fall on the squares next to the king."],
|
|
364
386
|
},
|
|
365
|
-
groups: { pawns: "Pawns", pieces: "Pieces", king: "King" },
|
|
366
387
|
yes: "yes",
|
|
367
388
|
notYet: "not yet",
|
|
368
389
|
noMore: "no more",
|
|
369
390
|
phases: { opening: "Opening", middlegame: "Middlegame", endgame: "Endgame" },
|
|
370
|
-
openFiles: "Open files",
|
|
371
|
-
control: "Squares controlled",
|
|
372
|
-
both: "both",
|
|
373
391
|
controlled: (white, black, both) => `Squares only White's ${white}, only Black's ${black}, both ${both}`,
|
|
392
|
+
controlledBy: (who, count, you) => {
|
|
393
|
+
if (who === "both") {
|
|
394
|
+
return `Squares both control: ${count}`;
|
|
395
|
+
}
|
|
396
|
+
return `Squares only ${who === "white" ? "White" : "Black"}${you ? " (you)" : ""} controls: ${count}`;
|
|
397
|
+
},
|
|
398
|
+
bothSides: "both sides",
|
|
374
399
|
oppositeBishops: "Bishops of opposite colours",
|
|
375
400
|
repetitions: (times) => `This position has stood ${times} times`,
|
|
376
401
|
fiftyMoves: (halfMoves) => `${halfMoves} half-moves left before the fifty-move draw`,
|
|
@@ -394,9 +419,8 @@ const english = {
|
|
|
394
419
|
guide: {
|
|
395
420
|
title: "Guide",
|
|
396
421
|
contents: "Contents",
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
support: "Support Chesspal",
|
|
422
|
+
previous: "Previous page",
|
|
423
|
+
next: "Next page",
|
|
400
424
|
credits: "Credits",
|
|
401
425
|
creditLines: [
|
|
402
426
|
"The rules: [chess.js](https://github.com/jhlywa/chess.js), under the BSD 2-Clause license.",
|
|
@@ -405,6 +429,11 @@ const english = {
|
|
|
405
429
|
"The sounds: Chesspal's own.",
|
|
406
430
|
],
|
|
407
431
|
},
|
|
432
|
+
foot: {
|
|
433
|
+
onGitHub: "Chesspal on GitHub",
|
|
434
|
+
onNpm: "Chesspal on npm",
|
|
435
|
+
support: "Support Chesspal",
|
|
436
|
+
},
|
|
408
437
|
};
|
|
409
438
|
const italian = {
|
|
410
439
|
language: "it",
|
|
@@ -412,6 +441,7 @@ const italian = {
|
|
|
412
441
|
theme: "Tema chiaro o scuro",
|
|
413
442
|
sounds: "Suoni",
|
|
414
443
|
voice: "Leggi ad alta voce le parole dell'AI",
|
|
444
|
+
noVoice: "Questo browser non ha una voce per questa lingua: aggiungila nelle impostazioni del sistema",
|
|
415
445
|
saidMove: (move) => moveInWords(italianMoveWords, move),
|
|
416
446
|
newGame: "Nuova partita",
|
|
417
447
|
offerDraw: "Proponi patta",
|
|
@@ -469,7 +499,7 @@ const italian = {
|
|
|
469
499
|
saveMoves: "PGN",
|
|
470
500
|
saveMovesHint: "Solo le mosse, da aprire su Lichess o chess.com",
|
|
471
501
|
noGameNow: "Nessuna partita in corso",
|
|
472
|
-
analysing: "Analisi
|
|
502
|
+
analysing: "Analisi",
|
|
473
503
|
badges: {
|
|
474
504
|
brilliant: "Geniale",
|
|
475
505
|
great: "Ottima mossa",
|
|
@@ -497,6 +527,9 @@ const italian = {
|
|
|
497
527
|
mated: (side) => `Matto al ${side === "white" ? "Bianco" : "Nero"}`,
|
|
498
528
|
},
|
|
499
529
|
reviewing: (name) => `${name} sta analizzando la partita…`,
|
|
530
|
+
incomplete: "Analisi non completa",
|
|
531
|
+
complete: "Completa",
|
|
532
|
+
completeHint: "Completa l'analisi",
|
|
500
533
|
you: "Tu",
|
|
501
534
|
ai: "AI",
|
|
502
535
|
sides: { white: "Bianco", black: "Nero" },
|
|
@@ -530,6 +563,20 @@ const italian = {
|
|
|
530
563
|
boardLabel: (turn, lastMove) => `Scacchiera, ${italian.toMove(turn)}${lastMove === undefined ? "" : `, ultima mossa ${lastMove}`}`,
|
|
531
564
|
clearChat: (name) => `Prima di una nuova partita azzera la conversazione con ${name}: nella finestra dove hai aperto ${name}, non qui, scrivi /clear e poi un messaggio, per esempio "nuova partita". Con la chat pulita l'AI gioca più veloce.`,
|
|
532
565
|
outdated: (name) => `Chesspal è stato aggiornato, ma questa cartella ha ancora i file di prima: chiudi la chat con ${name}, esegui chesspal init in questa cartella e apri una chat nuova.`,
|
|
566
|
+
update: {
|
|
567
|
+
mark: (version) => `È uscito Chesspal ${version}: aggiorna`,
|
|
568
|
+
title: "Aggiorna Chesspal",
|
|
569
|
+
offer: (version, current) => `È uscita la versione ${version} di Chesspal${current === undefined ? "" : `; questa è la ${current}`}. Il tavolo la installa e riparte da solo.`,
|
|
570
|
+
chatAgain: (name) => `Anche la chat con ${name} riparte pulita.`,
|
|
571
|
+
byHand: (name) => `La chat con ${name} l'hai aperta tu: dopo, chiudila e aprine una nuova.`,
|
|
572
|
+
whilePlaying: "C'è una partita in corso: finiscila, poi aggiorna.",
|
|
573
|
+
install: "Aggiorna",
|
|
574
|
+
installing: (version) => `Installo la ${version}…`,
|
|
575
|
+
installed: "Installata: il tavolo riparte da solo a fine partita.",
|
|
576
|
+
failed: "Chesspal non si è aggiornato: chiudi la chat, poi scrivi in un terminale, uno dopo l'altro:",
|
|
577
|
+
notice: (version, name) => `È uscita la versione ${version} di Chesspal: chiudi la chat con ${name}, scrivi questo comando in un terminale e apri una chat nuova.`,
|
|
578
|
+
hide: "Nascondi fino alla prossima versione",
|
|
579
|
+
},
|
|
533
580
|
offline: (name) => `${name} è scollegato. Scrivigli un messaggio nella finestra dove hai aperto ${name}, non nella chat di questa pagina: la pagina si ricollega da sola.`,
|
|
534
581
|
startClocks: "Inizia",
|
|
535
582
|
thinking: { move: "Sta pensando alla sua mossa", ponder: "Pensa mentre giochi tu" },
|
|
@@ -538,6 +585,8 @@ const italian = {
|
|
|
538
585
|
table: {
|
|
539
586
|
title: "Contro chi giochi?",
|
|
540
587
|
choose: "Scegli la chat con cui giocare: parte in una finestra a parte, da tenere aperta.",
|
|
588
|
+
reviewTitle: "Chi analizza la partita?",
|
|
589
|
+
reviewChoose: "Scegli la chat che analizza la partita: parte in una finestra a parte, da tenere aperta.",
|
|
541
590
|
restartHint: "Scegli modello e ragionamento, poi premi Claude Code o Codex: la chat riparte pulita nella stessa finestra, appena ha finito di rispondere. La partita resta com'è.",
|
|
542
591
|
byHand: (name) => `Questa chat l'hai aperta tu: cambia il modello di ${name} con /model nella sua finestra, oppure chiudila e aprine una da qui, con le scelte qui sotto.`,
|
|
543
592
|
noChat: "Nessuna chat al tavolo: scegline una",
|
|
@@ -573,6 +622,8 @@ const italian = {
|
|
|
573
622
|
"profile-game": () => italian.profile.whilePlaying,
|
|
574
623
|
"game-going": () => "C'è una partita in corso: finiscila prima di portarne un'altra da analizzare.",
|
|
575
624
|
"pgn-unreadable": () => "Chesspal non riesce a leggere questo PGN: controlla di aver copiato la partita intera, intestazioni e mosse.",
|
|
625
|
+
"update-game": () => italian.update.whilePlaying,
|
|
626
|
+
"update-chat": (most, name) => `${name} sta rispondendo: aggiorna quando ha finito.`,
|
|
576
627
|
},
|
|
577
628
|
// Queen and rook are feminine in Italian.
|
|
578
629
|
piece: (letter, side) => `${italianNames[letter]} ${side === "white" ? (letter === "Q" || letter === "R" ? "bianca" : "bianco") : (letter === "Q" || letter === "R" ? "nera" : "nero")}`,
|
|
@@ -631,7 +682,6 @@ const italian = {
|
|
|
631
682
|
back: "Indietro",
|
|
632
683
|
yourProfile: "Il tuo profilo",
|
|
633
684
|
editProfile: "Modifica il profilo",
|
|
634
|
-
yourPicture: "La tua immagine: modifica il profilo",
|
|
635
685
|
avatars: { "short-hair": "Capelli corti", bun: "Chignon", glasses: "Occhiali", beanie: "Berretto", beard: "Barba", curls: "Ricci", moustache: "Baffi", "silver-bob": "Caschetto grigio", cat: "Gatto", owl: "Gufo" },
|
|
636
686
|
whilePlaying: "Finisci la partita, o abbandona, prima di cambiare giocatore.",
|
|
637
687
|
accounts: "Giochi su Lichess, Chess.com o nei tornei FIDE?",
|
|
@@ -736,25 +786,29 @@ const italian = {
|
|
|
736
786
|
backward: ["Pedoni arretrati", "Un pedone rimasto indietro rispetto a quelli accanto, con la casa davanti attaccata da un pedone nemico."],
|
|
737
787
|
passed: ["Pedoni passati", "Nessun pedone nemico davanti a lui, né sulla sua colonna né su quelle accanto."],
|
|
738
788
|
islands: ["Isole di pedoni", "Gruppi di pedoni su colonne vicine, separati fra loro."],
|
|
789
|
+
openFiles: ["Colonne aperte", "Colonne senza pedoni di nessuno dei due."],
|
|
739
790
|
halfOpen: ["Colonne semiaperte", "Colonne con pedoni nemici e nessuno dei propri."],
|
|
740
791
|
heavyOnFiles: ["Torri e donna su colonne aperte", "Torri e donna su colonne aperte o semiaperte."],
|
|
741
792
|
onSeventh: ["Torri e donna in settima", "Torri e donna sulla seconda traversa del nemico: la settima per il Bianco, la seconda per il Nero."],
|
|
742
793
|
outposts: ["Avamposti", "Case sulle proprie traverse dalla quarta alla sesta, difese da un pedone, che nessun pedone nemico potrà mai attaccare."],
|
|
743
794
|
bishopPair: ["Coppia degli alfieri", "Tutti e due gli alfieri ancora sulla scacchiera."],
|
|
744
|
-
space: ["Spazio
|
|
795
|
+
space: ["Spazio", "Quante case della metà avversaria attaccano i propri pezzi."],
|
|
745
796
|
undeveloped: ["Pezzi minori non sviluppati", "Cavalli e alfieri ancora sulle case di partenza."],
|
|
746
797
|
castled: ["Arrocco", "Come ha arroccato; un trattino finché può ancora farlo, una croce quando il re o le torri si sono già mossi."],
|
|
747
798
|
kingAttacks: ["Attacchi nemici attorno al re", "Quanti attacchi nemici cadono sulle case accanto al re."],
|
|
748
799
|
},
|
|
749
|
-
groups: { pawns: "Pedoni", pieces: "Pezzi", king: "Re" },
|
|
750
800
|
yes: "sì",
|
|
751
801
|
notYet: "non ancora",
|
|
752
802
|
noMore: "non più",
|
|
753
803
|
phases: { opening: "Apertura", middlegame: "Mediogioco", endgame: "Finale" },
|
|
754
|
-
openFiles: "Colonne aperte",
|
|
755
|
-
control: "Case controllate",
|
|
756
|
-
both: "tutti e due",
|
|
757
804
|
controlled: (white, black, both) => `Case solo del Bianco ${white}, solo del Nero ${black}, di tutti e due ${both}`,
|
|
805
|
+
controlledBy: (who, count, you) => {
|
|
806
|
+
if (who === "both") {
|
|
807
|
+
return `Case controllate da tutti e due: ${count}`;
|
|
808
|
+
}
|
|
809
|
+
return `Case controllate solo dal ${who === "white" ? "Bianco" : "Nero"}${you ? " (tu)" : ""}: ${count}`;
|
|
810
|
+
},
|
|
811
|
+
bothSides: "tutti e due",
|
|
758
812
|
oppositeBishops: "Alfieri di colore contrario",
|
|
759
813
|
repetitions: (times) => `Questa posizione si è vista ${times} volte`,
|
|
760
814
|
fiftyMoves: (halfMoves) => `Mancano ${halfMoves} semimosse alla patta delle cinquanta mosse`,
|
|
@@ -778,9 +832,8 @@ const italian = {
|
|
|
778
832
|
guide: {
|
|
779
833
|
title: "Guida",
|
|
780
834
|
contents: "Indice",
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
support: "Sostieni Chesspal",
|
|
835
|
+
previous: "Pagina precedente",
|
|
836
|
+
next: "Pagina seguente",
|
|
784
837
|
credits: "Crediti",
|
|
785
838
|
creditLines: [
|
|
786
839
|
"Le regole: [chess.js](https://github.com/jhlywa/chess.js), con licenza BSD 2-Clause.",
|
|
@@ -789,6 +842,11 @@ const italian = {
|
|
|
789
842
|
"I suoni: di Chesspal.",
|
|
790
843
|
],
|
|
791
844
|
},
|
|
845
|
+
foot: {
|
|
846
|
+
onGitHub: "Chesspal su GitHub",
|
|
847
|
+
onNpm: "Chesspal su npm",
|
|
848
|
+
support: "Sostieni Chesspal",
|
|
849
|
+
},
|
|
792
850
|
};
|
|
793
851
|
// How each piece moves, said when it was taken where it cannot go (Anatolij's words).
|
|
794
852
|
const englishMoves = {
|
package/dist/page/theme.css
CHANGED