Skip to content

Commit

Permalink
Merge pull request #85 from Marvin-Brouwer/78-undo
Browse files Browse the repository at this point in the history
78 undo
  • Loading branch information
Marvin-Brouwer authored Oct 26, 2023
2 parents 1dc2b25 + 1eafc70 commit 1797ee8
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 66 deletions.
10 changes: 5 additions & 5 deletions src/app/src/components/game/game.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ import { KeyboardContextProvider } from '../../context/keyboardContext'

const round = createSignal(1)
const scorePad = useScorePad()
const [getScorePad] = scorePad
const { getScorePad } = scorePad

const createPlayerNameSignal = () => {

const playerName = createSignal('')
const [getPlayerName, setPlayerName] = playerName

onMount(() => {
const playerName = localStorage.getItem('playerName')
setPlayerName(playerName ?? '')

createEffect(() => {
localStorage.setItem('playerName', getPlayerName())
}, getPlayerName)
Expand All @@ -28,9 +28,9 @@ const createPlayerNameSignal = () => {
export const Game: Component = () => {

const playerName = createPlayerNameSignal()

return (<KeyboardContextProvider>
<ScoreCard playerName={playerName} round={round} getScorePad={getScorePad} />
<ScoreInputDialog round={round} scorePad={scorePad} />
<ScoreInputDialog round={round} scorePad={scorePad} />
</KeyboardContextProvider>)
}
15 changes: 14 additions & 1 deletion src/app/src/components/scoreInput/scoreInput.css
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,18 @@ section.score-input .set-score button.enter-button {
right: 1.4em;
bottom: 1.3em;
}
section.score-input .set-score button.reset-button {
section.score-input .set-score button.undo-button {
font-size: 1.5ex;
position: absolute;
right: 2.8em;
bottom: 1.38em;
}
section.score-input .set-score button.reset-button {
font-size: 1.5ex;
position: absolute;
right: 3.9em;
bottom: 1.38em;
}

.set-score button.die-button svg {
top: calc(var(--dice-padding) * 3);
Expand All @@ -70,6 +76,13 @@ section.score-input .set-score button.reset-button {
/* right: calc(var(--dice-padding) * 2); */
width: calc(100% - (var(--dice-padding) * 4));
}
.set-score button.die-button.undo-button svg {
top: calc(var(--dice-padding) * 3.5);
/* bottom: calc(var(--dice-padding) * 2); */
left: calc(var(--dice-padding) * .8);
/* right: calc(var(--dice-padding) * 2); */
width: calc(100% - (var(--dice-padding) * 2));
}

section.title-section{
position: fixed;
Expand Down
28 changes: 14 additions & 14 deletions src/app/src/components/scoreInput/scoreInput.state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { isScoreApplicableToField } from '../../game/score/scoreFieldValidator'
import { DialogState, createDialogSignal } from '../hacks/dialog'

export type ScoreInput = [
one: DieValue | undefined,
two: DieValue | undefined,
three: DieValue | undefined,
one: DieValue | undefined,
two: DieValue | undefined,
three: DieValue | undefined,
four: DieValue | undefined ,
five: DieValue | undefined
]
Expand Down Expand Up @@ -49,9 +49,9 @@ export type ScoreInputStateProps = {
const createEmptyScore = () => (
[ undefined, undefined, undefined, undefined, undefined ] as ScoreInput
)
export function createScoreInputState({
scorePad: [,setScorePad],
round:[,setRound]
export function createScoreInputState({
scorePad: { applyScore },
round:[,setRound]
}: ScoreInputStateProps): ScoreInputState {

const step = createSignal<'closed' | 'diceSelector' | 'rowSelector' | 'flushDiscard'>('closed')
Expand Down Expand Up @@ -92,7 +92,7 @@ export function createScoreInputState({
})
}


function getSignalForDie(die: keyof ScoreInput) {
const accessorProxy = () => getScoreForDie(die)
const setterProxy = ((handler) => {
Expand All @@ -105,11 +105,11 @@ export function createScoreInputState({

return [accessorProxy, setterProxy] as Signal<DieValue | undefined>
}

const getAllDiceSet = createMemo(
() => {
return Array.from(getScoreInput()).every(value => value !== undefined) === true
},
},
getScoreInput
)
const diceSelector: ScoreInputState['diceSelector'] = {
Expand Down Expand Up @@ -152,19 +152,19 @@ export function createScoreInputState({
if (isScoreApplicableToField(scoreValue, row)){

if (row !== 'flush') {
setScorePad({
applyScore({
field: row,
score: scoreValue
})
} else {
setScorePad({
applyScore({
field: row,
score: scoreValue,
discard: getFlushDiscard()!
})
}
} else{
setScorePad({
applyScore({
field: row,
score: discard()
})
Expand All @@ -181,7 +181,7 @@ export function createScoreInputState({

function nextStep() {
const currentStep = getStep()

if (currentStep === 'diceSelector') {
diceSelectorDialogSignal.closeDialog(false)
rowSelectorDialogSignal.openDialog()
Expand All @@ -192,7 +192,7 @@ export function createScoreInputState({
flushDiscardDialogSignal.openDialog()
return setStep('flushDiscard')
}

resetAndClose()
}
return {
Expand Down
25 changes: 23 additions & 2 deletions src/app/src/components/scoreInput/scoreInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import getTrumpetAudio from '../../audio/383154__profcalla__re_frullato_tromba.m
import getPartyHornAudio from '../../audio/170583__audiosmedia__party-horn.wav?blob'

import PlusIcon from '../../icons/iconmonstr-plus-lined.svg?raw'
import UndoIcon from '../../icons/iconmonstr-refresh-5.svg?raw'
import ResetIcon from '../../icons/iconmonstr-trash-can-lined.svg?raw'

import { Component, onCleanup } from 'solid-js'
Expand All @@ -25,13 +26,20 @@ type Props = ScoreInputStateProps
export const ScoreInputDialog: Component<Props> = (props) => {

const inputState = createScoreInputState(props)
const [getScorePad] = props.scorePad
const [getRound] = props.round
const { getScorePad, canUndoScore, undoScore } = props.scorePad
const [getRound, setRound] = props.round

// Put into memo to force rerender on change
const gameEnded = createMemo(() => getRound() > roundAmount, getRound)
const getAudioContext = createAudioContextAccessor()

const undoDisabled = createMemo(() => gameEnded() || !canUndoScore(), [gameEnded, canUndoScore])
const undoLastTurn = () => {
if (!canUndoScore()) return
setRound((prev) => prev -1)
undoScore()
}

const ballonPopAudio = getBalloonPopAudio()
const trumpetAudio = getTrumpetAudio()
const partyHornAudio = getPartyHornAudio()
Expand Down Expand Up @@ -96,6 +104,19 @@ export const ScoreInputDialog: Component<Props> = (props) => {
inputState.open()
}}
/>
<DieButton
classList={{
'die-button': true,
'undo-button': true,
'game-ended': gameEnded()
}}
value={<span class="illustration" innerHTML={UndoIcon} /> as Element}
description="Undo last turn" disabled={undoDisabled} // todo
onClick={() => {
if (confirm('Are you sure you wan\'t to reset to your previous round?'))
undoLastTurn()
}}
/>
<DieButton
classList={{
'die-button': true,
Expand Down
24 changes: 12 additions & 12 deletions src/app/src/game/score/scoreApplicationProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import { isScoreApplicableToField } from './scoreFieldValidator'
import { InvalidScoreApplicationError } from './invalidScoreApplicationError'
import { discard as discardScore } from './score'

type SimpleScoreApplication =
type SimpleScoreApplication =
| { field: ScoreField, score: ValidScore | DiscardedScore }
type DiscardFlushApplication =
type DiscardFlushApplication =
| { field: 'flush', score: DiscardedScore}
type FlushApplication =
type FlushApplication =
| { field: 'flush', score: ValidScore, discard: Exclude<ScoreField, 'flush'> }

export type ScoreApplication =
export type ScoreApplication =
| SimpleScoreApplication
| DiscardFlushApplication
| FlushApplication
Expand All @@ -25,11 +25,11 @@ function isDiscardedFlushApplication(application: ScoreApplication): application

return application.field === 'flush' && isDiscarded(application.score)
}

export function applyScore(scorePad: Readonly<ScorePad>, application: ScoreApplication) {

console.log('applyScore', application)
const { field, score } = application
const { field, score } = application

if (!isScoreApplicableToField(score, field))
throw InvalidScoreApplicationError.invalidScoreApplication(scorePad, application)
Expand All @@ -42,12 +42,12 @@ export function applyScore(scorePad: Readonly<ScorePad>, application: ScoreAppli
}

return processSimpleScore(scorePad, application)

}

function processFlushAppendScore(scorePad: Readonly<ScorePad>, application: FlushApplication): ScorePad {

const { field, score, discard } = application
const { field, score, discard } = application

const scoreField = scorePad[field]

Expand All @@ -56,20 +56,20 @@ function processFlushAppendScore(scorePad: Readonly<ScorePad>, application: Flus
throw InvalidScoreApplicationError.flushDiscarded(scorePad, application)

const currentFlushValue = scorePad.flush
if (!discard && !isDiscarded(currentFlushValue) && currentFlushValue.length > 0)
if (!discard && !isDiscarded(currentFlushValue) && currentFlushValue.length > 0)
throw InvalidScoreApplicationError.noDiscardOnFlush(scorePad, application)

if (scorePad[discard] !== undefined)
throw InvalidScoreApplicationError.scoreAlreadyApplied(scorePad, application)

return Object.assign({}, scorePad, {
return Object.assign({}, scorePad, {
[field]: [...scoreField, score],
[discard]: discardScore()
})
}
function processFlushDiscardScore(scorePad: Readonly<ScorePad>, application: DiscardFlushApplication): ScorePad {

const { field, score } = application
const { field, score } = application

if (isDiscarded(scorePad[field]))
throw InvalidScoreApplicationError.scoreAlreadyApplied(scorePad, application)
Expand All @@ -80,7 +80,7 @@ function processFlushDiscardScore(scorePad: Readonly<ScorePad>, application: Dis
}
function processSimpleScore(scorePad: Readonly<ScorePad>, application: SimpleScoreApplication): ScorePad {

const { field, score } = application
const { field, score } = application

if (scorePad[field] !== undefined)
throw InvalidScoreApplicationError.scoreAlreadyApplied(scorePad, application)
Expand Down
33 changes: 24 additions & 9 deletions src/app/src/game/score/useScorePad.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
import { createSignal, Accessor } from 'solid-js'
import { createSignal, Accessor, createMemo } from 'solid-js'
import { ScorePad, createScorePad } from './scorePad'
import { ScoreApplication, applyScore } from './scoreApplicationProcessor'

export type ScorePadAccessor = Accessor<Readonly<ScorePad>>;
export type ScorePadModifier = (score: ScoreApplication) => (Readonly<ScorePad> | void)

export type ScorePadSignal = [state: ScorePadAccessor, stateSetter: ScorePadModifier];
export type ScorePadSignal = {
getScorePad: ScorePadAccessor, applyScore: ScorePadModifier,
canUndoScore: Accessor<boolean>, undoScore: () => void
};

export function useScorePad(): ScorePadSignal {

const [getUndoState, setUndoState] = createSignal<ScorePad | undefined>(undefined)
const [currentScorePad, setScorePad] = createSignal<ScorePad>(createScorePad())

function modifyScorePad(application: ScoreApplication) {
setScorePad(state => {
const test = applyScore(state, application)
console.log('currentScore', test)
return test
})
setUndoState(cloneScorePad(currentScorePad()))
setScorePad(state => applyScore(state, application))
}

const canUndoScore = createMemo(() => getUndoState() !== undefined, getUndoState)
function undoScore() {
const newScore = cloneScorePad(getUndoState()!)
console.log('undo', newScore)
setScorePad(newScore)
setUndoState(undefined)
}
return [currentScorePad, modifyScorePad]

return { getScorePad: currentScorePad, applyScore: modifyScorePad, canUndoScore, undoScore }
}

function cloneScorePad(scorePad: Readonly<ScorePad>): Readonly<ScorePad> {

return Object.assign({}, scorePad)
}
2 changes: 2 additions & 0 deletions src/app/src/icons/iconmonstr-refresh-5.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 10 additions & 4 deletions src/app/src/layouts/content.css
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ a.link-button {
justify-content: flex-start;
align-items: center;
}
a.link-button .die{
a.link-button .die{
margin-right: 1ex;
font-size: 2.5ex;
}
Expand All @@ -85,7 +85,7 @@ a.link-button:focus-visible:focus-within {
color: var(--theme-foreground-hover);
}

figure.add-score-button {
figure.button-illustration {
background-color: var(--theme-background-secondary);
border-width: 1px;
border-style: solid;
Expand All @@ -99,10 +99,16 @@ figure.add-score-button {
flex-direction: column;
align-items: center;
}
figure.add-score-button .die {
figure.button-illustration .die {
font-size: 4ex;
}
figure.add-score-button figcaption {
figure.button-illustration.undo-button .die svg {
width: 60%;
height: 60%;
left: 18%;
top: 27%;
}
figure.button-illustration figcaption {
font-size: .8ex;
margin-bottom: 2ex;
color: var(--theme-foreground-hint);
Expand Down
Loading

0 comments on commit 1797ee8

Please sign in to comment.