Skip to content

Commit

Permalink
feat: make it possible to require symbols in words
Browse files Browse the repository at this point in the history
  • Loading branch information
OptimusCrime committed Dec 11, 2023
1 parent fedeeb9 commit bc789ac
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 40 deletions.
4 changes: 2 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import React, { useState } from 'react';
import { Layout } from './components';
import { Game, Settings } from './pages';
import { Pages } from './types';
import { getSettingsFromLocalStorage } from './utilities';
import { getSettingsFromLocalStorage, SettingData } from './utilities';

export const App = () => {
const [page, setPage] = useState<Pages>(Pages.Game);
const [settings, setSettings] = useState<string[]>(getSettingsFromLocalStorage());
const [settings, setSettings] = useState<SettingData[]>(getSettingsFromLocalStorage());

const AppWrapper = ({ children }: { children: React.ReactNode }) => (
<Layout setPage={setPage} page={page}>
Expand Down
10 changes: 8 additions & 2 deletions src/components/BrailleSymbol.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const BrailleDot = ({ enabled, padding }: { enabled: boolean; padding?: boolean

interface BrailleSymbolProps {
input: BRAILLE;
highlight?: 'success' | 'failure';
highlight?: 'success' | 'failure' | 'require';
text?: string;
}

Expand All @@ -40,7 +40,13 @@ export const BrailleSymbol = ({ input, highlight, text }: BrailleSymbolProps) =>
<div>
<div
className={`flex flex-col items-center justify-center mr-2 mb-4 rounded ${
!highlight ? '' : highlight === 'failure' ? 'bg-red-500' : 'bg-green-600'
!highlight
? ''
: highlight === 'failure'
? 'bg-red-500'
: highlight === 'success'
? 'bg-green-600'
: 'bg-green-900'
}`}
>
<BrailleSymbolRow padding={true}>
Expand Down
7 changes: 6 additions & 1 deletion src/pages/game/Game.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react';

import { SettingData } from '../../utilities';
import { WordListContainer } from '../../wordListContainer';
import { StartGame, Stats, TextField, WordCurrent, WordPrevious } from './components';
import { verifyCorrectSymbols } from './helpers';
Expand All @@ -9,7 +10,7 @@ import { GuessesStateProps, PreviousWordStateProps } from './stateProps';
const wordListContainer = new WordListContainer();

interface GameProps {
settings: string[];
settings: SettingData[];
}

export const Game = (props: GameProps) => {
Expand Down Expand Up @@ -41,9 +42,13 @@ export const Game = (props: GameProps) => {
};

useEffect(() => {
console.log('fired 1');
if (!gameStarted) {
console.log('fired 2');
wordListContainer.applySettings(settings).then(() => {
// Make the game playable after the wordlist has been loaded with applied filters
console.log('fired 3');
console.log(wordListContainer.getWordListSize());
setReady(true);
setCurrentWord(wordListContainer.getRandomWord());
});
Expand Down
23 changes: 20 additions & 3 deletions src/pages/game/components/WordPrevious.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,31 @@ const WordPreviousText = (props: WordPreviousCommonProps) => {
answer: answer,
});

const allCorrect = verifiedAnswer.every((item) => item.correct);
if (allCorrect) {
return (
<div className="flex flex-col justify-center mb-8 opacity-60">
<span className="text-green-600">{answer}</span>
</div>
);
}

return (
<div className="flex justify-center mb-8 opacity-60">
{verifiedAnswer.map((item) => {
{verifiedAnswer.map((item, index) => {
if (item.correct) {
return <span className="text-green-600">{item.character}</span>;
return (
<span className="text-green-600" key={index}>
{item.character}
</span>
);
}

return <span className={`text-red-500 ${item.underline ? 'underline' : ''}`}>{item.character}</span>;
return (
<span className={`text-red-500 ${item.underline ? 'underline' : ''}`} key={index}>
{item.character}
</span>
);
})}
</div>
);
Expand Down
10 changes: 5 additions & 5 deletions src/pages/settings/Settings.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import React from 'react';

import { LETTERS, NUMBERS, SIGNS } from '../../symbols/keys';
import { saveSettingsInLocalStorage } from '../../utilities';
import { saveSettingsInLocalStorage, SettingData } from '../../utilities';
import { SettingsSection } from './components';

interface SettingsProps {
goToGame: () => void;
settings: string[];
setSettings: React.Dispatch<React.SetStateAction<string[]>>;
settings: SettingData[];
setSettings: React.Dispatch<React.SetStateAction<SettingData[]>>;
}

const numberOfSymbolsSelectedForSection = (symbols: string[], settings: string[]): string =>
`${symbols.filter((symbol) => settings.includes(symbol)).length} / ${symbols.length}`;
const numberOfSymbolsSelectedForSection = (symbols: string[], settings: SettingData[]): string =>
`${symbols.filter((symbol) => settings.find((item) => item.character === symbol)).length} / ${symbols.length}`;

const sections: { symbols: string[]; heading: string }[] = [
{
Expand Down
56 changes: 35 additions & 21 deletions src/pages/settings/components/SettingSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import React from 'react';

import { BrailleSymbol } from '../../../components';
import { translate } from '../../../translator';
import { SettingData } from '../../../utilities';

interface SettingsSectionProps {
symbols: string[];
heading: string;
settings: string[];
setSettings: React.Dispatch<React.SetStateAction<string[]>>;
settings: SettingData[];
setSettings: React.Dispatch<React.SetStateAction<SettingData[]>>;
}

export const SettingsSection = ({ symbols, heading, settings, setSettings }: SettingsSectionProps) => (
Expand All @@ -16,25 +17,38 @@ export const SettingsSection = ({ symbols, heading, settings, setSettings }: Set
<h3 className="m-4">{heading}</h3>
</div>
<ul className="flex flex-wrap">
{symbols.map((symbol) => (
<div
className="pr-8 pb-8 cursor-pointer"
onClick={() => {
if (settings.includes(symbol)) {
// This is so dumb...
setSettings((prevState) => [...prevState.filter((value) => value !== symbol)]);
} else {
setSettings((prevState) => [...prevState, symbol]);
}
}}
>
<BrailleSymbol
input={translate(symbol)[0]}
highlight={settings.includes(symbol) ? 'success' : 'failure'}
text={symbol}
/>
</div>
))}
{symbols.map((symbol) => {
const highlight = settings.find((item) => item.character === symbol);

return (
<div
className="pr-8 pb-8 cursor-pointer"
onClick={() => {
const inSettings = settings.find((item) => item.character === symbol);
if (!inSettings) {
return setSettings((prevState) => [...prevState, { character: symbol, mode: 'include' }]);
}
if (inSettings.mode === 'include') {
return setSettings((prevState) => [
...prevState.filter((item) => item.character !== symbol),
{
character: symbol,
mode: 'require',
},
]);
}

return setSettings((prevState) => [...prevState.filter((item) => item.character !== symbol)]);
}}
>
<BrailleSymbol
input={translate(symbol)[0]}
highlight={!highlight ? 'failure' : highlight.mode === 'include' ? 'success' : 'require'}
text={symbol}
/>
</div>
);
})}
</ul>
</div>
);
9 changes: 7 additions & 2 deletions src/utilities/localStorageSettings.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
const KEY = 'LEARN_BRAILLE_SETTINGS';

export const getSettingsFromLocalStorage = (): string[] => {
export interface SettingData {
character: string;
mode: 'include' | 'require';
}

export const getSettingsFromLocalStorage = (): SettingData[] => {
const item = localStorage.getItem(KEY);
return item ? JSON.parse(item) : [];
};

export const saveSettingsInLocalStorage = (settings: string[]): void => {
export const saveSettingsInLocalStorage = (settings: SettingData[]): void => {
localStorage.setItem(KEY, JSON.stringify(settings));
};
32 changes: 28 additions & 4 deletions src/wordListContainer/wordListContainer.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SettingData } from '../utilities';
import wordsPayload from './words.json';

// TODO
Expand All @@ -6,23 +7,30 @@ import wordsPayload from './words.json';

export class WordListContainer {
private readonly lookup: string[];
private settings: string[] = [];
private settings: SettingData[] = [];
private filtered: string[] = [];
private filteredLength: number = 0;

constructor() {
this.lookup = wordsPayload.words;
}

async applySettings(settings: string[]) {
async applySettings(settings: SettingData[]) {
console.log(settings);
this.settings = settings;

// Remember to reset the list, dummy, otherwise you'll find all sort of weird bugs...
this.filtered = [];

const requiredSymbols = settings.filter((item) => item.mode === 'require');

// There has got to be a better way of doing this lmao
for (const word of this.lookup) {
const letters = word.split('');
let skip = false;
for (const letter of letters) {
if (!this.settings.includes(letter)) {
const inSettings = this.settings.find((item) => item.character === letter);
if (!inSettings) {
skip = true;
break;
}
Expand All @@ -33,7 +41,13 @@ export class WordListContainer {
}

if (!skip) {
this.filtered.push(word);
if (requiredSymbols.length === 0) {
this.filtered.push(word);
}

if (WordListContainer.containsAllRequireSettings(word, requiredSymbols)) {
this.filtered.push(word);
}
}
}

Expand All @@ -55,4 +69,14 @@ export class WordListContainer {

return this.filtered[Math.floor(Math.random() * this.filteredLength)];
}

private static containsAllRequireSettings(word: string, requiredSymbols: SettingData[]): boolean {
for (const requiredSymbol of requiredSymbols) {
if (!word.includes(requiredSymbol.character)) {
return false;
}
}

return true;
}
}

0 comments on commit bc789ac

Please sign in to comment.