diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index d97ec91..eefb149 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -27,8 +27,12 @@ function Router(props: {faro?: Faro}) { console.log(response) }) .then(userNameResponse => { - const userName = userNameResponse && userNameResponse.length > 0 ? userNameResponse : null; - dispatch(setUser(userName)) + if (userNameResponse && userNameResponse.length > 0) { + dispatch(setUser(userNameResponse)) + } else { + dispatch(unsetUser()) + } + }) .catch(() => { dispatch(unsetUser()) diff --git a/frontend/src/first-edition/domain-models/tulajdonsag.ts b/frontend/src/first-edition/domain-models/tulajdonsag.ts index 09f5f69..2cc3a08 100644 --- a/frontend/src/first-edition/domain-models/tulajdonsag.ts +++ b/frontend/src/first-edition/domain-models/tulajdonsag.ts @@ -1,7 +1,7 @@ import {TulajdonsagokFajjal} from "./faj"; import {KarakterInputs} from "./karakter"; -import {d6} from "../../shared/domain-models/kockak"; +import {RollAbility} from "../../shared/domain-models/rollAbility"; export enum Tulajdonsag { Ero = 't_ero', @@ -43,27 +43,10 @@ export function TulajdonsagLabel(tul: Tulajdonsag) : string { } } -function rollAbility() { - let min = 6; - let sum = 0; - let rolls: number[] = [] - for (let i = 0; i < 4; i++) { - const roll = d6(); - if (roll < min) { - min = roll; - } - sum += roll; - rolls.push(roll) - } - const result = sum - min; - console.log("Rolled: " + rolls + " got: " + result) - return result; -} - export function RollAllAbilities() : KarakterTulajdonsagok { const response = {...TulajdonsagDefaults} for (const key of TulajdonsagIDs) { - response[key] = rollAbility() + response[key] = RollAbility() } return response } diff --git a/frontend/src/second-edition/components/Tulajdonsagok2E.tsx b/frontend/src/second-edition/components/Tulajdonsagok2E.tsx index 5876068..00daf08 100644 --- a/frontend/src/second-edition/components/Tulajdonsagok2E.tsx +++ b/frontend/src/second-edition/components/Tulajdonsagok2E.tsx @@ -1,24 +1,33 @@ import React from "react"; import { - KarakterTulajdonsagok, - RollAllAbilities, Tulajdonsag2E, } from "../domain-models/tulajdonsag2E"; import TulajdonsagInput from "./TulajdonsagInput2E"; import {Faj2E, TulajdonsagModositokFajokra} from "../domain-models/faj2E"; +import {useDispatch, useSelector} from "react-redux"; +import {AppDispatch, RootState} from "../../store"; +import { + rollAbilities, + setBolcsesseg, + setEgeszseg, + setEro, + setIntelligencia, setKarizma, + setUgyesseg, + tulajdonsagSelector +} from "../domain-models/tulajdonsagSlice"; function Tulajdonsagok(props: { currentFaj: Faj2E, - tulajdonsagok: KarakterTulajdonsagok - changeTulajdonsagok: (tulajdonsagok: KarakterTulajdonsagok) => void }) { - const {currentFaj, tulajdonsagok, changeTulajdonsagok} = props + const {currentFaj} = props + const dispatch = useDispatch.withTypes()() + const tulajdonsagok = useSelector.withTypes()(tulajdonsagSelector) return <>
Tulajdonságok
@@ -27,7 +36,7 @@ function Tulajdonsagok(props: { currentValue={tulajdonsagok.t_ero} currentFaj={currentFaj} fajiModosito={TulajdonsagModositokFajokra(Tulajdonsag2E.Ero)} - changeValue={(val: number) => changeTulajdonsagok({...tulajdonsagok, t_ero: val})} + changeValue={(val: number) => dispatch(setEro(val))} tooLowError='Túl gyenge vagy, nem bírtad felemelni a kezed a jelentkezéshez!' tooHighError='Szét szakadtak az izmaid!' dataTestId={"t_ero"} @@ -37,7 +46,7 @@ function Tulajdonsagok(props: { currentValue={tulajdonsagok.t_ugy} currentFaj={currentFaj} fajiModosito={TulajdonsagModositokFajokra(Tulajdonsag2E.Ugyesseg)} - changeValue={(val: number) => changeTulajdonsagok({...tulajdonsagok, t_ugy: val})} + changeValue={(val: number) => dispatch(setUgyesseg(val))} tooLowError='Orrabuktál jelentkezés helyett!' tooHighError='Emberfeletti zsonglörködésedre záptojással válaszoltak a helyiek!' dataTestId={"t_ugy"} @@ -47,7 +56,7 @@ function Tulajdonsagok(props: { currentValue={tulajdonsagok.t_egs} currentFaj={currentFaj} fajiModosito={TulajdonsagModositokFajokra(Tulajdonsag2E.Egeszseg)} - changeValue={(val: number) => changeTulajdonsagok({...tulajdonsagok, t_egs: val})} + changeValue={(val: number) => dispatch(setEgeszseg(val))} tooLowError='Túl beteg vagy ahhoz, hogy kalandozni menj!' tooHighError='Kicsattanó egészségedet csak a diambroid állíthatja meg, minő véletlen, hogy pont az arcodba robbant...' dataTestId={"t_egs"} @@ -57,7 +66,7 @@ function Tulajdonsagok(props: { currentValue={tulajdonsagok.t_int} currentFaj={currentFaj} fajiModosito={TulajdonsagModositokFajokra(Tulajdonsag2E.Intelligencia)} - changeValue={(val: number) => changeTulajdonsagok({...tulajdonsagok, t_int: val})} + changeValue={(val: number) => dispatch(setIntelligencia(val))} tooLowError='Elfelejtetted, hogy mikor is kéne kalandozni indulni!' tooHighError='Ilyen tudás és logika birtokában mi szükséged van új információkra? Mindent le tudsz vezetni a már meglévő ismereteidből, és ezt azonnal beláttad.' dataTestId={"t_int"} @@ -67,7 +76,7 @@ function Tulajdonsagok(props: { currentValue={tulajdonsagok.t_bol} currentFaj={currentFaj} fajiModosito={TulajdonsagModositokFajokra(Tulajdonsag2E.Bolcsesseg)} - changeValue={(val: number) => changeTulajdonsagok({...tulajdonsagok, t_bol: val})} + changeValue={(val: number) => dispatch(setBolcsesseg(val))} tooLowError='Nem bírtál ellenállni a kíváncsiságodnak, hogy közelebbről is megvizsgáld a tőr hegyét. Nagyon közelről.' tooHighError='Hatalmas bölcsességedben beláttad a kalandozás veszélyeit és inkább más tevékenységbe fogtál.' dataTestId={"t_bol"} @@ -77,7 +86,7 @@ function Tulajdonsagok(props: { currentValue={tulajdonsagok.t_kar} currentFaj={currentFaj} fajiModosito={TulajdonsagModositokFajokra(Tulajdonsag2E.Karizma)} - changeValue={(val: number) => changeTulajdonsagok({...tulajdonsagok, t_kar: val})} + changeValue={(val: number) => dispatch(setKarizma(val))} tooLowError='Mintha taszítanád az embereket, sose sikerült kalandozó csapatot találnod.' tooHighError='Az ellenkező nem tagjai nem engedték, hogy útnak indulj.' dataTestId={"t_kar"} diff --git a/frontend/src/second-edition/domain-models/tamadas_bonusz.test.ts b/frontend/src/second-edition/domain-models/tamadas_bonusz.test.ts new file mode 100644 index 0000000..64e2848 --- /dev/null +++ b/frontend/src/second-edition/domain-models/tamadas_bonusz.test.ts @@ -0,0 +1,82 @@ +import {Osztaly2E} from "./osztaly2E"; +import {CelzoTB, KozelharciTB, TamadasBonusz} from "./tamadas_bonusz"; +import {KarakterTulajdonsagok, Modifier} from "./tulajdonsag2E"; +import {Szintlepes} from "./szintlepes"; +import {d6} from "../../shared/domain-models/kockak"; + +describe('Tamadas Bonusz calculation', () => { + + describe('Base Tamadas Bonusz', () => { + test.each([ + [Osztaly2E.Harcos, 1, [1]], + [Osztaly2E.Amazon, 6, [6,1]], + [Osztaly2E.Ijasz, 12, [10,7,2]], + [Osztaly2E.Tolvaj, 1, [0]], + [Osztaly2E.Tolvaj, 9, [6,1]], + [Osztaly2E.Pap, 12, [8,3]], + [Osztaly2E.Varazslo, 1, [0]], + [Osztaly2E.Varazslo, 12, [6, 1]], + [Osztaly2E.Illuzionista, 5, [2]], + ])('%s has a TB of %i at level %i', (osztaly: Osztaly2E, szint: number, expectedTB: number[]) => { + const actual = TamadasBonusz(osztaly, szint) + expect(actual).toEqual(expectedTB) + }) + }); + + describe('CelzoTB', () => { + const szint = 10 + const tulajdonsagok: KarakterTulajdonsagok = { + t_ugy: 17, + t_kar: 3, + t_bol: 3, + t_egs: 3, + t_ero: 3, + t_int: 3, + } + const modifier = Modifier(tulajdonsagok.t_ugy) + + it('should be equal base + ugyesseg modifier', () => { + const osztaly = Osztaly2E.Tolvaj + const szintlepesek = Array.from({length: szint}, + () => ({ osztaly, HProll: d6(), })) + const base = TamadasBonusz(osztaly, szint) + const expected = base.map(x => x + modifier) + + const actual = CelzoTB({ + szintlepesek, + tulajdonsagok + }) + + expect(actual).toEqual(expected) + }); + }); + + describe('KozelharciTB', () => { + const szint = 10 + const tulajdonsagok: KarakterTulajdonsagok = { + t_ugy: 3, + t_kar: 3, + t_bol: 3, + t_egs: 3, + t_ero: 3, + t_int: 3, + } + const modifier = Modifier(tulajdonsagok.t_ero) + + it('should be equal base + ero modifier', () => { + const osztaly = Osztaly2E.Pap + const szintlepesek: Szintlepes[] = Array.from({length: szint}, + () => ({ osztaly, HProll: 1, })); + const base = TamadasBonusz(osztaly, szint) + const expected = base.map(x => x + modifier) + + const actual = KozelharciTB({ + szintlepesek, + tulajdonsagok + }) + + expect(actual).toEqual(expected) + }); + }); + +}); \ No newline at end of file diff --git a/frontend/src/second-edition/domain-models/tulajdonsag2E.ts b/frontend/src/second-edition/domain-models/tulajdonsag2E.ts index 77e5459..87c1706 100644 --- a/frontend/src/second-edition/domain-models/tulajdonsag2E.ts +++ b/frontend/src/second-edition/domain-models/tulajdonsag2E.ts @@ -1,6 +1,6 @@ -import {d6} from "../../shared/domain-models/kockak"; import {Karakter2E} from "./karakter2E"; import {TulajdonsagokFajjal} from "./faj2E"; +import {RollAbility} from "../../shared/domain-models/rollAbility"; export enum Tulajdonsag2E { Ero = 't_ero', @@ -42,27 +42,10 @@ export function TulajdonsagLabel(tul: Tulajdonsag2E) : string { } } -function rollAbility() { - let min = 6; - let sum = 0; - let rolls: number[] = [] - for (let i = 0; i < 4; i++) { - const roll = d6(); - if (roll < min) { - min = roll; - } - sum += roll; - rolls.push(roll) - } - const result = sum - min; - console.log("Rolled: " + rolls + " got: " + result) - return result; -} - export function RollAllAbilities() : KarakterTulajdonsagok { const response = {...TulajdonsagDefaults} for (const key of TulajdonsagIDs) { - response[key] = rollAbility() + response[key] = RollAbility() } return response } diff --git a/frontend/src/second-edition/domain-models/tulajdonsagSlice.ts b/frontend/src/second-edition/domain-models/tulajdonsagSlice.ts new file mode 100644 index 0000000..66c3164 --- /dev/null +++ b/frontend/src/second-edition/domain-models/tulajdonsagSlice.ts @@ -0,0 +1,37 @@ +import {createSlice} from "@reduxjs/toolkit"; +import {RollAllAbilities, TulajdonsagDefaults} from "./tulajdonsag2E"; + +export const tulajdonsagSlice = createSlice({ + name: "tulajdonsag2E", + initialState: TulajdonsagDefaults, + reducers: { + rollAbilities: (state) => { + state = RollAllAbilities() + return state; + }, + setEro: (state, action: {payload: number}) => { + state.t_ero = action.payload; + }, + setUgyesseg: (state, action: {payload: number}) => { + state.t_ugy = action.payload; + }, + setEgeszseg: (state, action: {payload: number}) => { + state.t_egs = action.payload; + }, + setIntelligencia: (state, action: {payload: number}) => { + state.t_int = action.payload; + }, + setBolcsesseg: (state, action: {payload: number}) => { + state.t_bol = action.payload; + }, + setKarizma: (state, action: {payload: number}) => { + state.t_kar = action.payload; + }, + }, +}) + +export const { rollAbilities, setEro, setUgyesseg, setEgeszseg, setIntelligencia, setBolcsesseg, setKarizma } = tulajdonsagSlice.actions + +export const tulajdonsagSelector = tulajdonsagSlice.selectSlice; + +export default tulajdonsagSlice.reducer \ No newline at end of file diff --git a/frontend/src/second-edition/pages/CreateCharacter2E.tsx b/frontend/src/second-edition/pages/CreateCharacter2E.tsx index b7a93dd..4bfad98 100644 --- a/frontend/src/second-edition/pages/CreateCharacter2E.tsx +++ b/frontend/src/second-edition/pages/CreateCharacter2E.tsx @@ -2,7 +2,6 @@ import React, {useState} from 'react' import {useLoaderData, useNavigate, useParams} from "react-router-dom"; import {OverlayTrigger, Toast, ToastContainer} from "react-bootstrap"; import {ChangeLvl1Osztaly, DefaultKarakter, Karakter2E} from "../domain-models/karakter2E"; -import {KarakterTulajdonsagok} from "../domain-models/tulajdonsag2E"; import FajSelector2E from "../components/FajSelector2E"; import Tulajdonsagok2E from "../components/Tulajdonsagok2E"; import OsztalySelector2E from "../components/OsztalySelector2E"; @@ -34,6 +33,7 @@ import {useSelector} from "react-redux"; import {RootState} from "../../store"; import {userSelector} from "../../shared/domain-models/userSlice"; import {SaveModal} from "../../shared/components/SaveModal"; +import {tulajdonsagSelector} from "../domain-models/tulajdonsagSlice"; function CreateCharacter2E(props: { faro?: Faro @@ -51,6 +51,7 @@ function CreateCharacter2E(props: { const navigate = useNavigate(); const [karakter, setKarakter] = useState(initialKarakterInputs) + karakter.tulajdonsagok = useSelector.withTypes()(tulajdonsagSelector) const tulajdonsagokFajjal = TulajdonsagokFajjal(karakter.tulajdonsagok, karakter.faj) const changeKepzettseg = (k: KepzettsegId[]) => setKarakter({...karakter, kepzettsegek: k}) const changeTolvajKepzettseg = (tk?: KepzettsegId[]) => setKarakter({...karakter, tolvajKepzettsegek: tk}) @@ -143,11 +144,6 @@ function CreateCharacter2E(props: {
setKarakter({ - ...karakter, - tulajdonsagok: tul - })} />
diff --git a/frontend/src/shared/contexts/UserContext.ts b/frontend/src/shared/contexts/UserContext.ts deleted file mode 100644 index 273f05f..0000000 --- a/frontend/src/shared/contexts/UserContext.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Fetched } from "../models/Fetched"; -import React from "react"; - -export const userDefaults: Fetched = { - state: "not-started", - data: null, -} - -export const UserContext = React.createContext(userDefaults) -UserContext.displayName = "UserEmailContext"; diff --git a/frontend/src/shared/domain-models/rollAbility.test.ts b/frontend/src/shared/domain-models/rollAbility.test.ts new file mode 100644 index 0000000..a9f31f5 --- /dev/null +++ b/frontend/src/shared/domain-models/rollAbility.test.ts @@ -0,0 +1,31 @@ +import {RollAbility} from "./rollAbility"; + +describe('RollAbility', () => { + it('returns 3 if all rolls are 1', () => { + const actual = RollAbility({ + d6: () => 1 + }) + expect(actual).toEqual(3) + }) + it('returns 18 if at least 3 rolls are 6', () => { + let counter = 0; + const actual = RollAbility({ + d6: () => { + return ++counter > 1 ? 6 : 1; + } + }) + expect(actual).toEqual(18) + }) + it('sums up rolls are removes the smallest roll', () => { + let counter = 1; + const actual = RollAbility({ + d6: () => { + if (counter++ > 4) { + throw "Cheater! You can only roll 4 times!" + } + return counter + } + }) + expect(actual).toEqual(12) + }) +}) \ No newline at end of file diff --git a/frontend/src/shared/domain-models/rollAbility.ts b/frontend/src/shared/domain-models/rollAbility.ts new file mode 100644 index 0000000..9b02d67 --- /dev/null +++ b/frontend/src/shared/domain-models/rollAbility.ts @@ -0,0 +1,21 @@ +import {d6} from "./kockak"; + +export function RollAbility(dependencies: { + d6: () => number +} = {d6}) { + const { d6: roll6 } = dependencies; + let min = 6; + let sum = 0; + let rolls: number[] = [] + for (let i = 0; i < 4; i++) { + const roll = roll6(); + if (roll < min) { + min = roll; + } + sum += roll; + rolls.push(roll) + } + const result = sum - min; + console.log("Rolled: " + rolls + " got: " + result) + return result; +} \ No newline at end of file diff --git a/frontend/src/shared/domain-models/userSlice.ts b/frontend/src/shared/domain-models/userSlice.ts index c78b889..29795ec 100644 --- a/frontend/src/shared/domain-models/userSlice.ts +++ b/frontend/src/shared/domain-models/userSlice.ts @@ -6,19 +6,22 @@ export const userSlice = createSlice({ name: 'user', initialState: { state: "not-started" as LoadingState, - email: null, + email: null as string | null, }, reducers: { load: (state) => { state.state = "loading" + return state }, - setUser: (state, action) => { + setUser: (state, action: {payload: string}) => { state.state = "finished" state.email = action.payload + return state }, unsetUser: (state) => { state.state = "finished" state.email = null + return state } }, }) diff --git a/frontend/src/store.ts b/frontend/src/store.ts index b93b301..74db900 100644 --- a/frontend/src/store.ts +++ b/frontend/src/store.ts @@ -1,9 +1,11 @@ import { configureStore } from "@reduxjs/toolkit" import userReducer from './shared/domain-models/userSlice' +import tulajdonsag2eReducer from './second-edition/domain-models/tulajdonsagSlice'; const store = configureStore({ reducer: { - user: userReducer + user: userReducer, + tulajdonsag2E: tulajdonsag2eReducer }, });