// RxJS v6+
import { fromEvent, of, interval, combineLatest } from 'rxjs';
import {
finalize,
map,
pluck,
scan,
startWith,
takeWhile,
tap
} from 'rxjs/operators';
import { score, randomBrick, clearGame, initialState } from './game';
import { render, renderGameOver } from './html-renderer';
import { handleKeyPress, resetKey } from './keyboard';
import { collide } from './collision';
import { rotate } from './rotation';
import { BRICK } from './constants';
import { State, Brick, Key } from './interfaces';
const player$ = combineLatest(
of(randomBrick()),
of({ code: '' }),
fromEvent(document, 'keyup').pipe(
startWith({ code: undefined }),
pluck('code')
)
).pipe(
map(
([brick, key, keyCode]: [Brick, Key, string]) => (
(key.code = keyCode), [brick, key]
)
)
);
const state$ = interval(1000).pipe(
scan < number,
State > ((state, _) => (state.x++, state), initialState)
);
const game$ = combineLatest(state$, player$).pipe(
scan < [State, [Brick, Key]],
[State, [Brick, Key]] >
(([state, [brick, key]]) => (
(state = handleKeyPress(state, brick, key)),
(([newState, rotatedBrick]: [State, Brick]) => (
(state = newState), (brick = rotatedBrick)
))(rotate(state, brick, key)),
(([newState, collidedBrick]: [State, Brick]) => (
(state = newState), (brick = collidedBrick)
))(collide(state, brick)),
(state = score(state)),
resetKey(key),
[state, [brick, key]]
)),
tap(([state, [brick, key]]) => render(state, brick)),
takeWhile(([state, [brick, key]]) => !state.game[1].some(c => c === BRICK)),
finalize(renderGameOver)
);
game$.subscribe();