From 6a3c40b36c413da1b30f166d9993ff639041bab5 Mon Sep 17 00:00:00 2001 From: Yuriy Evdokimov Date: Wed, 4 Oct 2023 22:43:20 +0500 Subject: [PATCH] tones, begin of state management --- src/App.tsx | 225 +++++++++++++++++++++++++++++++------------------ src/Data.ts | 6 +- src/Utils.ts | 25 +++++- src/reducer.ts | 23 +++++ src/store.tsx | 17 ++++ 5 files changed, 210 insertions(+), 86 deletions(-) create mode 100644 src/reducer.ts create mode 100644 src/store.tsx diff --git a/src/App.tsx b/src/App.tsx index 2074759..ada75ef 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,12 +1,11 @@ import { useState } from 'react' import './App.css' -import Accordion from 'react-bootstrap/Accordion'; import Form from 'react-bootstrap/Form'; -import { Badge, Button, Modal } from 'react-bootstrap'; -import { initials, finales, syllables, tones } from './Data'; -import { isEnabled, toggle } from './Utils'; -import { Found, Syllable, Tone } from './Types'; -import { strings } from './Strings'; +import { Badge, Button, ListGroup } from 'react-bootstrap'; +import { initials, finales, syllables, tones } from './data'; +import { getRandomTones, isEnabled, toggle } from './utils'; +import { Found, Syllable, Tone } from './types'; +import { strings } from './strings'; const defaultFoundState:Found = { allfinales: false, @@ -14,9 +13,12 @@ const defaultFoundState:Found = { finales: [], initiales: [], syllables: [], - tones: [] + toneS: [], + randomTones: [] } +enum Status {params, plaing, plaied, showlist} + function App() { const [ count, setCount ] = useState(10) @@ -25,71 +27,135 @@ function App() { const [ found, setFound ] = useState(defaultFoundState) const onchangepause = (e: React.ChangeEvent ) => setPause( Number(e.target.value) ) - const onchangecount = (e: React.ChangeEvent ) => setCount( Number(e.target.value) ) + const onchangecount = (e: React.ChangeEvent ) => { + setCount( Number(e.target.value) ) + refreshRandomTones() + } //---------------- to found state const toggleAllInitiales = () => { + let toggled = found.allInitiales ? [] : initials + let foundSyllables:Syllable[] = syllables.filter( syl => + toggled.includes(syl.initiale) && found.finales.includes(syl.finale) ) + let foundTones = tones.filter( t => foundSyllables.some( syl => syl.tones.some( st => st===t.tone) ) ) + let foundRandomTones = getRandomTones( foundTones, count ) setFound({...found, allInitiales: !found.allInitiales, - initiales: found.allInitiales ? [] : initials + initiales: toggled, + syllables: foundSyllables, + toneS: foundTones, + randomTones: foundRandomTones }) } - const toggleInitialsState = (caption: String) => setFound({...found, - initiales: toggle(found.initiales,caption) - }) - const toggleInitiales = (captions: String[]) => setFound({...found, - initiales: [...found.initiales.filter( f => !captions.includes(f)), - ...captions.filter( c => !found.initiales.includes(c))] - }) - // let arr3 = [...arr1, ...arr2]; - //uniqueItems = [...new Set(items)] + const toggleInitialsState = (caption: string) => { + let toggled = toggle(found.initiales,caption) + let foundSyllables:Syllable[] = syllables.filter( syl => + toggled.includes(syl.initiale) && found.finales.includes(syl.finale) ) + let foundTones = tones.filter( t => foundSyllables.some( syl => syl.tones.some( st => st===t.tone) ) ) + let foundRandomTones = getRandomTones( foundTones, count ) + setFound({...found, + initiales: toggled, + syllables: foundSyllables, + toneS: foundTones, + randomTones: foundRandomTones + }) + } + const toggleAllFinales = () => { + let toggled = found.allfinales ? [] : finales.map( f => f.finale) + let foundSyllables:Syllable[] = syllables.filter ( syl => + found.initiales.includes( syl.initiale) && toggled.includes( syl.finale ) ) + let foundTones = tones.filter( t => foundSyllables.some( syl => syl.tones.some( st => st===t.tone) ) ) + let foundRandomTones = getRandomTones( foundTones, count ) setFound({...found, allfinales: !found.allfinales, - finales: found.allfinales ? [] : finales.map( f => f.finale) + finales: toggled, + syllables: foundSyllables, + toneS: foundTones, + randomTones: foundRandomTones }) + } +const toggleFinalsState = (caption: string) => { + let toggled = toggle(found.finales,caption) + let foundSyllables:Syllable[] = syllables.filter ( syl => + found.initiales.includes( syl.initiale) && toggled.includes( syl.finale ) ) + let foundTones = tones.filter( t => foundSyllables.some( syl => syl.tones.some( st => st===t.tone) ) ) + let foundRandomTones = getRandomTones( foundTones, count ) + setFound({...found, + finales: toggled, + syllables: foundSyllables, + toneS: foundTones, + randomTones: foundRandomTones + }) + } + + const isFound = ():boolean => found.syllables.length > 0 + const [plaingNo, setPlaingNo ] = useState(0) + +// ---- опять по новой +const [ status, setStatus ] = useState(Status.params) + +const beginDictation = (): void => { + refreshRandomTones() + console.debug(found.randomTones) + playDictation2(found.randomTones) } -const toggleFinalsState = (caption: String) => setFound({...found, - finales: toggle(found.finales,caption) -}) -//---------------------- - const foundSyllables = ():Syllable[] => syllables.filter( (syl) => ( found.initiales.some( (i) => i == syl.initiale ) ) - && ( found.finales.some( (f) => f == syl.finale ) ) ) +const playDictation2 = (randomTones: Tone[]) => { + if ( randomTones.length == 0 ) return + let audios:HTMLAudioElement[] = [] + randomTones.forEach(element => { + audios = [...audios, new Audio(`/src/assets/audio/${element.tone}.mp3`) ] + }); + console.debug(audios) + if ( audios.length == 0 ) return + for(let x=0; x setTimeout( () => { + let pno = x+2 + setPlaingNo(pno) + audios[x+1].play() + }, 1000*pause ) ; + } + audios[audios.length-1].onended = () => setStatus(Status.plaied) + setStatus(Status.plaing) + setPlaingNo(1) + audios[0].play() +} - const isFound = ():boolean => foundSyllables().length > 0 +const renderRandomTones2 = () => { + return found.randomTones.map( (ton, i) => { return {ton.caption}{' '} }) +} - const [show, setShow] = useState(false); +const refresh = () => { + refreshRandomTones() + setStatus(Status.params) +} - const handleClose = () => setShow(false); - const handleShow = () => setShow(true); - - const foundTones = ():Tone[] => tones.filter( (t) => foundSyllables().some( (syl) => syl.tones.some( (st) => st===t.tone) ) ) - // const randomTones = ( length:number, fromTones:Tone[]):Tone[] => { - // const ftones = foundTones(); - // return ftones - // } +const refreshRandomTones = () => { + let foundRandomTones = getRandomTones( found.toneS, count ) + setFound({...found, + randomTones: foundRandomTones + }) + } return ( <>

Диктант pīnyīn

- - - {strings.selectInitiales} - + + +

{strings.selectInitiales}

{initials.map( (text, i) => )} -
-
- - {strings.selectFinales} - + + +

{strings.selectFinales}

)} -
-
- - {strings.params} - + + +

{strings.params}

Количество слогов {count} Пауза между слогами {pause} секунд -
-
-
-
- Выбрано {found.initiales.length} инициалей, {found.finales.length} финалей, количество слогов {count}, пауза между слогами {pause} секунд. -
- Найдено {foundSyllables().length} слогов, { foundSyllables().reduce( - ( p, c ) => p + c.tones.length , 0 - ) } тонов -
- -
- - - Modal heading - - - - {foundTones().map( (t, i) => <>{t.caption}{' '})} - - - - - - + + } + { + status == Status.plaing && +

Воспроизводится...{plaingNo}

+ } + { + status == Status.plaied && + + } + { + status == Status.showlist && + <> +
{renderRandomTones2()}
+
+ + + } + + ) } export default App + diff --git a/src/Data.ts b/src/Data.ts index 3de3a90..53e0985 100644 --- a/src/Data.ts +++ b/src/Data.ts @@ -1,6 +1,6 @@ -import { Finale, Syllable, Tone } from "./Types" +import { Finale, Syllable, Tone } from "./types" -export const initials: String[] = [ '-', 'y', 'w', +export const initials: string[] = [ '-', 'y', 'w', 'b', 'p', 'm', 'f', 'd', 't', 'n', 'l', 'g', 'k', 'h', 'j', 'q', 'x', 'zh', 'ch', 'sh', 'r', 'z', 'c', 's' ] @@ -41,7 +41,7 @@ export const finales: Finale[] = [ { caption: 'üan', finale: 'van' }, { caption: 'üe', finale: 've' }, { caption: 'ü', finale: 'v' }, - { caption: 'ün', finale: 'vn' } + { caption: 'ün', finale: 'vn' } ] export const syllables: Syllable[] = [ diff --git a/src/Utils.ts b/src/Utils.ts index b2f0e8d..e634150 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -1,8 +1,29 @@ -export const isEnabled = (arr: String[], caption: String): Boolean => arr.some((btn) => btn==caption) +import { Tone } from "./types" -export const toggle = ( arr: String[], caption: String ):String[] => { +export const isEnabled = (arr: string[], caption: string): boolean => arr.some((btn) => btn==caption) + +export const toggle = ( arr: string[], caption: string ):string[] => { if ( arr.some((btn) => btn==caption) ) return arr.filter((el)=>el!==caption) else return [ ...arr, caption] +} + +export const genrateRandomNumber = (min: number, max: number):number => { + min = Math.ceil(min) + max = Math.floor(max) + let rnd = Math.floor(Math.random() * (max - min + 1)) + min + return rnd +} + +export const getRandomTones = (fromTomes:Tone[], counT:number):Tone[] => { + let _tone:Tone[] = [] + if (fromTomes.length==0) { + return _tone + } + for( let x=0; x { + switch (action.type) { + default: return state + } +} + +export const defaultState:Found = { + allfinales: false, + allInitiales: false, + finales: [], + initiales: [], + syllables: [], + toneS: [], + randomTones: [] + } \ No newline at end of file diff --git a/src/store.tsx b/src/store.tsx new file mode 100644 index 0000000..27f6153 --- /dev/null +++ b/src/store.tsx @@ -0,0 +1,17 @@ +import { Context, createContext, Dispatch, ReactElement, useContext, useReducer } from "react"; +import { reducer, defaultState, Action } from "./reducer" +import { Found } from "./types"; + +export interface IStore { + state: Found + dispatch?: Dispatch +} + +export const AppContext:Context = createContext({ state: defaultState, dispatch: () => null }) + +export const useStateContext = () => useContext(AppContext); + +export const StateProvider = ({ children }: { children: ReactElement }) => { + const [state, dispatch] = useReducer(reducer, defaultState); + return +} \ No newline at end of file