Skip to content

Commit

Permalink
Rewrite large portion of redux
Browse files Browse the repository at this point in the history
* now only 2 slices, gameState and stacks
  • Loading branch information
tswaters committed Jul 12, 2020
1 parent 2a25c1c commit 3b701e2
Show file tree
Hide file tree
Showing 24 changed files with 541 additions and 941 deletions.
3 changes: 1 addition & 2 deletions src/ts/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import * as React from 'react'
import { Provider } from 'react-redux'

import configStore from '../store'
import { initialize } from '../redux/actions'
import { ThunkDispatch } from '../redux'
import { ThunkDispatch, initialize } from '../redux/thunks'
import Container from './Container'

const App: React.FC = () => {
Expand Down
40 changes: 16 additions & 24 deletions src/ts/components/Container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,28 @@ import { hot } from 'react-hot-loader/root'
import { useDispatch, useSelector } from 'react-redux'
import FireworksComponent from './Fireworks'
import { newGame, score, version, switchScoreType } from '../../styles/cards.css'
import { initialize } from '../redux/actions'
import { getScore } from '../redux/selectors'
import { initialize } from '../redux/thunks'
import { getScore, getScoringType } from '../redux/selectors'
import { undo, redo } from '../redux/undoable'
import { ScoringType } from '../redux/globals'
import { ScoringType } from '../redux/game-state'
import GameCanvas from './GameCanvas'
import StackElement from './StackElement'

import { getStock, getFoundation, getTableau, getWaste } from '../redux/selectors'
import { getDraws, getShowing, getAllStacks } from '../redux/selectors'

const Container: React.FC = () => {
const dispatch = useDispatch()
const { score: currentScore, scoringType } = useSelector(getScore)
const { stacks: stock, draws } = useSelector(getStock)
const { stacks: waste, showing } = useSelector(getWaste)
const { stacks: tableau } = useSelector(getTableau)
const { stacks: foundation } = useSelector(getFoundation)
const stacks = useSelector(getAllStacks)
const currentScore = useSelector(getScore)
const scoringType = useSelector(getScoringType)
const draws = useSelector(getDraws)
const showing = useSelector(getShowing)

const otherGameType = React.useMemo(
() => (scoringType === ScoringType.vegas ? ScoringType.regular : ScoringType.vegas),
[scoringType],
)
const { otherGameType, switchLabel } = React.useMemo(() => {
const otherGameType = scoringType === ScoringType.vegas ? ScoringType.regular : ScoringType.vegas
const switchLabel = `Switch to ${ScoringType[otherGameType]}`
return { otherGameType, switchLabel }
}, [scoringType])

const handleNewGameClick = React.useCallback(() => {
dispatch(initialize())
Expand Down Expand Up @@ -67,17 +68,8 @@ const Container: React.FC = () => {
</label>
</div>
<GameCanvas>
{stock.map((stack) => (
<StackElement key={stack.index} stack={stack} draws={draws} />
))}
{waste.map((stack) => (
<StackElement key={stack.index} stack={stack} showing={showing} />
))}
{tableau.map((stack) => (
<StackElement key={stack.index} stack={stack} />
))}
{foundation.map((stack) => (
<StackElement key={stack.index} stack={stack} />
{stacks.map((stack) => (
<StackElement key={`${stack.type}-${stack.index}`} stack={stack} showing={showing} draws={draws} />
))}
</GameCanvas>
<div className={version}>{process.env.version}</div>
Expand Down
2 changes: 1 addition & 1 deletion src/ts/components/Fireworks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { getFoundation } from '../redux/selectors'
const Fireworks: React.FC = () => {
const ref = React.useRef<HTMLDivElement>(null)
const fireworksObj = React.useRef<FireworksCanvas>()
const { stacks: foundation } = useSelector(getFoundation)
const foundation = useSelector(getFoundation)
const active = foundation.every((stack) => stack.cards.length === 13)
const display = active ? '' : 'none'

Expand Down
2 changes: 1 addition & 1 deletion src/ts/components/StackElement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { GameCtx } from './GameCanvas'
import { drawStack } from '../drawing/Stack'
import { Stack, StackDirection, StackCard } from '../lib/Card'
import { useDispatch } from 'react-redux'
import { clickCard, doubleClickCard } from '../redux/actions'
import { clickCard, doubleClickCard } from '../redux/thunks'
import { Drawable, Point } from '../drawing/Common'

type DrawableStack = Drawable & {
Expand Down
2 changes: 1 addition & 1 deletion src/ts/lib/Card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export enum StackType {

export type Stack = {
cards: StackCard[]
selection?: Card
selection: Card | null
type: StackType
index: number
}
Expand Down
30 changes: 0 additions & 30 deletions src/ts/lib/persist.ts

This file was deleted.

115 changes: 20 additions & 95 deletions src/ts/lib/util.ts
Original file line number Diff line number Diff line change
@@ -1,112 +1,37 @@
import { Card, ValueType, SuitType, Stack, StackCard } from './Card'
import { MoveCardAction, AppendCardAction, SelectAction } from '../redux/globals'

export const random = (min: number, max: number): number => Math.floor(Math.random() * max) + min

const contains = (stack: Stack, card: Card) => stack.cards.some((item: StackCard) => item.card === card)

export const get_top_card = (stack: Stack): StackCard | null => stack.cards[stack.cards.length - 1]

type Selection = { card: Card; stack: Stack } | null

export const get_selection = (stacks: Stack[]): Selection => {
for (const stack of stacks) {
if (stack.selection) return { card: stack.selection, stack }
}
return null
// minstd_rand
export const rnd = (s: number) => {
const rnd = () => ((2 ** 31 - 1) & (s = Math.imul(48271, s))) / 2 ** 31
rnd() // first call is always junk
return (min: number, max: number) => Math.floor(rnd() * (max - min + 1)) + min
}

export const select_card = (stacks: Stack[], { card: { card } }: SelectAction) =>
card == null
? stacks
: stacks.map((stack) =>
!contains(stack, card)
? stack
: {
...stack,
cards: stack.cards.map((stackCard) =>
!stackCard.card || stackCard.card !== card ? stackCard : { ...stackCard, selected: true },
),
selection: card,
},
)

export const deselect_card = (stacks: Stack[]) =>
stacks.map((stack) =>
!stack.selection
? stack
: {
...stack,
selection: null,
cards: stack.cards.map((stackCard) => (!stackCard.selected ? stackCard : { ...stackCard, selected: null })),
},
)

export const move_cards = (stacks: Stack[], { from, to, cards, hidden }: MoveCardAction) =>
stacks.map((stack) =>
stack === to
? {
...stack,
cards: [...stack.cards, ...cards.map((card) => ({ ...card, selected: false, hidden }))],
}
: stack === from
? {
...stack,
cards: stack.cards.filter((stackCard) => !cards.includes(stackCard)),
}
: stack,
)
export const sumConsecutive = (i: number) => (i * (i + 1)) / 2

export const append_cards = (stacks: Stack[], { stack, cards }: AppendCardAction) =>
stacks.map((existingStack) =>
existingStack !== stack
? existingStack
: {
...existingStack,
cards: [...existingStack.cards, ...cards],
},
)
export const getTopCard = (cards: StackCard[]): StackCard | null => cards[cards.length - 1]

export const movable_to_foundation = (card1: Card, card2: StackCard | null) => {
if (card2 == null) {
return card1.value === ValueType.ace
}

const { card } = card2
if (!card) {
return false
}
export const random = (min: number, max: number): number => Math.floor(Math.random() * max) + min

return valueToInt(card1.value) === valueToInt(card.value) + 1 && card1.suit === card.suit
}

export const movable_to_tableau = (source: Card, target?: StackCard) => {
return target == null
? source.value === ValueType.king
: target.card == null
? false
: isSequential(target.card, source) &&
((isRed(source) && isBlack(target.card)) || (isBlack(source) && isRed(target.card)))
}
export const contains = (stack: Stack, card: Card) => stack.cards.some((item: StackCard) => item.card === card)

export const isSequential = (card: Card, card1: Card) => valueToInt(card1.value) + 1 === valueToInt(card.value)

export const isRed = (card: Card) => [SuitType.diamond, SuitType.heart].includes(card.suit)

export const isBlack = (card: Card) => [SuitType.club, SuitType.spade].includes(card.suit)

export const isValidMove = (card: Card, destination?: StackCard) => {
return destination == null
? card.value === ValueType.king
: isSequential(destination.card, card) &&
((isRed(card) && isBlack(destination.card)) || (isBlack(card) && isRed(destination.card)))
}

const valueToInt = (value: ValueType): number => {
if (value === ValueType.ace) {
return 1
}
if (value === ValueType.jack) {
return 11
}
if (value === ValueType.queen) {
return 12
}
if (value === ValueType.king) {
return 13
}
if (value === ValueType.ace) return 1
if (value === ValueType.jack) return 11
if (value === ValueType.queen) return 12
if (value === ValueType.king) return 13
return parseInt(value, 10)
}
Loading

0 comments on commit 3b701e2

Please sign in to comment.