import { equals } from '@typed/common' ; import { delay , Effects , PureEffect , TimerEnv } from '@typed/effects' ; import { Arity1 } from '@typed/lambda' ; import { UuidEnv } from '@typed/uuid/esm' ; import { sortTilesForDirection } from 'source/domain/services/moveTilesInDirection/sortTiles' ; import { addNewTile , Bounds , createNewGrid , Grid , moveTilesInDirection , RandomIntEnv , Size , } from '../domain' ; import { Action } from './types' ; export function createDispatch ( bounds , getGrid , setGrid ) { return function * dispatch ( action ) : Effects < RandomIntEnv & UuidEnv & TimerEnv , void > { switch ( action [ 0 ] ) { case 'new-grid' : { const grid = yield * getGrid ( ) ; const newGrid = yield * createNewGrid ( grid . size ) ; yield * setGrid ( ( ) => newGrid ) ; break ; } case 'move' : { const direction = action [ 1 ] ; const grid = yield * getGrid ( ) ; const updatedGrid = { ... grid , tiles : moveTilesInDirection ( bounds , direction , grid . tiles ) } ; if ( equals ( sortTilesForDirection ( direction , grid . tiles ) , sortTilesForDirection ( direction , updatedGrid . tiles ) ) ) { break ; } yield * setGrid ( ( ) => updatedGrid ) ; yield * delay ( 100 ) ; const newGrid = yield * addNewTile ( updatedGrid ) ; yield * setGrid ( ( ) => newGrid ) ; break ; } case 'resize' : { const grid = yield * getGrid ( ) ; const newGrid = yield * createNewGrid ( getNextSize ( grid . size ) ) ; yield * setGrid ( ( ) => newGrid ) ; break ; } } } ; } function getNextSize ( size ) { if ( size [ 0 ] === 6 ) { return [ 3 , 3 ] ; } return [ size [ 0 ] + 1 , size [ 1 ] + 1 ] as Size ; }