WIP
This commit is contained in:
35
src/main.tsx
35
src/main.tsx
@@ -1,5 +1,4 @@
|
|||||||
import WebFont from "webfontloader";
|
import WebFont from "webfontloader";
|
||||||
// import * as Hammer from "hammerjs";
|
|
||||||
import { render } from "solid-js/web";
|
import { render } from "solid-js/web";
|
||||||
|
|
||||||
import { BoardStyle } from "./types";
|
import { BoardStyle } from "./types";
|
||||||
@@ -17,7 +16,6 @@ import createAnimation from "./encoders/createAnimation";
|
|||||||
import readFile from "./utils/readFile";
|
import readFile from "./utils/readFile";
|
||||||
import download from "./utils/download";
|
import download from "./utils/download";
|
||||||
import { compressPGN } from "./game/PGNHelpers";
|
import { compressPGN } from "./game/PGNHelpers";
|
||||||
// import extractUrlData from "./persistance/extractUrlData";
|
|
||||||
import importFromLink from "./imports/importFromLink";
|
import importFromLink from "./imports/importFromLink";
|
||||||
import isFEN from "./utils/isFEN";
|
import isFEN from "./utils/isFEN";
|
||||||
import isPGN from "./utils/isPGN";
|
import isPGN from "./utils/isPGN";
|
||||||
@@ -230,6 +228,10 @@ const main = async () => {
|
|||||||
setState("boardConfig", "sounds", !state.boardConfig.sounds);
|
setState("boardConfig", "sounds", !state.boardConfig.sounds);
|
||||||
saveConfig("board");
|
saveConfig("board");
|
||||||
},
|
},
|
||||||
|
toggleSpeech() {
|
||||||
|
setState("boardConfig", "speech", !state.boardConfig.speech);
|
||||||
|
saveConfig("board");
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Render the page */
|
/* Render the page */
|
||||||
@@ -332,25 +334,13 @@ const main = async () => {
|
|||||||
handlers.loadPGN(content);
|
handlers.loadPGN(content);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
// const hammer = new Hammer.Manager(board.canvas);
|
|
||||||
// hammer.add(new Hammer.Swipe());
|
|
||||||
// hammer.add(new Hammer.Pinch());
|
|
||||||
// hammer.add(new Hammer.Press({ time: 500 }));
|
|
||||||
// hammer.add(new Hammer.Tap({ taps: 1 }));
|
|
||||||
// hammer.on("swiperight", handlers.next);
|
|
||||||
// hammer.on("swipeleft", handlers.prev);
|
|
||||||
// hammer.on("swipeup", handlers.first);
|
|
||||||
// hammer.on("swipedown", handlers.last);
|
|
||||||
// hammer.on("pinchin", handlers.showBorder);
|
|
||||||
// hammer.on("pinchout", handlers.hideBorder);
|
|
||||||
// hammer.on("tap", handlers.next);
|
|
||||||
// hammer.on("press", handlers.flip);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Boot */
|
/* Boot */
|
||||||
|
|
||||||
|
Promise.all([
|
||||||
|
new Promise((resolve) =>
|
||||||
WebFont.load({
|
WebFont.load({
|
||||||
google: {
|
google: {
|
||||||
families: ["Ubuntu:500,700", "Fira Mono:500"],
|
families: ["Ubuntu:500,700", "Fira Mono:500"],
|
||||||
@@ -359,5 +349,14 @@ WebFont.load({
|
|||||||
families: ["Chess"],
|
families: ["Chess"],
|
||||||
urls: ["/fonts.css"],
|
urls: ["/fonts.css"],
|
||||||
},
|
},
|
||||||
active: main,
|
active: () => resolve(null),
|
||||||
});
|
})
|
||||||
|
).catch(() => null),
|
||||||
|
new Promise((resolve) => {
|
||||||
|
if (speechSynthesis.getVoices().length > 0) {
|
||||||
|
resolve(null);
|
||||||
|
} else {
|
||||||
|
window.speechSynthesis.onvoiceschanged = resolve;
|
||||||
|
}
|
||||||
|
}).catch(() => null),
|
||||||
|
]).then(() => main());
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import Board from "../board/Board";
|
|||||||
import Game from "../game/Game";
|
import Game from "../game/Game";
|
||||||
import { setState, state } from "../state";
|
import { setState, state } from "../state";
|
||||||
import sfx from "./sfx";
|
import sfx from "./sfx";
|
||||||
|
import Speech, { sanToText } from "./speach";
|
||||||
|
|
||||||
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
|
||||||
@@ -11,11 +12,14 @@ class Player {
|
|||||||
private game: Game = new Game();
|
private game: Game = new Game();
|
||||||
private ply: number = 0;
|
private ply: number = 0;
|
||||||
private callback: (playing: boolean, ply: number) => void = () => {};
|
private callback: (playing: boolean, ply: number) => void = () => {};
|
||||||
|
private speech: Speech;
|
||||||
public playing: boolean = false;
|
public playing: boolean = false;
|
||||||
|
|
||||||
private firstRender: Promise<void>;
|
private firstRender: Promise<void>;
|
||||||
|
|
||||||
constructor(private board: Board, private config: GameConfig) {
|
constructor(private board: Board, private config: GameConfig) {
|
||||||
|
this.speech = new Speech();
|
||||||
|
|
||||||
this.firstRender = this.board
|
this.firstRender = this.board
|
||||||
.frame(this.game.getPosition(0), this.game.header)
|
.frame(this.game.getPosition(0), this.game.header)
|
||||||
.then((_) => this.board.render());
|
.then((_) => this.board.render());
|
||||||
@@ -109,6 +113,10 @@ class Player {
|
|||||||
await this.board.frame(position, this.game.header);
|
await this.board.frame(position, this.game.header);
|
||||||
this.board.render();
|
this.board.render();
|
||||||
|
|
||||||
|
if (state.boardConfig.speech) {
|
||||||
|
this.speech.say(sanToText(position.move?.san as string));
|
||||||
|
}
|
||||||
|
|
||||||
if (this.ply > 0 && state.boardConfig.sounds) {
|
if (this.ply > 0 && state.boardConfig.sounds) {
|
||||||
if (position.mate) {
|
if (position.mate) {
|
||||||
sfx.snap.play();
|
sfx.snap.play();
|
||||||
|
|||||||
66
src/player/speach.ts
Normal file
66
src/player/speach.ts
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
const words: { [key: string]: string } = {
|
||||||
|
x: " takes ",
|
||||||
|
"+": " check!",
|
||||||
|
"#": " mate!",
|
||||||
|
"=": " promotes to a ",
|
||||||
|
P: "pawn ",
|
||||||
|
R: "rook ",
|
||||||
|
B: "bishop ",
|
||||||
|
N: "knight ",
|
||||||
|
Q: "queen ",
|
||||||
|
K: "king ",
|
||||||
|
"O-O": "short castle",
|
||||||
|
"O-O-O": "long castle",
|
||||||
|
};
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
volume: 50,
|
||||||
|
rate: 2,
|
||||||
|
lang: "en-US",
|
||||||
|
};
|
||||||
|
|
||||||
|
const sanToText = (move: string) => {
|
||||||
|
if (move === "O-O" || move === "O-O-O") {
|
||||||
|
move = words[move];
|
||||||
|
} else {
|
||||||
|
// Handles special cases like R2a6 ore Nbd2
|
||||||
|
const special = move.match(/[a-h1-8][a-h][1-8]/);
|
||||||
|
|
||||||
|
if (special) {
|
||||||
|
move = move.replace(
|
||||||
|
special[0],
|
||||||
|
`${special[0][0]} ${special[0][1]}${special[0][2]}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
move = move
|
||||||
|
.split("")
|
||||||
|
.map((x) => words[x] ?? x)
|
||||||
|
.join("")
|
||||||
|
.replace(/\s{2,}/g, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
return move;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Speach {
|
||||||
|
private voice: SpeechSynthesisVoice | undefined;
|
||||||
|
constructor() {
|
||||||
|
const voices = speechSynthesis.getVoices();
|
||||||
|
this.voice = voices.find((voice) => voice.lang === config.lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
say(text: string) {
|
||||||
|
const info = new SpeechSynthesisUtterance(text);
|
||||||
|
info.volume = config.volume / 100;
|
||||||
|
info.lang = config.lang;
|
||||||
|
if (this.voice) {
|
||||||
|
info.voice = this.voice;
|
||||||
|
}
|
||||||
|
info.rate = 1 + config.rate / 10;
|
||||||
|
speechSynthesis.speak(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { sanToText };
|
||||||
|
export default Speach;
|
||||||
@@ -21,6 +21,7 @@ const initialBoardConfig: BoardConfig = {
|
|||||||
showCoords: true,
|
showCoords: true,
|
||||||
showShadows: false,
|
showShadows: false,
|
||||||
sounds: true,
|
sounds: true,
|
||||||
|
speech: false,
|
||||||
flipped: false,
|
flipped: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -73,8 +74,6 @@ const initialState: State = {
|
|||||||
refreshHash: true,
|
refreshHash: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log(initialState);
|
|
||||||
|
|
||||||
const [state, setState] = createStore(initialState);
|
const [state, setState] = createStore(initialState);
|
||||||
|
|
||||||
export { state, setState };
|
export { state, setState };
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ export type BoardConfig = {
|
|||||||
showCoords: boolean;
|
showCoords: boolean;
|
||||||
showShadows: boolean;
|
showShadows: boolean;
|
||||||
sounds: boolean;
|
sounds: boolean;
|
||||||
|
speech: boolean;
|
||||||
flipped: boolean;
|
flipped: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -173,6 +174,7 @@ export type Handlers = {
|
|||||||
downloadImage: () => Promise<void>;
|
downloadImage: () => Promise<void>;
|
||||||
downloadAnimation: () => Promise<void>;
|
downloadAnimation: () => Promise<void>;
|
||||||
toggleSound(): void;
|
toggleSound(): void;
|
||||||
|
toggleSpeech(): void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Header = {
|
export type Header = {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.header__options {
|
.header__options {
|
||||||
padding: 0 2rem;
|
padding: 0 2rem 0;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,8 +36,7 @@
|
|||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
padding-top: 1rem;
|
padding-top: 1rem;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin-left: 10px;
|
margin-left: 0.5rem;
|
||||||
/* background-color: aqua; */
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Component, createSignal } from "solid-js";
|
import { Component, createSignal } from "solid-js";
|
||||||
import { Handlers } from "../../types";
|
import { Handlers } from "../../types";
|
||||||
// import { state, setState } from "../../state";
|
import { state, setState } from "../../state";
|
||||||
import "./Header.css";
|
import "./Header.css";
|
||||||
|
|
||||||
const Header: Component<{ handlers: Handlers }> = () => {
|
const Header: Component<{ handlers: Handlers }> = (props) => {
|
||||||
const [darkMode, setDarkMode] = createSignal(true);
|
const [darkMode, setDarkMode] = createSignal(true);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -15,6 +15,36 @@ const Header: Component<{ handlers: Handlers }> = () => {
|
|||||||
{/* <div class="header__options-ico" onClick={() => {}}>
|
{/* <div class="header__options-ico" onClick={() => {}}>
|
||||||
<i class="las la-question-circle"></i>
|
<i class="las la-question-circle"></i>
|
||||||
</div> */}
|
</div> */}
|
||||||
|
<div
|
||||||
|
class="header__options-ico"
|
||||||
|
onClick={() => {
|
||||||
|
props.handlers.toggleSound();
|
||||||
|
}}
|
||||||
|
title={state.boardConfig.sounds ? "MUTE" : "SOUND ON"}
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
classList={{
|
||||||
|
las: true,
|
||||||
|
"la-volume-mute": !state.boardConfig.sounds,
|
||||||
|
"la-volume-up": state.boardConfig.sounds,
|
||||||
|
}}
|
||||||
|
></i>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="header__options-ico"
|
||||||
|
onClick={() => {
|
||||||
|
props.handlers.toggleSpeech();
|
||||||
|
}}
|
||||||
|
title={state.boardConfig.speech ? "SPEECH OFF" : "SPEECH ON"}
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
classList={{
|
||||||
|
las: true,
|
||||||
|
"la-deaf": !state.boardConfig.speech,
|
||||||
|
"la-assistive-listening-systems": state.boardConfig.speech,
|
||||||
|
}}
|
||||||
|
></i>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
class="header__options-ico"
|
class="header__options-ico"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|||||||
@@ -81,17 +81,6 @@ const Share: Component<{ handlers: Handlers; class?: string }> = (props) => {
|
|||||||
>
|
>
|
||||||
<i class="las la-cloud"></i>
|
<i class="las la-cloud"></i>
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
classList={{
|
|
||||||
options__button: true,
|
|
||||||
"options__button--last": true,
|
|
||||||
"options__button--active": state.boardConfig.sounds,
|
|
||||||
}}
|
|
||||||
onClick={props.handlers.toggleSound}
|
|
||||||
title={state.boardConfig.sounds ? "MUTE" : "SOUND ON"}
|
|
||||||
>
|
|
||||||
<i class="las la-volume-up"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
<div className="share__fen">
|
<div className="share__fen">
|
||||||
|
|||||||
Reference in New Issue
Block a user