UNPKG

what-is-word-cli

Version:

CLI game where your task is to unscramble words by given definition

189 lines 7.79 kB
import React, { useContext, useEffect } from 'react'; import { Text, Box, useInput } from 'ink'; import Gradient from 'ink-gradient'; import TextInput from 'ink-text-input'; import { Alert, StatusMessage } from '@inkjs/ui'; import * as R from 'remeda'; import { listenKeys } from 'nanostores'; import { useStore } from '@nanostores/react'; import delay from 'delay'; import { manager as appManager, $roundItem, $suite } from '../store.js'; import { useScreenSize } from '../hooks/useScreenSize.js'; import { $newLines, $definitionHeight, actions as roundActions, $panelHeight } from '../store/round.js'; import { $status, actions as statusActions, manager as statusManager, statuses } from '../store/status.js'; import { $score, $userInput, $gameRounds, manager as gameManager, scoreActions, $lastUserAnswer } from '../store/game.js'; import { getId, getSuiteBySettings } from '../helpers.js'; import { SettingsContext } from '../app.js'; export default function Game() { const definitionHeight = useStore($definitionHeight); const escapingCharsPanelHeight = useStore($panelHeight); const newLines = useStore($newLines); useStore($status); const roundItem = useStore($roundItem); const suite = useStore($suite); const gameRounds = useStore($gameRounds); const score = useStore($score); const userInput = useStore($userInput); const lastUserAnswer = useStore($lastUserAnswer); const { settings } = useContext(SettingsContext); const { width, height } = useScreenSize(); useEffect(() => { listenKeys($roundItem, ['definition'], value => { roundActions.calculateDefinitionHeight(value.definition); }); const unbindDefintionHeightListener = $definitionHeight.subscribe(value => { roundActions.setNewLines(height - value - 9); roundActions.setPanelHeight(height - value - 6); }); const unbindFinishedListener = $status.subscribe(value => { if (value === statuses.finished) { appManager.displayNextResult(); } }); appManager.displayNextResult(); return () => { unbindDefintionHeightListener(); unbindFinishedListener(); clearInterval($roundItem.get().intervalId); console.clear(); }; }, [height]); const startNewRound = () => { appManager.setupNextRound(); statusActions.setRunning(); roundActions.setNewLines(process.stdout.rows - definitionHeight - 9); const intervalId = setInterval(async () => { const newLines = roundActions.decrement(); appManager.setRoundTemplate(); if (newLines < 0) { clearInterval(intervalId); gameManager.setErrored(); statusActions.setDisplayingResult(); await delay(600); if ($suite.get().length === $gameRounds.get().length) { statusActions.setFinished(); } else { startNewRound(); } } }, 1000); appManager.setIntervalId(intervalId); return intervalId; }; useInput((input, _key) => { if (input === 'y') { roundActions.setPanelHeight(process.stdout.rows - definitionHeight - 5); appManager.setSuite(getSuiteBySettings(settings).items); const intervalId = startNewRound(); appManager.setIntervalId(intervalId); statusActions.setRunning(); } }, { isActive: statusManager.isPaused() }); const lastGameRound = R.last(gameRounds); return statusManager.isRunning() || statusManager.isDisplayingResult() ? /*#__PURE__*/React.createElement(Box, { width: width, height: height, flexDirection: "column", alignItems: "center" }, /*#__PURE__*/React.createElement(Box, { alignSelf: "flex-end", marginBottom: 1 }, /*#__PURE__*/React.createElement(Box, { alignSelf: "flex-end", borderStyle: "single" }, /*#__PURE__*/React.createElement(Text, null, "Trial ", $gameRounds.get().length), /*#__PURE__*/React.createElement(Text, null, "\xA0of"), /*#__PURE__*/React.createElement(Text, null, "\xA0", $suite.get().length)), /*#__PURE__*/React.createElement(Box, { alignSelf: "flex-end", borderStyle: "single" }, /*#__PURE__*/React.createElement(Text, null, "Score: ", score))), /*#__PURE__*/React.createElement(Box, { flexDirection: "column", marginBottom: 1 }, /*#__PURE__*/React.createElement(Box, { height: definitionHeight, alignItems: "center", justifyContent: "center" }, /*#__PURE__*/React.createElement(Text, { color: "#89d" }, roundItem.definition))), statusManager.isDisplayingResult() ? R.isDefined(lastGameRound) && /*#__PURE__*/React.createElement(Box, { flexDirection: "column", height: escapingCharsPanelHeight, justifyContent: "center", alignItems: "center" }, /*#__PURE__*/React.createElement(Box, null, /*#__PURE__*/React.createElement(Alert, { variant: lastGameRound.status === 'success' ? 'success' : 'error' }, lastGameRound.message))) : /*#__PURE__*/React.createElement(Box, { flexDirection: "column", height: escapingCharsPanelHeight, alignItems: "center" }, /*#__PURE__*/React.createElement(Box, null, /*#__PURE__*/React.createElement(Text, null, R.times(roundItem.word.length, () => '-'))), /*#__PURE__*/React.createElement(Box, { flexDirection: "column" }, /*#__PURE__*/React.createElement(Box, { height: newLines }), roundItem.template.map(chars => /*#__PURE__*/React.createElement(Text, { key: getId() }, chars.join(''))))), /*#__PURE__*/React.createElement(Box, { marginTop: 1, alignItems: "center", justifyContent: "center" }, /*#__PURE__*/React.createElement(Text, null, "Answer:\xA0"), /*#__PURE__*/React.createElement(Box, { borderStyle: "single", borderColor: "#e90", borderTop: false, borderLeft: false, borderRight: false }, !statusManager.isPaused() && /*#__PURE__*/React.createElement(TextInput, { placeholder: "What is it?", value: userInput, onChange: value => { gameManager.setInput(value); }, onSubmit: async value => { if (value === roundItem.word) { clearInterval(roundItem.intervalId); gameManager.setSucceeded(value); gameManager.resetInput(); scoreActions.increment(); statusActions.setDisplayingResult(); await delay(600); if (suite.length === $gameRounds.get().length) { statusActions.setFinished(); return; } startNewRound(); } else { gameManager.registerUserAnswer(userInput); gameManager.resetInput(); } } })), /*#__PURE__*/React.createElement(Box, { paddingLeft: 2, flexDirection: "row", justifyContent: "space-around" }, R.isEmpty(lastUserAnswer) ? /*#__PURE__*/React.createElement(Text, { color: "green" }) : /*#__PURE__*/React.createElement(StatusMessage, { variant: "error" }, lastUserAnswer)))) : /*#__PURE__*/React.createElement(Box, { width: width, height: height, flexDirection: "column", justifyContent: "center", alignItems: "center", paddingX: 2 }, /*#__PURE__*/React.createElement(Box, null, /*#__PURE__*/React.createElement(Gradient, { name: "teen" }, /*#__PURE__*/React.createElement(Text, null, "WHAT-IS-WORD"))), /*#__PURE__*/React.createElement(Box, { marginTop: 3 }, /*#__PURE__*/React.createElement(Text, null, "Try to unscramble words by given definition and provide a correct word.")), /*#__PURE__*/React.createElement(Box, { paddingBottom: 3 }, /*#__PURE__*/React.createElement(Text, null, "You must be in time before the scrambled word reaches dashed borders.")), /*#__PURE__*/React.createElement(Box, null, /*#__PURE__*/React.createElement(Text, null, "Are you ready? Press", ' ', /*#__PURE__*/React.createElement(Text, { bold: true, color: "cyan" }, "y"), ' ', "to start."))); }