diff --git a/bsconfig.json b/bsconfig.json index 43a232f..c39b9be 100644 --- a/bsconfig.json +++ b/bsconfig.json @@ -1,5 +1,5 @@ { - "name": "reason-react-examples", + "name": "multi-n-back", "reason": { "react-jsx": 3 }, diff --git a/package.json b/package.json index 9106873..8fd5527 100644 --- a/package.json +++ b/package.json @@ -2,9 +2,9 @@ "name": "multi-n-back", "version": "0.1.0", "scripts": { - "build": "bsb -make-world", - "start": "bsb -make-world -w -ws _ ", - "clean": "bsb -clean-world", + "build": "rescript", + "start": "rescript build -w", + "clean": "rescript clean", "server": "moduleserve ./ --port 8000", "clean-dist": "rimraf ./dist", "build-dist": "yarn clean-dist && webpack --config ./webpack.config.js && cp ./indexProduction.html ./dist/index.html && cp ./favicon.ico ./dist/favicon.ico", @@ -19,17 +19,18 @@ "author": "", "license": "MIT", "dependencies": { - "@glennsl/bs-jest": "^0.5.1", - "react": "^16.8.1", - "react-dom": "^16.8.1", + "@glennsl/bs-jest": "^0.7.0", + "react": "^17.0.2", + "react-dom": "^17.0.2", "reason-react": ">=0.7.0", + "rescript": "^9.1.4", "rimraf": "^3.0.2", - "serve": "^11.3.2", - "webpack": "^4.41.6", - "webpack-cli": "^3.3.11" + "serve": "^12.0.0", + "webpack": "^5.52.0", + "webpack-cli": "^4.8.0" }, "devDependencies": { - "bs-platform": "^8.2.0", + "bs-platform": "^9.0.2", "moduleserve": "^0.9.0" }, "jest": { diff --git a/src/App.bs.js b/src/App.bs.js index 4a5e0c6..b834ff5 100644 --- a/src/App.bs.js +++ b/src/App.bs.js @@ -1,27 +1,27 @@ 'use strict'; -var List = require("bs-platform/lib/js/list.js"); -var $$Array = require("bs-platform/lib/js/array.js"); -var Curry = require("bs-platform/lib/js/curry.js"); +var List = require("rescript/lib/js/list.js"); +var $$Array = require("rescript/lib/js/array.js"); +var Curry = require("rescript/lib/js/curry.js"); var React = require("react"); -var Score$ReasonReactExamples = require("./GameCore/Score.bs.js"); -var Answer$ReasonReactExamples = require("./GameCore/Answer.bs.js"); -var Canvas$ReasonReactExamples = require("./GameCore/Canvas.bs.js"); -var Modality$ReasonReactExamples = require("./GameCore/Modality/Modality.bs.js"); -var GameState$ReasonReactExamples = require("./GameCore/GameState.bs.js"); -var Statistics$ReasonReactExamples = require("./Interface/Statistics.bs.js"); -var AnswerToggle$ReasonReactExamples = require("./Interface/AnswerToggle.bs.js"); -var GameConfiguration$ReasonReactExamples = require("./GameCore/GameConfiguration.bs.js"); -var ConfigurationPanel$ReasonReactExamples = require("./Interface/ConfigurationPanel.bs.js"); -var ConfigurationTrigger$ReasonReactExamples = require("./Interface/ConfigurationTrigger.bs.js"); +var Score$MultiNBack = require("./GameCore/Score.bs.js"); +var Answer$MultiNBack = require("./GameCore/Answer.bs.js"); +var Canvas$MultiNBack = require("./GameCore/Canvas.bs.js"); +var Modality$MultiNBack = require("./GameCore/Modality/Modality.bs.js"); +var GameState$MultiNBack = require("./GameCore/GameState.bs.js"); +var Statistics$MultiNBack = require("./Interface/Statistics.bs.js"); +var AnswerToggle$MultiNBack = require("./Interface/AnswerToggle.bs.js"); +var GameConfiguration$MultiNBack = require("./GameCore/GameConfiguration.bs.js"); +var ConfigurationPanel$MultiNBack = require("./Interface/ConfigurationPanel.bs.js"); +var ConfigurationTrigger$MultiNBack = require("./Interface/ConfigurationTrigger.bs.js"); -var initialConfig = GameConfiguration$ReasonReactExamples.makeDefault(undefined); +var initialConfig = GameConfiguration$MultiNBack.makeDefault(undefined); -var initialState_gameState = GameState$ReasonReactExamples.makeRandom(initialConfig); +var initialState_gameState = GameState$MultiNBack.makeRandom(initialConfig); -var initialState_answer = Answer$ReasonReactExamples.make(undefined); +var initialState_answer = Answer$MultiNBack.make(undefined); -var initialState_highScore = Score$ReasonReactExamples.getHighScore(undefined); +var initialState_highScore = Score$MultiNBack.getHighScore(undefined); var initialState = { config: initialConfig, @@ -48,7 +48,7 @@ function reducer(state, action) { } var partiallyUpdatedState; if (List.length(state.stateHistory) >= state.config.depth) { - var result = GameState$ReasonReactExamples.compareToHistory(state.answer, state.gameState, state.stateHistory, state.config); + var result = GameState$MultiNBack.compareToHistory(state.answer, state.gameState, state.stateHistory, state.config); partiallyUpdatedState = result !== undefined ? ({ config: state.config, configPanelOpen: state.configPanelOpen, @@ -58,7 +58,7 @@ function reducer(state, action) { tl: state.stateHistory }, answer: state.answer, - score: Score$ReasonReactExamples.calculateScore(result, state.config.depth) + state.score | 0, + score: Score$MultiNBack.calculateScore(result, state.config.depth) + state.score | 0, highScore: state.highScore }) : ({ config: state.config, @@ -67,7 +67,7 @@ function reducer(state, action) { stateHistory: /* [] */0, answer: state.answer, score: 0, - highScore: Score$ReasonReactExamples.updateHighScore(state.score) + highScore: Score$MultiNBack.updateHighScore(state.score) }); } else { partiallyUpdatedState = { @@ -86,9 +86,9 @@ function reducer(state, action) { return { config: partiallyUpdatedState.config, configPanelOpen: partiallyUpdatedState.configPanelOpen, - gameState: GameState$ReasonReactExamples.makeRandom(state.config), + gameState: GameState$MultiNBack.makeRandom(state.config), stateHistory: partiallyUpdatedState.stateHistory, - answer: Answer$ReasonReactExamples.make(undefined), + answer: Answer$MultiNBack.make(undefined), score: partiallyUpdatedState.score, highScore: partiallyUpdatedState.highScore }; @@ -96,7 +96,7 @@ function reducer(state, action) { switch (action.TAG | 0) { case /* UpdateDepthConfig */0 : return { - config: GameConfiguration$ReasonReactExamples.updateDepth(action._0, state.config), + config: GameConfiguration$MultiNBack.updateDepth(action._0, state.config), configPanelOpen: state.configPanelOpen, gameState: state.gameState, stateHistory: state.stateHistory, @@ -106,7 +106,7 @@ function reducer(state, action) { }; case /* UpdateModalityConfig */1 : return { - config: GameConfiguration$ReasonReactExamples.updateModality(action._0, action._1, state.config), + config: GameConfiguration$MultiNBack.updateModality(action._0, action._1, state.config), configPanelOpen: state.configPanelOpen, gameState: state.gameState, stateHistory: state.stateHistory, @@ -142,20 +142,20 @@ function App(Props) { className: "overviewContainer" }, React.createElement("div", { className: "scoreContainer" - }, value !== 0 ? React.createElement(Statistics$ReasonReactExamples.make, { + }, value !== 0 ? React.createElement(Statistics$MultiNBack.make, { label: "Turn", value: value + 1 | 0 }) : "First Turn!"), React.createElement("div", { className: "scoreContainer" - }, value$1 !== 0 ? React.createElement(Statistics$ReasonReactExamples.make, { + }, value$1 !== 0 ? React.createElement(Statistics$MultiNBack.make, { label: "Score", value: value$1 }) : null), React.createElement("div", { className: "scoreContainer" - }, value$2 !== undefined ? React.createElement(Statistics$ReasonReactExamples.make, { + }, value$2 !== undefined ? React.createElement(Statistics$MultiNBack.make, { label: "High Score", value: value$2 - }) : null)), React.createElement(Canvas$ReasonReactExamples.make, { + }) : null)), React.createElement(Canvas$MultiNBack.make, { config: state.config, gameState: state.gameState }), state.configPanelOpen ? null : React.createElement("div", { @@ -170,7 +170,7 @@ function App(Props) { onClick: (function (param) { return Curry._1(dispatch, /* AdvanceTurn */1); }) - }, List.length(state.stateHistory) === 0 ? "Start" : "Next")), !state.configPanelOpen && List.length(state.stateHistory) === 0 ? React.createElement(ConfigurationTrigger$ReasonReactExamples.make, { + }, List.length(state.stateHistory) === 0 ? "Start" : "Next")), !state.configPanelOpen && List.length(state.stateHistory) === 0 ? React.createElement(ConfigurationTrigger$MultiNBack.make, { toggleConfigPanelOpen: (function (param) { return Curry._1(dispatch, /* ToggleConfigPanelOpen */0); }) @@ -181,23 +181,23 @@ function App(Props) { justifyContent: "center" } }, $$Array.map((function (modality) { - var match = Modality$ReasonReactExamples.getValue(modality, state.config.modalities); + var match = Modality$MultiNBack.getValue(modality, state.config.modalities); if (match !== undefined) { - return React.createElement(AnswerToggle$ReasonReactExamples.make, { - checked: Modality$ReasonReactExamples.getValue(modality, state.answer), + return React.createElement(AnswerToggle$MultiNBack.make, { + checked: Modality$MultiNBack.getValue(modality, state.answer), onChange: (function (param) { return Curry._1(dispatch, { TAG: /* UpdateAnswer */2, - _0: Answer$ReasonReactExamples.toggle(modality, state.answer) + _0: Answer$MultiNBack.toggle(modality, state.answer) }); }), - label: "Same " + Modality$ReasonReactExamples.getLabel(modality), - key: Modality$ReasonReactExamples.getLabel(modality) + "_answer" + label: "Same " + Modality$MultiNBack.getLabel(modality), + key: Modality$MultiNBack.getLabel(modality) + "_answer" }); } else { return null; } - }), Modality$ReasonReactExamples.allModalityTypes)) : null, React.createElement(ConfigurationPanel$ReasonReactExamples.make, { + }), Modality$MultiNBack.allModalityTypes)) : null, React.createElement(ConfigurationPanel$MultiNBack.make, { panelOpen: state.configPanelOpen, config: state.config, updateModalityConfig: (function (modality, value) { diff --git a/src/App.re b/src/App.re deleted file mode 100644 index 2e612a2..0000000 --- a/src/App.re +++ /dev/null @@ -1,168 +0,0 @@ -type state = { - config: GameConfiguration.t, - configPanelOpen: bool, - gameState: GameState.t, - stateHistory: GameState.stateHistory, - answer: Answer.t, - score: int, - highScore: option(int), -}; - -type action = - | UpdateDepthConfig(int) - | UpdateModalityConfig(Modality.t, option(int)) - | ToggleConfigPanelOpen - | UpdateAnswer(Answer.t) - | AdvanceTurn; - -let initialConfig = GameConfiguration.makeDefault(); - -let initialState: state = { - config: initialConfig, - configPanelOpen: false, - gameState: GameState.makeRandom(initialConfig), - stateHistory: [], - answer: Answer.make(), - score: 0, - highScore: Score.getHighScore(), -}; - -let reducer = (state: state, action: action): state => { - switch (action) { - | UpdateDepthConfig(value) => { - ...state, - config: state.config |> GameConfiguration.updateDepth(value), - } - | UpdateModalityConfig(modality, value) => { - ...state, - config: - state.config |> GameConfiguration.updateModality(modality, value), - } - | ToggleConfigPanelOpen => { - ...state, - configPanelOpen: !state.configPanelOpen, - } - | UpdateAnswer(answer) => {...state, answer} - | AdvanceTurn => - let partiallyUpdatedState = - if (state.stateHistory->List.length >= state.config.depth) { - switch ( - GameState.compareToHistory( - state.answer, - state.gameState, - state.stateHistory, - state.config, - ) - ) { - | Some(result) => { - ...state, - stateHistory: [state.gameState, ...state.stateHistory], - score: - Score.calculateScore(result, state.config.depth) + state.score, - } - | None => { - ...state, - stateHistory: [], - score: 0, - highScore: Some(Score.updateHighScore(state.score)), - } - }; - } else { - {...state, stateHistory: [state.gameState, ...state.stateHistory]}; - }; - { - ...partiallyUpdatedState, - answer: Answer.make(), - gameState: GameState.makeRandom(state.config), - }; - }; -}; - -[@react.component] -let make = () => { - let (state, dispatch) = React.useReducer(reducer, initialState); - - let toggleAnswer = modality => { - dispatch(UpdateAnswer(state.answer |> Answer.toggle(modality))); - }; - - <> -
{React.string("Multi-N-Back")}
-
-
- {switch (state.stateHistory |> List.length) { - | 0 => React.string("First Turn!") - | value => - }} -
-
- {switch (state.score) { - | 0 => React.null - | value => - }} -
-
- {switch (state.highScore) { - | None => React.null - | Some(value) => - }} -
-
- - {!state.configPanelOpen - ?
- -
- : React.null} - {!state.configPanelOpen && List.length(state.stateHistory) == 0 - ? dispatch(ToggleConfigPanelOpen)} - /> - : React.null} - {if (List.length(state.stateHistory) >= state.config.depth) { -
- {Modality.allModalityTypes - |> Array.map(modality => { - switch (state.config.modalities |> Modality.getValue(modality)) { - | Some(_) => - Modality.getValue(modality)} - onChange={_ => toggleAnswer(modality)} - label={"Same " ++ Modality.getLabel(modality)} - /> - | None => React.null - } - }) - |> React.array} -
; - } else { - React.null; - }} - - dispatch(UpdateModalityConfig(modality, value)) - } - updateDepthConfig={depth => dispatch(UpdateDepthConfig(depth))} - togglePanelOpen={_ => dispatch(ToggleConfigPanelOpen)} - /> - ; -}; diff --git a/src/App.res b/src/App.res new file mode 100644 index 0000000..e8ac3d7 --- /dev/null +++ b/src/App.res @@ -0,0 +1,153 @@ +type state = { + config: GameConfiguration.t, + configPanelOpen: bool, + gameState: GameState.t, + stateHistory: GameState.stateHistory, + answer: Answer.t, + score: int, + highScore: option, +} + +type action = + | UpdateDepthConfig(int) + | UpdateModalityConfig(Modality.t, option) + | ToggleConfigPanelOpen + | UpdateAnswer(Answer.t) + | AdvanceTurn + +let initialConfig = GameConfiguration.makeDefault() + +let initialState: state = { + config: initialConfig, + configPanelOpen: false, + gameState: GameState.makeRandom(initialConfig), + stateHistory: list{}, + answer: Answer.make(), + score: 0, + highScore: Score.getHighScore(), +} + +let reducer = (state: state, action: action): state => + switch action { + | UpdateDepthConfig(value) => { + ...state, + config: state.config |> GameConfiguration.updateDepth(value), + } + | UpdateModalityConfig(modality, value) => { + ...state, + config: state.config |> GameConfiguration.updateModality(modality, value), + } + | ToggleConfigPanelOpen => { + ...state, + configPanelOpen: !state.configPanelOpen, + } + | UpdateAnswer(answer) => {...state, answer: answer} + | AdvanceTurn => + let partiallyUpdatedState = if state.stateHistory->List.length >= state.config.depth { + switch GameState.compareToHistory( + state.answer, + state.gameState, + state.stateHistory, + state.config, + ) { + | Some(result) => { + ...state, + stateHistory: list{state.gameState, ...state.stateHistory}, + score: Score.calculateScore(result, state.config.depth) + state.score, + } + | None => { + ...state, + stateHistory: list{}, + score: 0, + highScore: Some(Score.updateHighScore(state.score)), + } + } + } else { + { + ...state, + stateHistory: list{state.gameState, ...state.stateHistory}, + } + } + { + ...partiallyUpdatedState, + answer: Answer.make(), + gameState: GameState.makeRandom(state.config), + } + } + +@react.component +let make = () => { + let (state, dispatch) = React.useReducer(reducer, initialState) + + let toggleAnswer = modality => dispatch(UpdateAnswer(state.answer |> Answer.toggle(modality))) + + <> +
{React.string("Multi-N-Back")}
+
+
+ {switch state.stateHistory |> List.length { + | 0 => React.string("First Turn!") + | value => + }} +
+
+ {switch state.score { + | 0 => React.null + | value => + }} +
+
+ {switch state.highScore { + | None => React.null + | Some(value) => + }} +
+
+ + {!state.configPanelOpen + ?
+ +
+ : React.null} + {!state.configPanelOpen && List.length(state.stateHistory) == 0 + ? dispatch(ToggleConfigPanelOpen)} /> + : React.null} + {if List.length(state.stateHistory) >= state.config.depth { +
+ {Modality.allModalityTypes + |> Array.map(modality => + switch state.config.modalities |> Modality.getValue(modality) { + | Some(_) => + Modality.getValue(modality)} + onChange={_ => toggleAnswer(modality)} + label={"Same " ++ Modality.getLabel(modality)} + /> + | None => React.null + } + ) + |> React.array} +
+ } else { + React.null + }} + dispatch(UpdateModalityConfig(modality, value))} + updateDepthConfig={depth => dispatch(UpdateDepthConfig(depth))} + togglePanelOpen={_ => dispatch(ToggleConfigPanelOpen)} + /> + +} diff --git a/src/AppStyles.re b/src/AppStyles.res similarity index 93% rename from src/AppStyles.re rename to src/AppStyles.res index d86b2a7..f0d8245 100644 --- a/src/AppStyles.re +++ b/src/AppStyles.res @@ -1,15 +1,15 @@ -let blue = "#48a9dc"; -let background = "#e0e2ef"; -let background_less_darker = "#d0d2de"; -let background_less_lighter = "#f0f2ff"; -let background_more_darker = "#c1c2ce"; -let background_more_lighter = "#ffffff"; +let blue = "#48a9dc" +let background = "#e0e2ef" +let background_less_darker = "#d0d2de" +let background_less_lighter = "#f0f2ff" +let background_more_darker = "#c1c2ce" +let background_more_lighter = "#ffffff" // The {j|...|j} feature is just string interpolation, from // bucklescript.github.io/docs/en/interop-cheatsheet#string-unicode-interpolation // This allows us to conveniently write CSS, together with variables, by // constructing a string -let style = {j| +let style = j` * { box-sizing: content-box; } @@ -144,4 +144,4 @@ let style = {j| .configPanelClosed { transform: translateY(100vh); } -|j}; +` diff --git a/src/GameCore/Answer.bs.js b/src/GameCore/Answer.bs.js index 9a40062..f40dbd1 100644 --- a/src/GameCore/Answer.bs.js +++ b/src/GameCore/Answer.bs.js @@ -1,6 +1,6 @@ 'use strict'; -var Modality$ReasonReactExamples = require("./Modality/Modality.bs.js"); +var Modality$MultiNBack = require("./Modality/Modality.bs.js"); function make(param) { return { @@ -11,28 +11,28 @@ function make(param) { } function toggleValue(modality, answer) { - return !Modality$ReasonReactExamples.getValue(modality, answer); + return !Modality$MultiNBack.getValue(modality, answer); } function toggle(modality, answer) { switch (modality) { case /* Position */0 : return { - position: !Modality$ReasonReactExamples.getValue(/* Position */0, answer), + position: !Modality$MultiNBack.getValue(/* Position */0, answer), color: answer.color, icon: answer.icon }; case /* Color */1 : return { position: answer.position, - color: !Modality$ReasonReactExamples.getValue(/* Color */1, answer), + color: !Modality$MultiNBack.getValue(/* Color */1, answer), icon: answer.icon }; case /* Icon */2 : return { position: answer.position, color: answer.color, - icon: !Modality$ReasonReactExamples.getValue(/* Icon */2, answer) + icon: !Modality$MultiNBack.getValue(/* Icon */2, answer) }; } diff --git a/src/GameCore/Answer.re b/src/GameCore/Answer.res similarity index 64% rename from src/GameCore/Answer.re rename to src/GameCore/Answer.res index 0f2b6c2..b1f26c9 100644 --- a/src/GameCore/Answer.re +++ b/src/GameCore/Answer.res @@ -1,15 +1,14 @@ -type answer = Modality.modalities(bool); +type answer = Modality.modalities -type t = answer; +type t = answer -let make = (): t => {position: false, color: false, icon: false}; +let make = (): t => {position: false, color: false, icon: false} -let toggleValue = (modality: Modality.t, answer: t) => - !Modality.getValue(modality, answer); +let toggleValue = (modality: Modality.t, answer: t) => !Modality.getValue(modality, answer) let toggle = (modality: Modality.t, answer: t) => - switch (modality) { + switch modality { | Modality.Position => {...answer, position: toggleValue(Position, answer)} | Modality.Color => {...answer, color: toggleValue(Color, answer)} | Modality.Icon => {...answer, icon: toggleValue(Icon, answer)} - }; + } diff --git a/src/GameCore/Canvas.bs.js b/src/GameCore/Canvas.bs.js index 3684b01..74f1b5b 100644 --- a/src/GameCore/Canvas.bs.js +++ b/src/GameCore/Canvas.bs.js @@ -1,16 +1,16 @@ 'use strict'; -var $$Array = require("bs-platform/lib/js/array.js"); +var $$Array = require("rescript/lib/js/array.js"); var React = require("react"); -var Caml_array = require("bs-platform/lib/js/caml_array.js"); -var Belt_Option = require("bs-platform/lib/js/belt_Option.js"); +var Caml_array = require("rescript/lib/js/caml_array.js"); +var Belt_Option = require("rescript/lib/js/belt_Option.js"); var ReactDOMStyle = require("reason-react/src/ReactDOMStyle.bs.js"); -var Icon$ReasonReactExamples = require("./Modality/Icon.bs.js"); -var Color$ReasonReactExamples = require("./Modality/Color.bs.js"); -var Modality$ReasonReactExamples = require("./Modality/Modality.bs.js"); +var Icon$MultiNBack = require("./Modality/Icon.bs.js"); +var Color$MultiNBack = require("./Modality/Color.bs.js"); +var Modality$MultiNBack = require("./Modality/Modality.bs.js"); -function getSize(param) { - switch (param) { +function getSize(x) { + switch (x) { case 0 : case 1 : return [ @@ -55,12 +55,12 @@ function Canvas(Props) { var config = Props.config; var gameState = Props.gameState; var modalityIndices = $$Array.fold_left((function (acc, modality) { - var match = Modality$ReasonReactExamples.getValue(modality, config.modalities); - var match$1 = Modality$ReasonReactExamples.getValue(modality, gameState); + var match = Modality$MultiNBack.getValue(modality, config.modalities); + var match$1 = Modality$MultiNBack.getValue(modality, gameState); var value = match !== undefined && match$1 !== undefined ? match$1 : 0; - return Modality$ReasonReactExamples.setValue(modality, value, acc); - }), Modality$ReasonReactExamples.make(0), Modality$ReasonReactExamples.allModalityTypes); - var positionDepth = Modality$ReasonReactExamples.getValue(/* Position */0, config.modalities); + return Modality$MultiNBack.setValue(modality, value, acc); + }), Modality$MultiNBack.make(0), Modality$MultiNBack.allModalityTypes); + var positionDepth = Modality$MultiNBack.getValue(/* Position */0, config.modalities); var positionDepth$1 = positionDepth !== undefined ? positionDepth : 1; var wrapperStyles = { display: "grid", @@ -75,23 +75,23 @@ function Canvas(Props) { className: "canvasContainer", style: ReactDOMStyle.unsafeAddProp(wrapperStyles, "gridTemplateColumns", "repeat(" + (String(positionDepth$1) + ", 1fr)")) }, $$Array.mapi((function (renderIndex, param) { - var active = Modality$ReasonReactExamples.getValue(/* Position */0, modalityIndices) === renderIndex; - return React.createElement(Color$ReasonReactExamples.make, { - children: React.createElement(Icon$ReasonReactExamples.make, { - index: Modality$ReasonReactExamples.getValue(/* Icon */2, modalityIndices), - active: active && Belt_Option.isSome(Modality$ReasonReactExamples.getValue(/* Icon */2, config.modalities)), + var active = Modality$MultiNBack.getValue(/* Position */0, modalityIndices) === renderIndex; + return React.createElement(Color$MultiNBack.make, { + children: React.createElement(Icon$MultiNBack.make, { + index: Modality$MultiNBack.getValue(/* Icon */2, modalityIndices), + active: active && Belt_Option.isSome(Modality$MultiNBack.getValue(/* Icon */2, config.modalities)), size: iconSize }), - active: active && Belt_Option.isSome(Modality$ReasonReactExamples.getValue(/* Color */1, config.modalities)), - index: Modality$ReasonReactExamples.getValue(/* Color */1, modalityIndices), + active: active && Belt_Option.isSome(Modality$MultiNBack.getValue(/* Color */1, config.modalities)), + index: Modality$MultiNBack.getValue(/* Color */1, modalityIndices), width: width, height: height, key: String(renderIndex) }); - }), Caml_array.caml_make_vect(Math.imul(positionDepth$1, positionDepth$1), 0))); + }), Caml_array.make(Math.imul(positionDepth$1, positionDepth$1), 0))); } -var getValue = Modality$ReasonReactExamples.getValue; +var getValue = Modality$MultiNBack.getValue; var make = Canvas; diff --git a/src/GameCore/Canvas.re b/src/GameCore/Canvas.re deleted file mode 100644 index dfcbc5e..0000000 --- a/src/GameCore/Canvas.re +++ /dev/null @@ -1,86 +0,0 @@ -let getValue = Modality.getValue; - -type modalityIndices = Modality.modalities(int); - -let getSize = - fun - | 0 - | 1 => (80, 88, 76) - | 2 => (60, 66, 58) - | 3 => (43, 48, 41) - | 4 => (40, 44, 38) - | 5 => (30, 33, 28) - | _ => (20, 22, 18); - -[@react.component] -let make = (~config: GameConfiguration.t, ~gameState: GameState.t) => { - let modalityIndices = - Modality.allModalityTypes - |> Array.fold_left( - (acc, modality) => { - let value = - switch ( - config.modalities |> getValue(modality), - gameState |> getValue(modality), - ) { - | (Some(_), Some(index)) => index - | _ => 0 - }; - acc |> Modality.setValue(modality, value); - }, - Modality.make(0), - ); - - let positionDepth = - switch (config.modalities |> getValue(Position)) { - | Some(positionDepth) => positionDepth - | _ => 1 - }; - - let wrapperStyles = - ReactDOMRe.Style.make( - ~display="grid", - ~alignItems="center", - ~justifyItems="center", - (), - ); - - let (width, height, iconSize) = getSize(positionDepth); - -
- {Array.make(positionDepth * positionDepth, 0) - |> Array.mapi((renderIndex, _) => { - let active = - modalityIndices |> Modality.getValue(Position) == renderIndex; - Modality.getValue(Color) - |> Belt.Option.isSome - } - index={modalityIndices |> Modality.getValue(Color)}> - Modality.getValue(Icon) - |> Belt.Option.isSome - } - index={modalityIndices |> Modality.getValue(Icon)} - size=iconSize - /> - ; - }) - |> ReasonReact.array} -
; -}; diff --git a/src/GameCore/Canvas.res b/src/GameCore/Canvas.res new file mode 100644 index 0000000..d452972 --- /dev/null +++ b/src/GameCore/Canvas.res @@ -0,0 +1,65 @@ +let getValue = Modality.getValue + +type modalityIndices = Modality.modalities + +let getSize = x => + switch x { + | 0 + | 1 => (80, 88, 76) + | 2 => (60, 66, 58) + | 3 => (43, 48, 41) + | 4 => (40, 44, 38) + | 5 => (30, 33, 28) + | _ => (20, 22, 18) + } + +@react.component +let make = (~config: GameConfiguration.t, ~gameState: GameState.t) => { + let modalityIndices = Modality.allModalityTypes |> Array.fold_left((acc, modality) => { + let value = switch (config.modalities |> getValue(modality), gameState |> getValue(modality)) { + | (Some(_), Some(index)) => index + | _ => 0 + } + acc |> Modality.setValue(modality, value) + }, Modality.make(0)) + + let positionDepth = switch config.modalities |> getValue(Position) { + | Some(positionDepth) => positionDepth + | _ => 1 + } + + let wrapperStyles = ReactDOMRe.Style.make( + ~display="grid", + ~alignItems="center", + ~justifyItems="center", + (), + ) + + let (width, height, iconSize) = getSize(positionDepth) + +
+ {Array.make(positionDepth * positionDepth, 0) + |> Array.mapi((renderIndex, _) => { + let active = modalityIndices |> Modality.getValue(Position) == renderIndex + Modality.getValue(Color) |> Belt.Option.isSome} + index={modalityIndices |> Modality.getValue(Color)}> + Modality.getValue(Icon) |> Belt.Option.isSome} + index={modalityIndices |> Modality.getValue(Icon)} + size=iconSize + /> + + }) + |> ReasonReact.array} +
+} diff --git a/src/GameCore/GameConfiguration.re b/src/GameCore/GameConfiguration.re deleted file mode 100644 index ab2c1bf..0000000 --- a/src/GameCore/GameConfiguration.re +++ /dev/null @@ -1,31 +0,0 @@ -type gameConfiguration = { - modalities: Modality.modalities(option(int)), - depth: int, -}; - -type t = gameConfiguration; - -let makeDefault = () => { - modalities: { - position: Some(2), - color: Some(4), - icon: Some(4), - }, - depth: 1, -}; - -let updateModality = (modality: Modality.t, value: option(int), config: t) => { - { - ...config, - modalities: - switch (modality) { - | Modality.Position => {...config.modalities, position: value} - | Modality.Color => {...config.modalities, color: value} - | Modality.Icon => {...config.modalities, icon: value} - }, - }; -}; - -let updateDepth = (value: int, config: t) => { - {...config, depth: value}; -}; diff --git a/src/GameCore/GameConfiguration.res b/src/GameCore/GameConfiguration.res new file mode 100644 index 0000000..1d2ab51 --- /dev/null +++ b/src/GameCore/GameConfiguration.res @@ -0,0 +1,29 @@ +type gameConfiguration = { + modalities: Modality.modalities>, + depth: int, +} + +type t = gameConfiguration + +let makeDefault = () => { + modalities: { + position: Some(2), + color: Some(4), + icon: Some(4), + }, + depth: 1, +} + +let updateModality = (modality: Modality.t, value: option, config: t) => { + ...config, + modalities: switch modality { + | Modality.Position => {...config.modalities, position: value} + | Modality.Color => {...config.modalities, color: value} + | Modality.Icon => {...config.modalities, icon: value} + }, +} + +let updateDepth = (value: int, config: t) => { + ...config, + depth: value, +} diff --git a/src/GameCore/GameState.bs.js b/src/GameCore/GameState.bs.js index edcaf4f..3ee0484 100644 --- a/src/GameCore/GameState.bs.js +++ b/src/GameCore/GameState.bs.js @@ -1,20 +1,20 @@ 'use strict'; -var List = require("bs-platform/lib/js/list.js"); -var $$Array = require("bs-platform/lib/js/array.js"); -var Random = require("bs-platform/lib/js/random.js"); -var Belt_Option = require("bs-platform/lib/js/belt_Option.js"); -var Modality$ReasonReactExamples = require("./Modality/Modality.bs.js"); +var List = require("rescript/lib/js/list.js"); +var $$Array = require("rescript/lib/js/array.js"); +var Random = require("rescript/lib/js/random.js"); +var Belt_Option = require("rescript/lib/js/belt_Option.js"); +var Modality$MultiNBack = require("./Modality/Modality.bs.js"); function makeRandom(configuration) { var modeConfig = configuration.modalities; Random.self_init(undefined); return { - position: Belt_Option.map(Modality$ReasonReactExamples.getValue(/* Position */0, modeConfig), (function (value) { + position: Belt_Option.map(Modality$MultiNBack.getValue(/* Position */0, modeConfig), (function (value) { return Random.$$int(Math.imul(value, value)); })), - color: Belt_Option.map(Modality$ReasonReactExamples.getValue(/* Color */1, modeConfig), Random.$$int), - icon: Belt_Option.map(Modality$ReasonReactExamples.getValue(/* Icon */2, modeConfig), Random.$$int) + color: Belt_Option.map(Modality$MultiNBack.getValue(/* Color */1, modeConfig), Random.$$int), + icon: Belt_Option.map(Modality$MultiNBack.getValue(/* Icon */2, modeConfig), Random.$$int) }; } @@ -36,8 +36,8 @@ function makeEmptyResult(param) { function makeResult(answer, configuration) { return $$Array.fold_left((function (result, modality) { - if (Modality$ReasonReactExamples.getValue(modality, answer)) { - return Modality$ReasonReactExamples.setValue(modality, Modality$ReasonReactExamples.getValue(modality, configuration.modalities), result); + if (Modality$MultiNBack.getValue(modality, answer)) { + return Modality$MultiNBack.setValue(modality, Modality$MultiNBack.getValue(modality, configuration.modalities), result); } else { return result; } @@ -45,20 +45,20 @@ function makeResult(answer, configuration) { position: undefined, color: undefined, icon: undefined - }, Modality$ReasonReactExamples.allModalityTypes); + }, Modality$MultiNBack.allModalityTypes); } function compareToHistory(answer, gameState, stateHistory, configuration) { var oldState = List.nth(stateHistory, configuration.depth - 1 | 0); if ($$Array.for_all((function (modality) { - return compareValue(Modality$ReasonReactExamples.getValue(modality, configuration.modalities), Modality$ReasonReactExamples.getValue(modality, answer), Modality$ReasonReactExamples.getValue(modality, oldState), Modality$ReasonReactExamples.getValue(modality, gameState)); - }), Modality$ReasonReactExamples.allModalityTypes)) { + return compareValue(Modality$MultiNBack.getValue(modality, configuration.modalities), Modality$MultiNBack.getValue(modality, answer), Modality$MultiNBack.getValue(modality, oldState), Modality$MultiNBack.getValue(modality, gameState)); + }), Modality$MultiNBack.allModalityTypes)) { return makeResult(answer, configuration); } } -var getValue = Modality$ReasonReactExamples.getValue; +var getValue = Modality$MultiNBack.getValue; exports.getValue = getValue; exports.makeRandom = makeRandom; diff --git a/src/GameCore/GameState.re b/src/GameCore/GameState.re deleted file mode 100644 index d038b04..0000000 --- a/src/GameCore/GameState.re +++ /dev/null @@ -1,76 +0,0 @@ -type gameState = Modality.modalities(option(int)); - -type t = gameState; - -type stateHistory = list(gameState); - -let getValue = Modality.getValue; - -let makeRandom = (configuration: GameConfiguration.t): t => { - let modeConfig = configuration.modalities; - Random.self_init(); - { - position: - getValue(Position, modeConfig) - ->Belt.Option.map(value => Random.int(value * value)), - color: getValue(Color, modeConfig)->Belt.Option.map(Random.int), - icon: getValue(Icon, modeConfig)->Belt.Option.map(Random.int), - }; -}; - -let compareValue = - ( - modalityConfig: option(int), - modalityAnswer: bool, - modalityOldValue: option(int), - modalityValue: option(int), - ) - : bool => - switch (modalityConfig, modalityAnswer, modalityOldValue, modalityValue) { - | (Some(_), isSame, Some(oldValue), Some(value)) => - oldValue == value == isSame - | _ => true - }; - -type result = Modality.modalities(option(int)); - -let makeEmptyResult = (): result => { - {position: None, color: None, icon: None}; -}; - -let makeResult = - (answer: Answer.t, configuration: GameConfiguration.t): result => { - Modality.allModalityTypes - |> Array.fold_left( - (result, modality) => - answer |> getValue(modality) - ? result - |> Modality.setValue( - modality, - configuration.modalities |> getValue(modality), - ) - : result, - makeEmptyResult(), - ); -}; - -let compareToHistory = - ( - answer: Answer.t, - gameState: t, - stateHistory: stateHistory, - configuration: GameConfiguration.t, - ) - : option(result) => { - let oldState = stateHistory->List.nth(configuration.depth - 1); - Modality.allModalityTypes - |> Array.for_all(modality => - compareValue( - configuration.modalities |> getValue(modality), - answer |> getValue(modality), - oldState |> getValue(modality), - gameState |> getValue(modality), - ) - ) - ? Some(makeResult(answer, configuration)) : None; -}; diff --git a/src/GameCore/GameState.res b/src/GameCore/GameState.res new file mode 100644 index 0000000..95c96a8 --- /dev/null +++ b/src/GameCore/GameState.res @@ -0,0 +1,64 @@ +type gameState = Modality.modalities> + +type t = gameState + +type stateHistory = list + +let getValue = Modality.getValue + +let makeRandom = (configuration: GameConfiguration.t): t => { + let modeConfig = configuration.modalities + Random.self_init() + { + position: getValue(Position, modeConfig)->Belt.Option.map(value => Random.int(value * value)), + color: getValue(Color, modeConfig)->Belt.Option.map(Random.int), + icon: getValue(Icon, modeConfig)->Belt.Option.map(Random.int), + } +} + +let compareValue = ( + modalityConfig: option, + modalityAnswer: bool, + modalityOldValue: option, + modalityValue: option, +): bool => + switch (modalityConfig, modalityAnswer, modalityOldValue, modalityValue) { + | (Some(_), isSame, Some(oldValue), Some(value)) => (oldValue == value) == isSame + | _ => true + } + +type result = Modality.modalities> + +let makeEmptyResult = (): result => { + position: None, + color: None, + icon: None, +} + +let makeResult = (answer: Answer.t, configuration: GameConfiguration.t): result => + Modality.allModalityTypes |> Array.fold_left( + (result, modality) => + answer |> getValue(modality) + ? result |> Modality.setValue(modality, configuration.modalities |> getValue(modality)) + : result, + makeEmptyResult(), + ) + +let compareToHistory = ( + answer: Answer.t, + gameState: t, + stateHistory: stateHistory, + configuration: GameConfiguration.t, +): option => { + let oldState = stateHistory->List.nth(configuration.depth - 1) + Modality.allModalityTypes |> Array.for_all(modality => + compareValue( + configuration.modalities |> getValue(modality), + answer |> getValue(modality), + oldState |> getValue(modality), + gameState |> getValue(modality), + ) + ) + ? Some(makeResult(answer, configuration)) + : None +} diff --git a/src/GameCore/GameState_test.bs.js b/src/GameCore/GameState_test.bs.js index 7adf794..187a19d 100644 --- a/src/GameCore/GameState_test.bs.js +++ b/src/GameCore/GameState_test.bs.js @@ -1,18 +1,18 @@ 'use strict'; -var Jest = require("@glennsl/bs-jest/src/jest.js"); -var GameState$ReasonReactExamples = require("./GameState.bs.js"); +var Jest = require("@glennsl/bs-jest/src/jest.bs.js"); +var GameState$MultiNBack = require("./GameState.bs.js"); Jest.describe("compareValue function", (function (param) { return Jest.describe("when historic value and current value are the same", (function (param) { Jest.describe("when user's answer for `is same` is true", (function (param) { return Jest.test("should return true", (function (param) { - return Jest.Expect.toBe(true, Jest.Expect.expect(GameState$ReasonReactExamples.compareValue(4, true, 1, 1))); + return Jest.Expect.toBe(true, Jest.Expect.expect(GameState$MultiNBack.compareValue(4, true, 1, 1))); })); })); return Jest.describe("when user's answer for `is same` is false", (function (param) { return Jest.test("should return false", (function (param) { - return Jest.Expect.toBe(false, Jest.Expect.expect(GameState$ReasonReactExamples.compareValue(4, true, 1, 2))); + return Jest.Expect.toBe(false, Jest.Expect.expect(GameState$MultiNBack.compareValue(4, true, 1, 2))); })); })); })); diff --git a/src/GameCore/GameState_test.re b/src/GameCore/GameState_test.re deleted file mode 100644 index 3008554..0000000 --- a/src/GameCore/GameState_test.re +++ /dev/null @@ -1,21 +0,0 @@ -open Jest; -open Expect; - -open GameState; - -describe("compareValue function", () => { - describe("when historic value and current value are the same", () => { - describe("when user's answer for `is same` is true", () => { - test("should return true", () => { - expect(compareValue(Some(4), true, Some(1), Some(1))) - |> toBe(true) - }) - }); - describe("when user's answer for `is same` is false", () => { - test("should return false", () => { - expect(compareValue(Some(4), true, Some(1), Some(2))) - |> toBe(false) - }) - }); - }) -}); diff --git a/src/GameCore/GameState_test.res b/src/GameCore/GameState_test.res new file mode 100644 index 0000000..ae82438 --- /dev/null +++ b/src/GameCore/GameState_test.res @@ -0,0 +1,19 @@ +open Jest +open Expect + +open GameState + +describe("compareValue function", () => + describe("when historic value and current value are the same", () => { + describe("when user's answer for `is same` is true", () => + test("should return true", () => + expect(compareValue(Some(4), true, Some(1), Some(1))) |> toBe(true) + ) + ) + describe("when user's answer for `is same` is false", () => + test("should return false", () => + expect(compareValue(Some(4), true, Some(1), Some(2))) |> toBe(false) + ) + ) + }) +) diff --git a/src/GameCore/Modality/Color.bs.js b/src/GameCore/Modality/Color.bs.js index 3cf5497..92f8866 100644 --- a/src/GameCore/Modality/Color.bs.js +++ b/src/GameCore/Modality/Color.bs.js @@ -1,7 +1,7 @@ 'use strict'; var React = require("react"); -var Caml_array = require("bs-platform/lib/js/caml_array.js"); +var Caml_array = require("rescript/lib/js/caml_array.js"); var colors = [ "#4e79a7", @@ -24,7 +24,7 @@ function Color(Props) { var height = Props.height; return React.createElement("div", { style: { - backgroundColor: active ? Caml_array.caml_array_get(colors, index) : "#EEEEEE", + backgroundColor: active ? Caml_array.get(colors, index) : "#EEEEEE", display: "flex", height: String(height) + "px", margin: String(width / 5 | 0) + "px", diff --git a/src/GameCore/Modality/Color.re b/src/GameCore/Modality/Color.res similarity index 91% rename from src/GameCore/Modality/Color.re rename to src/GameCore/Modality/Color.res index 4687cad..f836b74 100644 --- a/src/GameCore/Modality/Color.re +++ b/src/GameCore/Modality/Color.res @@ -1,4 +1,4 @@ -let colors = [| +let colors = [ "#4e79a7", "#f28e2c", "#e15759", @@ -9,9 +9,9 @@ let colors = [| "#ff9da7", "#9c755f", "#bab0ab", -|]; +] -[@react.component] +@react.component let make = (~children, ~active: bool, ~index: int, ~width: int, ~height: int) =>
(), )}> children -
; + diff --git a/src/GameCore/Modality/Icon.bs.js b/src/GameCore/Modality/Icon.bs.js index a8a4005..2b48657 100644 --- a/src/GameCore/Modality/Icon.bs.js +++ b/src/GameCore/Modality/Icon.bs.js @@ -1,7 +1,7 @@ 'use strict'; var React = require("react"); -var Caml_array = require("bs-platform/lib/js/caml_array.js"); +var Caml_array = require("rescript/lib/js/caml_array.js"); var icons = [ "M6.05,8.05c-2.73,2.73-2.73,7.15-0.02,9.88c1.47-3.4,4.09-6.24,7.36-7.93c-2.77,2.34-4.71,5.61-5.39,9.32 c2.6,1.23,5.8,0.78,7.95-1.37C19.43,14.47,20,4,20,4S9.53,4.57,6.05,8.05z", @@ -32,7 +32,7 @@ function Icon(Props) { width: "24", fill: "none" })), React.createElement("g", undefined, React.createElement("g", undefined, React.createElement("path", { - d: Caml_array.caml_array_get(icons, index) + d: Caml_array.get(icons, index) })))); } else { return null; diff --git a/src/GameCore/Modality/Icon.re b/src/GameCore/Modality/Icon.res similarity index 96% rename from src/GameCore/Modality/Icon.re rename to src/GameCore/Modality/Icon.res index 059b749..9d3af7e 100644 --- a/src/GameCore/Modality/Icon.re +++ b/src/GameCore/Modality/Icon.res @@ -1,4 +1,4 @@ -let icons = [| +let icons = [ "M6.05,8.05c-2.73,2.73-2.73,7.15-0.02,9.88c1.47-3.4,4.09-6.24,7.36-7.93c-2.77,2.34-4.71,5.61-5.39,9.32 c2.6,1.23,5.8,0.78,7.95-1.37C19.43,14.47,20,4,20,4S9.53,4.57,6.05,8.05z", "M22,16v-2l-8.5-5V3.5C13.5,2.67,12.83,2,12,2s-1.5,0.67-1.5,1.5V9L2,14v2l8.5-2.5V19L8,20.5L8,22l4-1l4,1l0-1.5L13.5,19 v-5.5L22,16z", "M13.127 14.56l1.43-1.43 6.44 6.443L19.57 21zm4.293-5.73l2.86-2.86c-3.95-3.95-10.35-3.96-14.3-.02 3.93-1.3 8.31-.25 11.44 2.88zM5.95 5.98c-3.94 3.95-3.93 10.35.02 14.3l2.86-2.86C5.7 14.29 4.65 9.91 5.95 5.98zm.02-.02l-.01.01c-.38 3.01 1.17 6.88 4.3 10.02l5.73-5.73c-3.13-3.13-7.01-4.68-10.02-4.3z", @@ -9,10 +9,10 @@ let icons = [| "M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95c-.32-1.25-.78-2.45-1.38-3.56 1.84.63 3.37 1.91 4.33 3.56zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56-1.84-.63-3.37-1.9-4.33-3.56zm2.95-8H5.08c.96-1.66 2.49-2.93 4.33-3.56C8.81 5.55 8.35 6.75 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95c-.96 1.65-2.49 2.93-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z", "M18 3v2h-2V3H8v2H6V3H4v18h2v-2h2v2h8v-2h2v2h2V3h-2zM8 17H6v-2h2v2zm0-4H6v-2h2v2zm0-4H6V7h2v2zm10 8h-2v-2h2v2zm0-4h-2v-2h2v2zm0-4h-2V7h2v2z", "M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z", -|]; +] -[@react.component] -let make = (~index: int, ~active: bool, ~size: int) => { +@react.component +let make = (~index: int, ~active: bool, ~size: int) => active ? { viewBox="0 0 24 24" width={string_of_int(size) ++ "px"}> - + - : React.null; -}; + : React.null diff --git a/src/GameCore/Modality/Modality.bs.js b/src/GameCore/Modality/Modality.bs.js index 05aa533..f650abe 100644 --- a/src/GameCore/Modality/Modality.bs.js +++ b/src/GameCore/Modality/Modality.bs.js @@ -51,8 +51,8 @@ function setValue(modality, value, modalities) { } } -function getLabel(param) { - switch (param) { +function getLabel(x) { + switch (x) { case /* Position */0 : return "Position"; case /* Color */1 : diff --git a/src/GameCore/Modality/Modality.re b/src/GameCore/Modality/Modality.res similarity index 62% rename from src/GameCore/Modality/Modality.re rename to src/GameCore/Modality/Modality.res index 710669a..0850a2b 100644 --- a/src/GameCore/Modality/Modality.re +++ b/src/GameCore/Modality/Modality.res @@ -1,38 +1,37 @@ type modality = | Position | Color - | Icon; + | Icon -type t = modality; +type t = modality -let allModalityTypes = [|Position, Color, Icon|]; +let allModalityTypes = [Position, Color, Icon] -type modalities('a) = { +type modalities<'a> = { position: 'a, color: 'a, icon: 'a, -}; +} -let make = (value: 'a) => {position: value, color: value, icon: value}; +let make = (value: 'a) => {position: value, color: value, icon: value} -let getValue = (modality: modality, modalities: modalities('a)) => { - switch (modality) { +let getValue = (modality: modality, modalities: modalities<'a>) => + switch modality { | Position => modalities.position | Color => modalities.color | Icon => modalities.icon - }; -}; + } -let setValue = (modality: modality, value: 'a, modalities: modalities('a)) => { - switch (modality) { +let setValue = (modality: modality, value: 'a, modalities: modalities<'a>) => + switch modality { | Position => {...modalities, position: value} | Color => {...modalities, color: value} | Icon => {...modalities, icon: value} - }; -}; + } -let getLabel = - fun +let getLabel = x => + switch x { | Position => "Position" | Color => "Color" - | Icon => "Icon"; + | Icon => "Icon" + } diff --git a/src/GameCore/Score.bs.js b/src/GameCore/Score.bs.js index 5a5ebf0..13c210f 100644 --- a/src/GameCore/Score.bs.js +++ b/src/GameCore/Score.bs.js @@ -1,10 +1,10 @@ 'use strict'; -var $$Array = require("bs-platform/lib/js/array.js"); -var Pervasives = require("bs-platform/lib/js/pervasives.js"); -var Belt_Option = require("bs-platform/lib/js/belt_Option.js"); -var Caml_option = require("bs-platform/lib/js/caml_option.js"); -var Modality$ReasonReactExamples = require("./Modality/Modality.bs.js"); +var $$Array = require("rescript/lib/js/array.js"); +var Pervasives = require("rescript/lib/js/pervasives.js"); +var Belt_Option = require("rescript/lib/js/belt_Option.js"); +var Caml_option = require("rescript/lib/js/caml_option.js"); +var Modality$MultiNBack = require("./Modality/Modality.bs.js"); var highScoreKey = "multi_n_back_hight_score"; @@ -15,13 +15,13 @@ function setHighScore(score) { function calculateScore(result, depth) { return Math.imul((depth << 1), $$Array.fold_left((function (acc, cur) { - var value = Modality$ReasonReactExamples.getValue(cur, result); + var value = Modality$MultiNBack.getValue(cur, result); if (value !== undefined) { return Math.imul(acc, value); } else { return acc; } - }), 1, Modality$ReasonReactExamples.allModalityTypes)); + }), 1, Modality$MultiNBack.allModalityTypes)); } function getHighScore(param) { diff --git a/src/GameCore/Score.re b/src/GameCore/Score.re deleted file mode 100644 index 12f4568..0000000 --- a/src/GameCore/Score.re +++ /dev/null @@ -1,39 +0,0 @@ -[@bs.val] -external getFromLocalStorage: (~key: string) => Js.Nullable.t(string) = - "window.localStorage.getItem"; - -[@bs.val] -external setInLocalStorage: (~key: string, ~value: string) => unit = - "window.localStorage.setItem"; - -let highScoreKey = "multi_n_back_hight_score"; -let getHighScore = (): option(string) => - getFromLocalStorage(~key=highScoreKey) |> Js.Nullable.toOption; -let setHighScore = (score: int) => { - setInLocalStorage(~key=highScoreKey, ~value=string_of_int(score)); - score; -}; - -let calculateScore = (result: GameState.result, depth: int): int => { - Modality.allModalityTypes - |> Array.fold_left( - (acc, cur) => - switch (result |> Modality.getValue(cur)) { - | Some(value) => acc * value - | None => acc - }, - 1, - ) - |> ( * )(depth * 2); -}; - -let getHighScore = (): option(int) => { - getHighScore()->Belt.Option.flatMap(int_of_string_opt); -}; - -let updateHighScore = (score: int): int => { - switch (getHighScore()) { - | Some(value) => value > score ? value : setHighScore(score) - | None => setHighScore(score) - }; -}; diff --git a/src/GameCore/Score.res b/src/GameCore/Score.res new file mode 100644 index 0000000..c12dca2 --- /dev/null +++ b/src/GameCore/Score.res @@ -0,0 +1,30 @@ +@val +external getFromLocalStorage: (~key: string) => Js.Nullable.t = + "window.localStorage.getItem" + +@val +external setInLocalStorage: (~key: string, ~value: string) => unit = "window.localStorage.setItem" + +let highScoreKey = "multi_n_back_hight_score" +let getHighScore = (): option => + getFromLocalStorage(~key=highScoreKey) |> Js.Nullable.toOption +let setHighScore = (score: int) => { + setInLocalStorage(~key=highScoreKey, ~value=string_of_int(score)) + score +} + +let calculateScore = (result: GameState.result, depth: int): int => + Modality.allModalityTypes |> Array.fold_left((acc, cur) => + switch result |> Modality.getValue(cur) { + | Some(value) => acc * value + | None => acc + } + , 1) |> \"*"(depth * 2) + +let getHighScore = (): option => getHighScore()->Belt.Option.flatMap(int_of_string_opt) + +let updateHighScore = (score: int): int => + switch getHighScore() { + | Some(value) => value > score ? value : setHighScore(score) + | None => setHighScore(score) + } diff --git a/src/Index.bs.js b/src/Index.bs.js index c23356a..51d5535 100644 --- a/src/Index.bs.js +++ b/src/Index.bs.js @@ -2,14 +2,29 @@ var React = require("react"); var ReactDom = require("react-dom"); -var App$ReasonReactExamples = require("./App.bs.js"); -var AppStyles$ReasonReactExamples = require("./AppStyles.bs.js"); +var App$MultiNBack = require("./App.bs.js"); +var AppStyles$MultiNBack = require("./AppStyles.bs.js"); + +var $$Element = {}; + +var $$Document = {}; + +var Webapi = { + $$Element: $$Element, + $$Document: $$Document +}; var style = document.createElement("style"); document.head.appendChild(style); -style.innerHTML = AppStyles$ReasonReactExamples.style; +style.innerHTML = AppStyles$MultiNBack.style; + +var body = document.body; + +var root = document.createElement("div"); + +body.appendChild(root); function makeContainer(param) { var container = document.createElement("div"); @@ -21,8 +36,11 @@ function makeContainer(param) { return content; } -ReactDom.render(React.createElement(App$ReasonReactExamples.make, {}), makeContainer(undefined)); +ReactDom.render(React.createElement(App$MultiNBack.make, {}), makeContainer(undefined)); +exports.Webapi = Webapi; exports.style = style; +exports.body = body; +exports.root = root; exports.makeContainer = makeContainer; /* style Not a pure module */ diff --git a/src/Index.re b/src/Index.re deleted file mode 100644 index 9d64040..0000000 --- a/src/Index.re +++ /dev/null @@ -1,25 +0,0 @@ -// Entry point - -[@bs.val] external document: Js.t({..}) = "document"; - -// We're using raw DOM manipulations here, to avoid making you read -// ReasonReact when you might precisely be trying to learn it for the first -// time through the examples later. -let style = document##createElement("style"); -document##head##appendChild(style); -style##innerHTML #= AppStyles.style; - -let makeContainer = () => { - let container = document##createElement("div"); - container##className #= "container"; - - let content = document##createElement("div"); - content##className #= "contentContainer"; - - let () = container##appendChild(content); - let () = document##body##appendChild(container); - - content; -}; - -ReactDOMRe.render(, makeContainer()); diff --git a/src/Index.res b/src/Index.res new file mode 100644 index 0000000..9292829 --- /dev/null +++ b/src/Index.res @@ -0,0 +1,47 @@ +// Entry point + +module Webapi = { + module Element = { + @set external setId: (Dom.element, string) => unit = "id" + @set external innerHTML: (Dom.element, string) => () = "innerHTML" + @set external className: (Dom.element, string) => () = "className" + @send external appendChild: (Dom.element, Dom.element) => unit = "appendChild" + } + + module Document = { + @val external document: Dom.document = "document" + @get external body: Dom.document => Dom.element = "body" + @get external head: Dom.document => Dom.element = "head" + @send external createElement: (Dom.document, string) => Dom.element = "createElement" + } +} + +open Webapi + +let style = Document.document -> Document.createElement("style") +Document.document -> Document.head -> Element.appendChild(style) +style -> Element.innerHTML(AppStyles.style) + +let body = { + open Document + document->body +} + +let root = Document.document -> Document.createElement("div") + +Element.appendChild(body, root) + +let makeContainer = () => { + let container = Document.document -> Document.createElement("div") + container -> Element.className("container") + + let content = Document.document -> Document.createElement("div") + content -> Element.className("contentContainer") + + let () = container -> Element.appendChild(content) + let () = Document.document -> Document.body -> Element.appendChild(container) + + content +} + +ReactDOMRe.render(, makeContainer()) diff --git a/src/Interface/AnswerToggle.bs.js b/src/Interface/AnswerToggle.bs.js index 8f85b0d..bdf7532 100644 --- a/src/Interface/AnswerToggle.bs.js +++ b/src/Interface/AnswerToggle.bs.js @@ -1,7 +1,7 @@ 'use strict'; var React = require("react"); -var AppStyles$ReasonReactExamples = require("../AppStyles.bs.js"); +var AppStyles$MultiNBack = require("../AppStyles.bs.js"); function AnswerToggle(Props) { var checked = Props.checked; @@ -15,7 +15,7 @@ function AnswerToggle(Props) { position: "relative", width: "10em", borderRadius: "10px", - boxShadow: checked ? "inset 2px 2px 6px " + (AppStyles$ReasonReactExamples.background_less_darker + (", inset -2px -2px 6px " + AppStyles$ReasonReactExamples.background_less_lighter)) : "8px 8px 20px " + (AppStyles$ReasonReactExamples.background_more_darker + (", -8px -8px 20px " + AppStyles$ReasonReactExamples.background_more_lighter)), + boxShadow: checked ? "inset 2px 2px 6px " + (AppStyles$MultiNBack.background_less_darker + (", inset -2px -2px 6px " + AppStyles$MultiNBack.background_less_lighter)) : "8px 8px 20px " + (AppStyles$MultiNBack.background_more_darker + (", -8px -8px 20px " + AppStyles$MultiNBack.background_more_lighter)), alignItems: "center", justifyContent: "center" } @@ -41,11 +41,11 @@ function AnswerToggle(Props) { position: "relative", width: "10px", borderRadius: "10px", - boxShadow: checked ? "2px 2px 4px " + (AppStyles$ReasonReactExamples.background_less_darker + (", -2px -2px 4px " + (AppStyles$ReasonReactExamples.background_less_lighter + ", 0 0 4px #13EF32"))) : "2px 2px 4px " + (AppStyles$ReasonReactExamples.background_more_darker + (", -2px -2px 4px " + AppStyles$ReasonReactExamples.background_more_lighter)) + boxShadow: checked ? "2px 2px 4px " + (AppStyles$MultiNBack.background_less_darker + (", -2px -2px 4px " + (AppStyles$MultiNBack.background_less_lighter + ", 0 0 4px #13EF32"))) : "2px 2px 4px " + (AppStyles$MultiNBack.background_more_darker + (", -2px -2px 4px " + AppStyles$MultiNBack.background_more_lighter)) } }, React.createElement("div", { style: { - background: checked ? "radial-gradient(#ABEFBC, #13EF32)" : "radial-gradient(" + (AppStyles$ReasonReactExamples.background_less_lighter + (", " + (AppStyles$ReasonReactExamples.background_more_darker + ")"))), + background: checked ? "radial-gradient(#ABEFBC, #13EF32)" : "radial-gradient(" + (AppStyles$MultiNBack.background_less_lighter + (", " + (AppStyles$MultiNBack.background_more_darker + ")"))), height: "15px", left: "-4px", position: "relative", diff --git a/src/Interface/AnswerToggle.re b/src/Interface/AnswerToggle.re deleted file mode 100644 index e42eda9..0000000 --- a/src/Interface/AnswerToggle.re +++ /dev/null @@ -1,82 +0,0 @@ -[@react.component] -let make = (~checked: bool, ~onChange: _ => unit, ~label: string) => -