diff --git a/App.js b/App.js
index 15b712e..357b4fc 100644
--- a/App.js
+++ b/App.js
@@ -3,8 +3,9 @@ import { connect } from 'react-redux';
import * as ModeActions from './actions/mode.actions';
-import Board from './components/board/board.component';
import Welcome from './components/welcome/welcome.component';
+import Options from './components/options/options.component';
+import Board from './components/board/board.component';
export class App extends Component {
render() {
@@ -13,6 +14,8 @@ export class App extends Component {
switch (this.props.mode) {
case ModeActions.WELCOME:
return ;
+ case ModeActions.OPTIONS:
+ return
case ModeActions.BOARD:
return ;
}
diff --git a/actions/mode.actions.js b/actions/mode.actions.js
index 518517b..dd2df06 100644
--- a/actions/mode.actions.js
+++ b/actions/mode.actions.js
@@ -1,6 +1,7 @@
// Game mode actions and action creators.
export const MODE_ACTION = 'MODE_ACTION';
export const WELCOME = 'MODE_WELCOME';
+export const OPTIONS = 'MODE_OPTIONS';
export const BOARD = 'MODE_BOARD';
export const welcome = () => ({
@@ -8,6 +9,11 @@ export const welcome = () => ({
action: WELCOME
});
+export const options = () => ({
+ type: MODE_ACTION,
+ action: OPTIONS
+});
+
export const board = () => ({
type: MODE_ACTION,
action: BOARD
diff --git a/actions/options/options.actions.js b/actions/options/options.actions.js
new file mode 100644
index 0000000..b0e59ac
--- /dev/null
+++ b/actions/options/options.actions.js
@@ -0,0 +1,8 @@
+export const OPTIONS_ACTION = 'OPTIONS_ACTION';
+export const UPDATE = 'OPTIONS_UPDATE';
+
+export const update = (selected) => ({
+ type: OPTIONS_ACTION,
+ action: UPDATE,
+ selected: selected
+});
diff --git a/components/options/option.component.js b/components/options/option.component.js
new file mode 100644
index 0000000..e9c1031
--- /dev/null
+++ b/components/options/option.component.js
@@ -0,0 +1,25 @@
+import { Component } from 'react';
+import { connect } from 'react-redux';
+
+export class Option extends Component {
+ render() {
+ const className = ['option'];
+ console.log(this.props.selected + ' ' + this.props.index)
+
+ if (this.props.selected === this.props.index) {
+ className.push('selected');
+ }
+
+ return (
+
{this.props.value}
+ );
+ };
+};
+
+const select = (state) => {
+ return {
+ selected: state.options
+ };
+};
+
+export default connect(select)(Option);
diff --git a/components/options/options.component.js b/components/options/options.component.js
new file mode 100644
index 0000000..6956356
--- /dev/null
+++ b/components/options/options.component.js
@@ -0,0 +1,26 @@
+require('../../sass/options/options.scss');
+
+import { Component } from 'react';
+import Option from './option.component';
+
+export default class Options extends Component {
+ render() {
+ const values = ['Multiples', 'Factors', 'Equality', 'Inequality'];
+ const optionsElements = [];
+
+ values.map((v, i) => {
+ optionsElements.push();
+ });
+
+ return (
+
+
Which game would you like to play?
+
+
Use the arrow keys to move.
+
Press spacebar to select.
+
+ {optionsElements}
+
+ );
+ };
+};
diff --git a/components/welcome/new-game.component.js b/components/welcome/new-game.component.js
index 42c1510..768cbac 100644
--- a/components/welcome/new-game.component.js
+++ b/components/welcome/new-game.component.js
@@ -27,7 +27,7 @@ export default class NewGame extends Component {
handleKeydown(e) {
if (e.keyCode === 32) {
- this.props.dispatch(ModeActions.board());
+ this.props.dispatch(ModeActions.options());
}
};
diff --git a/controllers/grid.controller.js b/controllers/grid.controller.js
index 6921d82..7e5131d 100644
--- a/controllers/grid.controller.js
+++ b/controllers/grid.controller.js
@@ -1,5 +1,5 @@
import * as GridActions from '../actions/board/grid.actions';
-import ValuesCtrl from './values.controller';
+import MultiplesModel from '../models/multiples.model';
import SETTINGS from '../AppSettings';
let values;
@@ -10,12 +10,12 @@ const GridCtrl = {
getValues: () => values,
generateValues: (level) => {
- values = ValuesCtrl.generate(SETTINGS.GRID_WIDTH * SETTINGS.GRID_HEIGHT, level);
+ values = MultiplesModel.generate(SETTINGS.GRID_WIDTH * SETTINGS.GRID_HEIGHT, level);
dispatch(GridActions.update(values));
},
isCompleted: (level) => {
- return ValuesCtrl.checkComplete(values, level)
+ return MultiplesModel.checkComplete(values, level)
},
hideValue: (index) => {
diff --git a/controllers/titlebar.controller.js b/controllers/titlebar.controller.js
index f046911..7f8fb3a 100644
--- a/controllers/titlebar.controller.js
+++ b/controllers/titlebar.controller.js
@@ -1,5 +1,5 @@
import * as TitlebarActions from '../actions/board/titlebar.actions';
-import ValuesCtrl from './values.controller';
+import MultiplesModel from '../models/multiples.model';
let dispatch;
@@ -7,7 +7,7 @@ const TitlebarCtrl = {
setDispatch: d => dispatch = d,
setTitle: (level) => {
- const title = ValuesCtrl.getTitle(level);
+ const title = MultiplesModel.getTitle(level);
dispatch(TitlebarActions.update(title));
}
};
diff --git a/index.js b/index.js
index 5393bd9..86198cc 100644
--- a/index.js
+++ b/index.js
@@ -13,6 +13,7 @@ import scorebarReducer from './reducers/board/scorebar.reducer';
import messageReducer from './reducers/board/message.reducer';
import troggleReducer from './reducers/board/troggle.reducer';
import titlebarReducer from './reducers/board/titlebar.reducer';
+import optionsReducer from './reducers/options/options.reducer';
const reducers = combineReducers({
mode: modeReducer,
@@ -22,7 +23,8 @@ const reducers = combineReducers({
message: messageReducer,
troggles: troggleReducer,
grid: gridReducer,
- titlebar: titlebarReducer
+ titlebar: titlebarReducer,
+ options: optionsReducer
});
const store = createStore(reducers);
diff --git a/controllers/values.controller.js b/models/equality.model.js
similarity index 79%
rename from controllers/values.controller.js
rename to models/equality.model.js
index 2f104e4..710f65a 100644
--- a/controllers/values.controller.js
+++ b/models/equality.model.js
@@ -1,8 +1,4 @@
-const validate = function(value, level) {
- return ((value || -1) % (level + 2) === 0);
-};
-
-const ValuesCtrl = {
+const MultiplesModel = {
// Anagrams, multiples, equality
generate(n, level) {
const values = [];
@@ -13,7 +9,7 @@ const ValuesCtrl = {
values.push({
value: v,
show: true,
- valid: validate(v, level)
+ valid: this.validate(v, level)
});
};
@@ -37,6 +33,10 @@ const ValuesCtrl = {
return true;
}
+
+ validate(value, level) {
+ return ((value || -1) % (level + 2) === 0);
+ };
};
-export default ValuesCtrl;
+export default MultiplesModel;
diff --git a/models/factors.model.js b/models/factors.model.js
new file mode 100644
index 0000000..362ab31
--- /dev/null
+++ b/models/factors.model.js
@@ -0,0 +1,42 @@
+const MultiplesModel = {
+ // Anagrams, multiples, equality
+ generate(n, level) {
+ const values = [];
+ let v;
+
+ for (let i = 0; i < n; i++) {
+ v = Math.ceil(Math.random() * 1000);
+ values.push({
+ value: v,
+ show: true,
+ valid: this.validate(v, level)
+ });
+ };
+
+ return values;
+ },
+
+ getTitle(level) {
+ return `Multiples of ${level + 2}`;
+ },
+
+ getError(value, level) {
+ return `Oops! ${value} is not a multiple of ${level + 2}.`;
+ },
+
+ checkComplete(values, level) {
+ for (let i = 0; i < values.length; i++) {
+ if (values[i].valid === true && values[i].show === true) {
+ return false;
+ }
+ }
+
+ return true;
+ },
+
+ validate(value, level) {
+ return ((value || -1) % (level + 2) === 0);
+ }
+};
+
+export default MultiplesModel;
diff --git a/models/inequality.model.js b/models/inequality.model.js
new file mode 100644
index 0000000..362ab31
--- /dev/null
+++ b/models/inequality.model.js
@@ -0,0 +1,42 @@
+const MultiplesModel = {
+ // Anagrams, multiples, equality
+ generate(n, level) {
+ const values = [];
+ let v;
+
+ for (let i = 0; i < n; i++) {
+ v = Math.ceil(Math.random() * 1000);
+ values.push({
+ value: v,
+ show: true,
+ valid: this.validate(v, level)
+ });
+ };
+
+ return values;
+ },
+
+ getTitle(level) {
+ return `Multiples of ${level + 2}`;
+ },
+
+ getError(value, level) {
+ return `Oops! ${value} is not a multiple of ${level + 2}.`;
+ },
+
+ checkComplete(values, level) {
+ for (let i = 0; i < values.length; i++) {
+ if (values[i].valid === true && values[i].show === true) {
+ return false;
+ }
+ }
+
+ return true;
+ },
+
+ validate(value, level) {
+ return ((value || -1) % (level + 2) === 0);
+ }
+};
+
+export default MultiplesModel;
diff --git a/models/multiples.model.js b/models/multiples.model.js
new file mode 100644
index 0000000..362ab31
--- /dev/null
+++ b/models/multiples.model.js
@@ -0,0 +1,42 @@
+const MultiplesModel = {
+ // Anagrams, multiples, equality
+ generate(n, level) {
+ const values = [];
+ let v;
+
+ for (let i = 0; i < n; i++) {
+ v = Math.ceil(Math.random() * 1000);
+ values.push({
+ value: v,
+ show: true,
+ valid: this.validate(v, level)
+ });
+ };
+
+ return values;
+ },
+
+ getTitle(level) {
+ return `Multiples of ${level + 2}`;
+ },
+
+ getError(value, level) {
+ return `Oops! ${value} is not a multiple of ${level + 2}.`;
+ },
+
+ checkComplete(values, level) {
+ for (let i = 0; i < values.length; i++) {
+ if (values[i].valid === true && values[i].show === true) {
+ return false;
+ }
+ }
+
+ return true;
+ },
+
+ validate(value, level) {
+ return ((value || -1) % (level + 2) === 0);
+ }
+};
+
+export default MultiplesModel;
diff --git a/reducers/mode.reducer.js b/reducers/mode.reducer.js
index d1e9045..862a058 100644
--- a/reducers/mode.reducer.js
+++ b/reducers/mode.reducer.js
@@ -1,6 +1,6 @@
import * as ModeActions from '../actions/mode.actions';
-const initial = ModeActions.WELCOME;
+const initial = ModeActions.OPTIONS;
const reducer = (state = initial, action) => {
if (action.type !== ModeActions.MODE_ACTION) {
diff --git a/reducers/options/options.reducer.js b/reducers/options/options.reducer.js
new file mode 100644
index 0000000..be95739
--- /dev/null
+++ b/reducers/options/options.reducer.js
@@ -0,0 +1,19 @@
+const Immutable = require('immutable');
+
+import * as OptionsActions from '../../actions/options/options.actions';
+
+const initial = 0;
+
+const reducer = (state = initial, action) => {
+ if (action.type !== OptionsActions.OPTIONS_ACTION) {
+ return state;
+ }
+
+ if (action.action === OptionsActions.UPDATE) {
+ return action.selected;
+ }
+
+ return state;
+};
+
+export default reducer;
diff --git a/sass/options/options.scss b/sass/options/options.scss
new file mode 100644
index 0000000..f910f3d
--- /dev/null
+++ b/sass/options/options.scss
@@ -0,0 +1,30 @@
+.options {
+ $w: 600px;
+
+ .line {
+ line-height:50px;
+ margin:5px auto;
+ text-align:center;
+ width:$w;
+ }
+
+ hr {
+ border:0;
+ border-top:1px #ccc solid;
+ margin:50px auto;
+ width:$w;
+ }
+
+ .option {
+ border:1px solid #444;
+ height:50px;
+ line-height:50px;
+ margin:5px auto;
+ text-align:center;
+ width:$w;
+ }
+
+ .selected {
+ background:rgba(17, 250, 87, 0.5);
+ }
+}