globalstate + params + btnsets
parent
e1bf83fd58
commit
5665eb4955
144
src/App.tsx
144
src/App.tsx
|
|
@ -1,103 +1,29 @@
|
|||
import { useState } from 'react'
|
||||
import './App.css'
|
||||
import Form from 'react-bootstrap/Form';
|
||||
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 { initials, finales } from './data';
|
||||
import { BtnColor, Tone } from './types';
|
||||
import { strings } from './strings';
|
||||
|
||||
const defaultFoundState:Found = {
|
||||
allfinales: false,
|
||||
allInitiales: false,
|
||||
finales: [],
|
||||
initiales: [],
|
||||
syllables: [],
|
||||
toneS: [],
|
||||
randomTones: []
|
||||
}
|
||||
import { useStateContext } from './store';
|
||||
import { Params } from './params';
|
||||
import { ActionType, ToggleType } from './reducer';
|
||||
import { ButtonSet } from './buttons';
|
||||
|
||||
enum Status {params, plaing, plaied, showlist}
|
||||
|
||||
function App() {
|
||||
|
||||
const { state, dispatch } = useStateContext();
|
||||
|
||||
const [ count, setCount ] = useState(10)
|
||||
const [ pause, setPause ] = useState(3)
|
||||
|
||||
const [ found, setFound ] = useState(defaultFoundState)
|
||||
|
||||
const onchangepause = (e: React.ChangeEvent<HTMLInputElement> ) => setPause( Number(e.target.value) )
|
||||
const onchangecount = (e: React.ChangeEvent<HTMLInputElement> ) => {
|
||||
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: toggled,
|
||||
syllables: foundSyllables,
|
||||
toneS: foundTones,
|
||||
randomTones: foundRandomTones
|
||||
})
|
||||
}
|
||||
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: 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 isFound = ():boolean => state.foundSyllables!.length > 0
|
||||
const [plaingNo, setPlaingNo ] = useState(0)
|
||||
|
||||
// ---- опять по новой
|
||||
const [ status, setStatus ] = useState(Status.params)
|
||||
|
||||
const beginDictation = (): void => {
|
||||
refreshRandomTones()
|
||||
console.debug(found.randomTones)
|
||||
playDictation2(found.randomTones)
|
||||
dispatch({ type: ActionType.refreshPlayList })
|
||||
playDictation2(state.randomTones!)
|
||||
}
|
||||
|
||||
const playDictation2 = (randomTones: Tone[]) => {
|
||||
|
|
@ -114,7 +40,7 @@ const playDictation2 = (randomTones: Tone[]) => {
|
|||
let pno = x+2
|
||||
setPlaingNo(pno)
|
||||
audios[x+1].play()
|
||||
}, 1000*pause ) ;
|
||||
}, 1000*state.sylPause! ) ;
|
||||
}
|
||||
audios[audios.length-1].onended = () => setStatus(Status.plaied)
|
||||
setStatus(Status.plaing)
|
||||
|
|
@ -123,60 +49,36 @@ const playDictation2 = (randomTones: Tone[]) => {
|
|||
}
|
||||
|
||||
const renderRandomTones2 = () => {
|
||||
return found.randomTones.map( (ton, i) => { return <span key={i}><Badge bg="success" pill>{ton.caption}</Badge>{' '}</span> })
|
||||
return state.randomTones!.map( (ton, i) => { return <span key={i}><Badge bg="success" pill>{ton.caption}</Badge>{' '}</span> })
|
||||
}
|
||||
|
||||
const refresh = () => {
|
||||
refreshRandomTones()
|
||||
dispatch({ type: ActionType.refreshPlayList })
|
||||
setStatus(Status.params)
|
||||
}
|
||||
|
||||
const refreshRandomTones = () => {
|
||||
let foundRandomTones = getRandomTones( found.toneS, count )
|
||||
setFound({...found,
|
||||
randomTones: foundRandomTones
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<>
|
||||
<h1>Диктант pīnyīn</h1>
|
||||
<ListGroup>
|
||||
<ListGroup.Item disabled={status != Status.params}>
|
||||
<h2>{strings.selectInitiales}</h2>
|
||||
<Button variant={found.allInitiales ? "primary" : "outline-primary"}
|
||||
onClick= {()=>toggleAllInitiales()}>
|
||||
{found.allInitiales ? strings.unselectAll : strings.selectAll}
|
||||
</Button>
|
||||
{initials.map( (text, i) => <Button variant={isEnabled(found.initiales, text) ? "primary" : "outline-primary"}
|
||||
key={i} onClick={()=>toggleInitialsState(text)}>
|
||||
{text}
|
||||
</Button>
|
||||
)}
|
||||
<ButtonSet source={initials} color={BtnColor.blue} toggle={ToggleType.init}/>
|
||||
</ListGroup.Item>
|
||||
|
||||
<ListGroup.Item disabled={status != Status.params}>
|
||||
<h2>{strings.selectFinales}</h2>
|
||||
<Button variant={found.allfinales ? "success" : "outline-success"}
|
||||
onClick= {toggleAllFinales}>
|
||||
{found.allfinales ? strings.unselectAll : strings.selectAll}
|
||||
</Button>
|
||||
{finales.map( (fin, i) => <Button variant={isEnabled(found.finales, fin.finale) ? "success" : "outline-success"}
|
||||
key={i} onClick={()=>toggleFinalsState(fin.finale)}>
|
||||
{fin.caption}
|
||||
</Button>
|
||||
)}
|
||||
<ButtonSet source={finales} color={BtnColor.green} toggle={ToggleType.fin}/>
|
||||
</ListGroup.Item>
|
||||
|
||||
<ListGroup.Item disabled={status != Status.params}>
|
||||
<h2>{strings.params}</h2>
|
||||
<Form.Label>Количество слогов {count}</Form.Label>
|
||||
<Form.Range value={count} min={5} max={50} step={5} onChange={onchangecount}/>
|
||||
<Form.Label>Пауза между слогами {pause} секунд</Form.Label>
|
||||
<Form.Range value={pause} min={1} max={10} step={1} onChange={onchangepause}/>
|
||||
</ListGroup.Item>
|
||||
<Params/>
|
||||
</ListGroup.Item>
|
||||
<ListGroup.Item>
|
||||
{ status == Status.params &&
|
||||
<>
|
||||
Выбрано {found.initiales.length} инициалей, {found.finales.length} финалей, найдено {found.syllables.length} слогов, { found.toneS.length } тонов ,
|
||||
Выбрано {state.initiales!.length} инициалей, {state.finales!.length} финалей, найдено {state.foundSyllables!.length} слогов, { state.foundTones!.length } тонов ,
|
||||
<br/>
|
||||
<Button variant={isFound() ? "success" : "secondary"} size="lg" onClick={()=>beginDictation()} disabled={!isFound()}>
|
||||
{isFound() ? "Начать диктант!" : "Выберите инициали и финали" }
|
||||
|
|
@ -201,7 +103,7 @@ const refreshRandomTones = () => {
|
|||
}
|
||||
</ListGroup.Item>
|
||||
</ListGroup>
|
||||
</>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
104
src/Data.ts
104
src/Data.ts
|
|
@ -1,47 +1,69 @@
|
|||
import { Finale, Syllable, Tone } from "./types"
|
||||
import { SylPart, Syllable, Tone } from "./types"
|
||||
|
||||
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'
|
||||
export const initials: SylPart[] = [
|
||||
{ caption: '-', index: '-' },
|
||||
{ caption: 'y', index: 'y' },
|
||||
{ caption: 'w', index: 'w' },
|
||||
{ caption: 'b', index: 'b' },
|
||||
{ caption: 'p', index: 'p' },
|
||||
{ caption: 'm', index: 'm' },
|
||||
{ caption: 'f', index: 'f' },
|
||||
{ caption: 'd', index: 'd' },
|
||||
{ caption: 't', index: 't' },
|
||||
{ caption: 'n', index: 'n' },
|
||||
{ caption: 'l', index: 'l' },
|
||||
{ caption: 'g', index: 'g' },
|
||||
{ caption: 'k', index: 'k' },
|
||||
{ caption: 'h', index: 'h' },
|
||||
{ caption: 'j', index: 'j' },
|
||||
{ caption: 'q', index: 'q' },
|
||||
{ caption: 'x', index: 'x' },
|
||||
{ caption: 'zh', index: 'zh' },
|
||||
{ caption: 'ch', index: 'ch' },
|
||||
{ caption: 'sh', index: 'sh' },
|
||||
{ caption: 'r', index: 'r' },
|
||||
{ caption: 'z', index: 'z' },
|
||||
{ caption: 'c', index: 'c' },
|
||||
{ caption: 's', index: 's' },
|
||||
]
|
||||
|
||||
export const finales: Finale[] = [
|
||||
{ caption: 'ai', finale: 'ai' },
|
||||
{ caption: 'a', finale: 'a' },
|
||||
{ caption: 'ang', finale: 'ang' },
|
||||
{ caption: 'an', finale: 'an' },
|
||||
{ caption: 'ao', finale: 'ao' },
|
||||
{ caption: 'ei', finale: 'ei' },
|
||||
{ caption: 'e', finale: 'e' },
|
||||
{ caption: 'eng', finale: 'eng' },
|
||||
{ caption: 'en', finale: 'en' },
|
||||
{ caption: 'er', finale: 'er' },
|
||||
{ caption: 'ia', finale: 'ia' },
|
||||
{ caption: 'iang', finale: 'iang' },
|
||||
{ caption: 'ian', finale: 'ian' },
|
||||
{ caption: 'iao', finale: 'iao' },
|
||||
{ caption: 'ie', finale: 'ie' },
|
||||
{ caption: 'i', finale: 'i' },
|
||||
{ caption: 'ing', finale: 'ing' },
|
||||
{ caption: 'in', finale: 'in' },
|
||||
{ caption: 'io', finale: 'io' },
|
||||
{ caption: 'iong', finale: 'iong' },
|
||||
{ caption: 'iu', finale: 'iu' },
|
||||
{ caption: 'o', finale: 'o' },
|
||||
{ caption: 'ong', finale: 'ong' },
|
||||
{ caption: 'ou', finale: 'ou' },
|
||||
{ caption: 'uai', finale: 'uai' },
|
||||
{ caption: 'ua', finale: 'ua' },
|
||||
{ caption: 'uang', finale: 'uang' },
|
||||
{ caption: 'uan', finale: 'uan' },
|
||||
{ caption: 'ui', finale: 'ui' },
|
||||
{ caption: 'u', finale: 'u' },
|
||||
{ caption: 'un', finale: 'un' },
|
||||
{ caption: 'uo', finale: 'uo' },
|
||||
{ caption: 'üan', finale: 'van' },
|
||||
{ caption: 'üe', finale: 've' },
|
||||
{ caption: 'ü', finale: 'v' },
|
||||
{ caption: 'ün', finale: 'vn' }
|
||||
export const finales: SylPart[] = [
|
||||
{ caption: 'ai', index: 'ai' },
|
||||
{ caption: 'a', index: 'a' },
|
||||
{ caption: 'ang', index: 'ang' },
|
||||
{ caption: 'an', index: 'an' },
|
||||
{ caption: 'ao', index: 'ao' },
|
||||
{ caption: 'ei', index: 'ei' },
|
||||
{ caption: 'e', index: 'e' },
|
||||
{ caption: 'eng', index: 'eng' },
|
||||
{ caption: 'en', index: 'en' },
|
||||
{ caption: 'er', index: 'er' },
|
||||
{ caption: 'ia', index: 'ia' },
|
||||
{ caption: 'iang', index: 'iang' },
|
||||
{ caption: 'ian', index: 'ian' },
|
||||
{ caption: 'iao', index: 'iao' },
|
||||
{ caption: 'ie', index: 'ie' },
|
||||
{ caption: 'i', index: 'i' },
|
||||
{ caption: 'ing', index: 'ing' },
|
||||
{ caption: 'in', index: 'in' },
|
||||
{ caption: 'io', index: 'io' },
|
||||
{ caption: 'iong', index: 'iong' },
|
||||
{ caption: 'iu', index: 'iu' },
|
||||
{ caption: 'o', index: 'o' },
|
||||
{ caption: 'ong', index: 'ong' },
|
||||
{ caption: 'ou', index: 'ou' },
|
||||
{ caption: 'uai', index: 'uai' },
|
||||
{ caption: 'ua', index: 'ua' },
|
||||
{ caption: 'uang', index: 'uang' },
|
||||
{ caption: 'uan', index: 'uan' },
|
||||
{ caption: 'ui', index: 'ui' },
|
||||
{ caption: 'u', index: 'u' },
|
||||
{ caption: 'un', index: 'un' },
|
||||
{ caption: 'uo', index: 'uo' },
|
||||
{ caption: 'üan', index: 'van' },
|
||||
{ caption: 'üe', index: 've' },
|
||||
{ caption: 'ü', index: 'v' },
|
||||
{ caption: 'ün', index: 'vn' }
|
||||
]
|
||||
|
||||
export const syllables: Syllable[] = [
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ export type Syllable = {
|
|||
tones: string[]
|
||||
}
|
||||
|
||||
export type Finale = {
|
||||
export type SylPart = {
|
||||
caption: string,
|
||||
finale: string
|
||||
index: string
|
||||
}
|
||||
|
||||
export type Tone = {
|
||||
|
|
@ -26,4 +26,9 @@ export type Found = {
|
|||
syllables: Syllable[],
|
||||
toneS: Tone[],
|
||||
randomTones: Tone[]
|
||||
}
|
||||
|
||||
export enum BtnColor {
|
||||
blue = "primary",
|
||||
green = "success"
|
||||
}
|
||||
35
src/Utils.ts
35
src/Utils.ts
|
|
@ -1,12 +1,13 @@
|
|||
import { Tone } from "./types"
|
||||
import { syllables } from "./data"
|
||||
import { BtnColor, SylPart, Syllable } from "./types"
|
||||
|
||||
export const isEnabled = (arr: string[], caption: string): boolean => arr.some((btn) => btn==caption)
|
||||
export const isEnabled = (arr: SylPart[], find: string): boolean => arr.some((str) => str.index==find)
|
||||
|
||||
export const toggle = ( arr: string[], caption: string ):string[] => {
|
||||
if ( arr.some((btn) => btn==caption) )
|
||||
return arr.filter((el)=>el!==caption)
|
||||
export const toggle = ( arr: SylPart[], part: SylPart ):SylPart[] => {
|
||||
if ( arr.some((btn) => btn.index==part.index) )
|
||||
return arr.filter((el)=>el.index!==part.index)
|
||||
else
|
||||
return [ ...arr, caption]
|
||||
return [ ...arr, part]
|
||||
}
|
||||
|
||||
export const genrateRandomNumber = (min: number, max: number):number => {
|
||||
|
|
@ -16,14 +17,22 @@ export const genrateRandomNumber = (min: number, max: number):number => {
|
|||
return rnd
|
||||
}
|
||||
|
||||
export const getRandomTones = (fromTomes:Tone[], counT:number):Tone[] => {
|
||||
let _tone:Tone[] = []
|
||||
if (fromTomes.length==0) {
|
||||
export const getRandomArray = <T>(fromArray:T[], count:number):T[] => {
|
||||
let _tone:T[] = []
|
||||
if (fromArray.length==0) {
|
||||
return _tone
|
||||
}
|
||||
for( let x=0; x<counT; x++) {
|
||||
let randomN = genrateRandomNumber(0,fromTomes.length-1)
|
||||
_tone = [..._tone, fromTomes[randomN]]
|
||||
for( let x=0; x<count; x++) {
|
||||
let randomN = genrateRandomNumber(0,fromArray.length-1)
|
||||
_tone = [..._tone, fromArray[randomN]]
|
||||
}
|
||||
return _tone
|
||||
}
|
||||
}
|
||||
|
||||
export const GetSyllablesByInitAndFin = (initiales:SylPart[], finales: SylPart[]):Syllable[] => {
|
||||
let inits = initiales.map( (i) => i.index)
|
||||
let fins = finales.map( (i) =>i.index )
|
||||
return syllables.filter( syl => inits.includes(syl.initiale) && fins.includes(syl.finale) )
|
||||
}
|
||||
|
||||
export const Outlined = (color: BtnColor):string => `outline-${color}`
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
import { Button } from "react-bootstrap";
|
||||
import { useStateContext } from "./store";
|
||||
import { Outlined } from "./utils";
|
||||
import { ActionType, ToggleType } from "./reducer";
|
||||
import { strings } from "./strings";
|
||||
import { BtnColor, SylPart } from "./types";
|
||||
|
||||
export interface IBtnSerProps {
|
||||
source: SylPart[],
|
||||
color: BtnColor,
|
||||
toggle: ToggleType
|
||||
}
|
||||
|
||||
export const ButtonSet = (props: IBtnSerProps) => {
|
||||
const { state, dispatch } = useStateContext();
|
||||
const { source, color, toggle } = props;
|
||||
return <>
|
||||
<Button variant={ state.allEnabled!(toggle) ? color : Outlined(color) }
|
||||
onClick= {()=>dispatch({type: ActionType.toggleAll, payload: toggle})}>
|
||||
{state.allInitiales ? strings.unselectAll : strings.selectAll}
|
||||
</Button>
|
||||
{ source.map( (part, i) => <Button
|
||||
variant={ state.isEnabled!(toggle, part.index) ? color : Outlined(color) }
|
||||
key={i} onClick={()=>dispatch({
|
||||
type: ActionType.toggleOne,
|
||||
payload: { type: toggle, part: part }
|
||||
})}>
|
||||
{part.caption}
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
|
|
@ -3,9 +3,12 @@ import ReactDOM from 'react-dom/client'
|
|||
import App from './App.tsx'
|
||||
import './index.css'
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
import { StateProvider } from './store.js';
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
<StateProvider>
|
||||
<App />
|
||||
</StateProvider>
|
||||
</React.StrictMode>,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
import { ReactElement } from "react";
|
||||
import { useStateContext } from "./store";
|
||||
import { Form } from "react-bootstrap";
|
||||
import { ActionType } from "./reducer";
|
||||
import { strings } from "./strings";
|
||||
|
||||
export const Params = (): ReactElement => {
|
||||
|
||||
const { state, dispatch } = useStateContext();
|
||||
|
||||
const pausedispatcher = (e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
dispatch({ type: ActionType.setPause, payload: Number(e.target.value)})
|
||||
const countdispatcher = (e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
dispatch({ type: ActionType.setCount, payload: Number(e.target.value)})
|
||||
|
||||
return <>
|
||||
<h2>{strings.params}</h2>
|
||||
<Form.Label>Количество слогов {state.sylCount}</Form.Label>
|
||||
<Form.Range value={state.sylCount} min={5} max={50} step={5} onChange={countdispatcher}/>
|
||||
<Form.Label>Пауза между слогами {state.sylPause} секунд</Form.Label>
|
||||
<Form.Range value={state.sylPause} min={1} max={10} step={1} onChange={pausedispatcher}/>
|
||||
</>
|
||||
|
||||
}
|
||||
|
|
@ -1,23 +1,88 @@
|
|||
import { Found } from "./types";
|
||||
import { finales, initials, tones } from "./data";
|
||||
import { IState } from "./store";
|
||||
import { SylPart, Syllable, Tone } from "./types";
|
||||
import { GetSyllablesByInitAndFin, getRandomArray, toggle } from "./utils";
|
||||
|
||||
export enum ActionType {
|
||||
toggleInitiale, toggleFinale, toggleAllInitiales, toggleAllFinales
|
||||
toggleOne, toggleAll, refreshPlayList, setPause, setCount
|
||||
}
|
||||
|
||||
export type Action = { type: ActionType } | { type: ActionType };
|
||||
export enum ToggleType { init, fin }
|
||||
export type TogglePayload = { type: ToggleType, part: SylPart }
|
||||
|
||||
export const reducer = (state:Found, action:Action):Found => {
|
||||
export type Action = { type: ActionType, payload?: any };
|
||||
|
||||
const ProceedAllInitials = (state: IState):{ allInitiales:boolean, initiales: SylPart[], foundSyllables:Syllable[], foundTones: Tone[]} =>
|
||||
{
|
||||
let toggled = state.allInitiales ? [] as SylPart[] : initials
|
||||
let foundSyllables:Syllable[] = GetSyllablesByInitAndFin( toggled, state.finales )
|
||||
let foundTones = tones.filter( t => foundSyllables.some( syl => syl.tones.some( st => st===t.tone) ) )
|
||||
return {
|
||||
allInitiales: !state.allInitiales,
|
||||
initiales: toggled,
|
||||
foundSyllables: foundSyllables,
|
||||
foundTones: foundTones
|
||||
}
|
||||
}
|
||||
|
||||
const ProceedAllFinales = (state: IState):{ allfinales:boolean, finales: SylPart[], foundSyllables:Syllable[], foundTones: Tone[]} =>
|
||||
{
|
||||
let toggled = state.allfinales ? [] as SylPart[] : finales
|
||||
let foundSyllables:Syllable[] = GetSyllablesByInitAndFin( state.initiales, toggled )
|
||||
let foundTones = tones.filter( t => foundSyllables.some( syl => syl.tones.some( st => st===t.tone) ) )
|
||||
return {
|
||||
allfinales: !state.allfinales,
|
||||
finales: toggled,
|
||||
foundSyllables: foundSyllables,
|
||||
foundTones: foundTones
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const ProceedInitiale = (state: IState, index: SylPart):{ initiales: SylPart[], foundSyllables:Syllable[], foundTones: Tone[]} =>
|
||||
{
|
||||
let toggled = toggle(state.initiales,index)
|
||||
let foundSyllables:Syllable[] = GetSyllablesByInitAndFin( toggled, state.finales )
|
||||
let foundTones = tones.filter( t => foundSyllables.some( syl => syl.tones.some( st => st===t.tone) ) )
|
||||
return {
|
||||
initiales: toggled,
|
||||
foundSyllables: foundSyllables,
|
||||
foundTones: foundTones
|
||||
}
|
||||
}
|
||||
|
||||
const ProceedFinale = (state: IState, index: SylPart):{ finales: SylPart[], foundSyllables:Syllable[], foundTones: Tone[]} =>
|
||||
{
|
||||
let toggled = toggle(state.finales,index)
|
||||
let foundSyllables:Syllable[] = GetSyllablesByInitAndFin( state.initiales , toggled )
|
||||
let foundTones = tones.filter( t => foundSyllables.some( syl => syl.tones.some( st => st===t.tone) ) )
|
||||
return {
|
||||
finales: toggled,
|
||||
foundSyllables: foundSyllables,
|
||||
foundTones: foundTones
|
||||
}
|
||||
}
|
||||
|
||||
export const reducer = (state:IState, action:Action):IState => {
|
||||
switch (action.type) {
|
||||
case ActionType.setPause: return { ...state, sylPause: action.payload as number }
|
||||
case ActionType.setCount: return { ...state, sylCount: action.payload as number }
|
||||
case ActionType.refreshPlayList: return { ...state, randomTones: getRandomArray( state.foundTones, state.sylCount! ) }
|
||||
|
||||
case ActionType.toggleAll: {
|
||||
if (action.payload as ToggleType === ToggleType.init) return { ...state, ...ProceedAllInitials(state) }
|
||||
if (action.payload as ToggleType === ToggleType.fin) return { ...state, ...ProceedAllFinales(state) }
|
||||
return state
|
||||
}
|
||||
|
||||
case ActionType.toggleOne: {
|
||||
if ( (action.payload as TogglePayload).type === ToggleType.init)
|
||||
return { ...state, ...ProceedInitiale(state, (action.payload as TogglePayload).part ) }
|
||||
if ( (action.payload as TogglePayload).type === ToggleType.fin)
|
||||
return { ...state, ...ProceedFinale(state, (action.payload as TogglePayload).part ) }
|
||||
return state
|
||||
}
|
||||
|
||||
default: return state
|
||||
}
|
||||
}
|
||||
|
||||
export const defaultState:Found = {
|
||||
allfinales: false,
|
||||
allInitiales: false,
|
||||
finales: [],
|
||||
initiales: [],
|
||||
syllables: [],
|
||||
toneS: [],
|
||||
randomTones: []
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +1,54 @@
|
|||
import { Context, createContext, Dispatch, ReactElement, useContext, useReducer } from "react";
|
||||
import { reducer, defaultState, Action } from "./reducer"
|
||||
import { Found } from "./types";
|
||||
import { reducer, Action, ToggleType } from "./reducer"
|
||||
import { Syllable, SylPart, Tone } from "./types";
|
||||
import { isEnabled } from "./utils";
|
||||
|
||||
export interface IStore {
|
||||
state: Found
|
||||
dispatch?: Dispatch<Action>
|
||||
export interface IState {
|
||||
sylCount: number,
|
||||
sylPause: number,
|
||||
initiales: SylPart[],
|
||||
finales: SylPart[],
|
||||
allInitiales: boolean,
|
||||
allfinales: boolean,
|
||||
foundSyllables: Syllable[],
|
||||
foundTones: Tone[],
|
||||
randomTones: Tone[],
|
||||
allEnabled: (type: ToggleType) => false,
|
||||
isEnabled: (type: ToggleType, index: string) => false
|
||||
}
|
||||
|
||||
export const AppContext:Context<IStore> = createContext<IStore>({ state: defaultState, dispatch: () => null })
|
||||
export interface IStore {
|
||||
state: Partial<IState>
|
||||
dispatch: Dispatch<Action>
|
||||
}
|
||||
|
||||
export const defaultState:Object = {
|
||||
sylCount: 10,
|
||||
sylPause: 3,
|
||||
allfinales: false,
|
||||
allInitiales: false,
|
||||
finales: [] as SylPart[],
|
||||
initiales: [] as SylPart[],
|
||||
foundSyllables: [],
|
||||
foundTones: [],
|
||||
randomTones: [],
|
||||
allEnabled: function(type: ToggleType) {
|
||||
if ( type === ToggleType.init ) return (this as IState).allInitiales
|
||||
if ( type === ToggleType.fin ) return (this as IState).allfinales
|
||||
return false
|
||||
},
|
||||
isEnabled: function(type: ToggleType, index: string) {
|
||||
if ( type === ToggleType.init ) return isEnabled((this as IState).initiales!, index)
|
||||
if ( type === ToggleType.fin ) return isEnabled((this as IState).finales!, index)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export const AppContext:Context<IStore> = createContext<IStore>({ state: defaultState as IState, dispatch: () => null })
|
||||
|
||||
export const useStateContext = () => useContext(AppContext);
|
||||
|
||||
export const StateProvider = ({ children }: { children: ReactElement }) => {
|
||||
const [state, dispatch] = useReducer(reducer, defaultState);
|
||||
const [state, dispatch] = useReducer(reducer, defaultState as IState);
|
||||
return <AppContext.Provider value={{ state, dispatch }} children={children} />
|
||||
}
|
||||
Loading…
Reference in New Issue