WIP
This commit is contained in:
51
src/main.tsx
51
src/main.tsx
@@ -1,5 +1,4 @@
|
||||
import WebFont from "webfontloader";
|
||||
// import * as Hammer from "hammerjs";
|
||||
import { render } from "solid-js/web";
|
||||
|
||||
import { BoardStyle } from "./types";
|
||||
@@ -17,7 +16,6 @@ import createAnimation from "./encoders/createAnimation";
|
||||
import readFile from "./utils/readFile";
|
||||
import download from "./utils/download";
|
||||
import { compressPGN } from "./game/PGNHelpers";
|
||||
// import extractUrlData from "./persistance/extractUrlData";
|
||||
import importFromLink from "./imports/importFromLink";
|
||||
import isFEN from "./utils/isFEN";
|
||||
import isPGN from "./utils/isPGN";
|
||||
@@ -230,6 +228,10 @@ const main = async () => {
|
||||
setState("boardConfig", "sounds", !state.boardConfig.sounds);
|
||||
saveConfig("board");
|
||||
},
|
||||
toggleSpeech() {
|
||||
setState("boardConfig", "speech", !state.boardConfig.speech);
|
||||
saveConfig("board");
|
||||
},
|
||||
};
|
||||
|
||||
/* Render the page */
|
||||
@@ -332,32 +334,29 @@ const main = async () => {
|
||||
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 */
|
||||
|
||||
WebFont.load({
|
||||
google: {
|
||||
families: ["Ubuntu:500,700", "Fira Mono:500"],
|
||||
},
|
||||
custom: {
|
||||
families: ["Chess"],
|
||||
urls: ["/fonts.css"],
|
||||
},
|
||||
active: main,
|
||||
});
|
||||
Promise.all([
|
||||
new Promise((resolve) =>
|
||||
WebFont.load({
|
||||
google: {
|
||||
families: ["Ubuntu:500,700", "Fira Mono:500"],
|
||||
},
|
||||
custom: {
|
||||
families: ["Chess"],
|
||||
urls: ["/fonts.css"],
|
||||
},
|
||||
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 { setState, state } from "../state";
|
||||
import sfx from "./sfx";
|
||||
import Speech, { sanToText } from "./speach";
|
||||
|
||||
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
@@ -11,11 +12,14 @@ class Player {
|
||||
private game: Game = new Game();
|
||||
private ply: number = 0;
|
||||
private callback: (playing: boolean, ply: number) => void = () => {};
|
||||
private speech: Speech;
|
||||
public playing: boolean = false;
|
||||
|
||||
private firstRender: Promise<void>;
|
||||
|
||||
constructor(private board: Board, private config: GameConfig) {
|
||||
this.speech = new Speech();
|
||||
|
||||
this.firstRender = this.board
|
||||
.frame(this.game.getPosition(0), this.game.header)
|
||||
.then((_) => this.board.render());
|
||||
@@ -109,6 +113,10 @@ class Player {
|
||||
await this.board.frame(position, this.game.header);
|
||||
this.board.render();
|
||||
|
||||
if (state.boardConfig.speech) {
|
||||
this.speech.say(sanToText(position.move?.san as string));
|
||||
}
|
||||
|
||||
if (this.ply > 0 && state.boardConfig.sounds) {
|
||||
if (position.mate) {
|
||||
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,
|
||||
showShadows: false,
|
||||
sounds: true,
|
||||
speech: false,
|
||||
flipped: false,
|
||||
};
|
||||
|
||||
@@ -73,8 +74,6 @@ const initialState: State = {
|
||||
refreshHash: true,
|
||||
};
|
||||
|
||||
console.log(initialState);
|
||||
|
||||
const [state, setState] = createStore(initialState);
|
||||
|
||||
export { state, setState };
|
||||
|
||||
@@ -90,6 +90,7 @@ export type BoardConfig = {
|
||||
showCoords: boolean;
|
||||
showShadows: boolean;
|
||||
sounds: boolean;
|
||||
speech: boolean;
|
||||
flipped: boolean;
|
||||
};
|
||||
|
||||
@@ -173,6 +174,7 @@ export type Handlers = {
|
||||
downloadImage: () => Promise<void>;
|
||||
downloadAnimation: () => Promise<void>;
|
||||
toggleSound(): void;
|
||||
toggleSpeech(): void;
|
||||
};
|
||||
|
||||
export type Header = {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
}
|
||||
|
||||
.header__options {
|
||||
padding: 0 2rem;
|
||||
padding: 0 2rem 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@@ -36,8 +36,7 @@
|
||||
color: var(--color-text);
|
||||
padding-top: 1rem;
|
||||
height: 100%;
|
||||
margin-left: 10px;
|
||||
/* background-color: aqua; */
|
||||
margin-left: 0.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Component, createSignal } from "solid-js";
|
||||
import { Handlers } from "../../types";
|
||||
// import { state, setState } from "../../state";
|
||||
import { state, setState } from "../../state";
|
||||
import "./Header.css";
|
||||
|
||||
const Header: Component<{ handlers: Handlers }> = () => {
|
||||
const Header: Component<{ handlers: Handlers }> = (props) => {
|
||||
const [darkMode, setDarkMode] = createSignal(true);
|
||||
|
||||
return (
|
||||
@@ -15,6 +15,36 @@ const Header: Component<{ handlers: Handlers }> = () => {
|
||||
{/* <div class="header__options-ico" onClick={() => {}}>
|
||||
<i class="las la-question-circle"></i>
|
||||
</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
|
||||
class="header__options-ico"
|
||||
onClick={() => {
|
||||
|
||||
@@ -81,17 +81,6 @@ const Share: Component<{ handlers: Handlers; class?: string }> = (props) => {
|
||||
>
|
||||
<i class="las la-cloud"></i>
|
||||
</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>
|
||||
<hr />
|
||||
<div className="share__fen">
|
||||
|
||||
Reference in New Issue
Block a user