Extracting logic into separate objects and simplifying dependencies.

master
Ben Burlingham 9 years ago
parent 49baf89a5e
commit faeae93892
  1. 11
      actions/board/grid.actions.js
  2. 42
      actions/board/muncher.actions.js
  3. 81
      components/board/board.component.js
  4. 17
      components/board/grid.component.js
  5. 10
      components/board/message.component.js
  6. 54
      components/board/muncher.component.js
  7. 2
      components/board/titlebar.component.js
  8. 4
      index.js
  9. 67
      logic/board.logic.js
  10. 27
      logic/grid.logic.js
  11. 9
      logic/message.logic.js
  12. 46
      logic/muncher.logic.js
  13. 4
      logic/values.logic.js
  14. 20
      reducers/board/grid.reducer.js
  15. 12
      reducers/board/message.reducer.js
  16. 25
      reducers/board/muncher.reducer.js

@ -0,0 +1,11 @@
export const GRID_ACTION = 'GRID_ACTION';
export const UPDATE = 'UPDATE';
const GridActions = {
update: () => ({
type: GRID_ACTION,
action: UPDATE
})
};
export default GridActions;

@ -1,43 +1,7 @@
export const MUNCHER_ACTION = 'MUNCHER_ACTION';
export const LEFT = 'LEFT';
export const RIGHT = 'RIGHT';
export const UP = 'UP';
export const DOWN = 'DOWN';
export const MUNCH = 'MUNCH';
export const FREEZE = 'FREEZE';
export const UNFREEZE = 'UNFREEZE';
export const UPDATE = 'UPDATE';
export const moveLeft = () => ({
export const update = () => ({
type: MUNCHER_ACTION,
action: LEFT
});
export const moveRight = () => ({
type: MUNCHER_ACTION,
action: RIGHT
});
export const moveUp = () => ({
type: MUNCHER_ACTION,
action: UP
});
export const moveDown = () => ({
type: MUNCHER_ACTION,
action: DOWN
});
export const munch = (x, y) => ({
type: MUNCHER_ACTION,
action: MUNCH
});
export const freeze = () => ({
type: MUNCHER_ACTION,
action: FREEZE
});
export const unfreeze = () => ({
type: MUNCHER_ACTION,
action:UNFREEZE
action: UPDATE
});

@ -2,7 +2,7 @@ require('../../sass/board/board.scss');
import { Component } from 'react';
import { connect } from 'react-redux';
import { getState } from 'react-redux';
import Scorebar from './scorebar.component';
import Titlebar from './titlebar.component';
import Grid from './grid.component';
@ -10,82 +10,33 @@ import Message from './message.component';
import Muncher from './muncher.component';
import Troggles from './troggles.component';
import ValuesLogic from '../../logic/values.logic.js';
import TroggleLogic from '../../logic/troggle.logic.js';
import { SETTINGS } from '../../App';
import * as BoardActions from '../../actions/board/board.actions';
import * as ScorebarActions from '../../actions/board/scorebar.actions';
import * as MessageActions from '../../actions/board/message.actions';
import * as MuncherActions from '../../actions/board/muncher.actions';
import BoardLogic from '../../logic/board.logic';
let nextLevelFlag = false;
let listener;
export default class Board extends Component {
export class Board extends Component {
componentDidMount() {
this.nextLevel();
};
nextLevel() {
this.props.dispatch(BoardActions.nextLevel());
TroggleLogic.clearAll(this.props.dispatch);
TroggleLogic.createTroggles(this.props.dispatch);
};
BoardLogic.setDispatch(this.props.dispatch);
BoardLogic.nextLevel();
messageNext() {
if (nextLevelFlag === true) {
this.nextLevel();
nextLevelFlag = false;
}
this.props.dispatch(MessageActions.hide());
ReactDOM.findDOMNode(this.refs.muncher).focus();
listener = BoardLogic.keyListener.bind(BoardLogic);
window.addEventListener('keydown', listener);
};
muncherNext(x, y) {
const index = y * SETTINGS.GRID_WIDTH + x;
if (this.props.values[index].valid) {
this.props.dispatch(BoardActions.hideValue(index));
this.props.dispatch(ScorebarActions.munchSucceeded());
// State will not have been updated; temporary state created for checking.
const tmp = this.props.values.slice(0);
tmp[index].show = false;
if (ValuesLogic.checkComplete(tmp, this.props.level)) {
nextLevelFlag = true;
this.props.dispatch(MessageActions.exclaim());
ReactDOM.findDOMNode(this.refs.message).focus();
}
}
else {
const msg = ValuesLogic.getError(this.props.values[index].value, this.props.level);
this.props.dispatch(MessageActions.show(msg));
this.props.dispatch(ScorebarActions.munchFailed());
ReactDOM.findDOMNode(this.refs.message).focus();
}
//
// if (troggles[i].x === muncher.x && troggles[i].y === muncher.y) {
// this.props.dispatch(MessageActions.show("You've been eaten by a troggle!"));
// this.props.dispatch(ScorebarActions.munchFailed());
// TroggleLogic.frozen = true;
// ReactDOM.findDOMNode(this.refs.message).focus();
// }
componentWillUnmount() {
window.removeEventListener('keydown', listener);
};
render() {
return (<div className='board'>
<Scorebar />
<Titlebar title={this.props.title} />
<Message ref='message' next={this.messageNext.bind(this)} />
<Grid values={this.props.values} />
<Muncher ref='muncher' onMunch={this.muncherNext.bind(this)} />
<Troggles ref='troggles' />
<Muncher />
<Message />
<Titlebar />
<Grid />
<Troggles />
</div>);
};
};
const select = (state) => {
return state.board;
}
export default connect(select)(Board);
export default connect()(Board)

@ -1,10 +1,17 @@
require('../../sass/board/grid.scss');
import { Component } from 'react';
import { connect } from 'react-redux';
import GridCell from './grid-cell.component';
import GridActions from '../../actions/board/grid.actions';
import { SETTINGS } from '../../App';
export default class Grid extends Component {
export class Grid extends Component {
componentDidMount() {
this.props.dispatch(GridActions.update());
};
render() {
const { values } = this.props.values;
const cells = [];
@ -18,3 +25,11 @@ export default class Grid extends Component {
return (<div className='grid'>{cells}</div>);
};
};
const select = (state) => {
return {
values: state.grid
}
}
export default connect(select)(Grid);

@ -8,12 +8,12 @@ let refocusListener = null;
export class Message extends Component {
componentDidMount() {
refocusListener = this.refocus.bind(this);
window.addEventListener('click', refocusListener);
// refocusListener = this.refocus.bind(this);
// window.addEventListener('click', refocusListener);
};
componentWillUnmount() {
window.removeEventListener('click', refocusListener);
// window.removeEventListener('click', refocusListener);
};
refocus() {
@ -33,8 +33,10 @@ export class Message extends Component {
classname.push('hidden');
}
//<div className={classname.join(' ')} tabIndex='1' onKeyDown={this.keydown.bind(this)}>
return (
<div className={classname.join(' ')} tabIndex='1' onKeyDown={this.keydown.bind(this)}>
<div className={classname.join(' ')}>
{this.props.message}
<br />
Press Spacebar to continue.

@ -2,65 +2,13 @@ require('../../sass/board/muncher.scss');
import { Component } from 'react';
import { connect } from 'react-redux';
import * as MuncherActions from '../../actions/board/muncher.actions';
import { SETTINGS } from '../../App';
let focusListener = null;
export class Muncher extends Component {
componentDidMount() {
this.focus();
focusListener = this.focus.bind(this);
window.addEventListener('click', focusListener);
};
componentWillUnmount() {
window.removeEventListener('click', focusListener);
};
focus() {
ReactDOM.findDOMNode(this).focus();
};
keydown(e) {
const x = this.props.x;
const y = this.props.y;
switch (e.keyCode) {
case 32:
this.props.onMunch(x, y);
break;
case 37:
if (x !== 0) {
this.props.dispatch(MuncherActions.moveLeft());
}
break;
case 38:
if (y !== 0) {
this.props.dispatch(MuncherActions.moveUp());
}
break;
case 39:
if (x !== SETTINGS.GRID_WIDTH - 1) {
this.props.dispatch(MuncherActions.moveRight());
}
break;
case 40:
if (y !== SETTINGS.GRID_HEIGHT - 1) {
this.props.dispatch(MuncherActions.moveDown());
}
break;
}
};
render() {
const classname = ['muncher', 'x' + this.props.x, 'y' + this.props.y];
return (
<div className={classname.join(' ')} tabIndex='1' onKeyDown={this.keydown.bind(this)}></div>
<div className={classname.join(' ')}></div>
);
};
};

@ -4,6 +4,6 @@ import { Component } from 'react';
export default class Titlebar extends Component {
render() {
return (<div className='titlebar'>{this.props.title}</div>);
return (<div className='titlebar'>Connect titlebar</div>);
};
};

@ -8,6 +8,7 @@ import App from './App';
import modeReducer from './reducers/mode.reducer';
import newgameReducer from './reducers/welcome/new-game.reducer';
import boardReducer from './reducers/board/board.reducer';
import gridReducer from './reducers/board/grid.reducer';
import muncherReducer from './reducers/board/muncher.reducer';
import scorebarReducer from './reducers/board/scorebar.reducer';
import messageReducer from './reducers/board/message.reducer';
@ -20,7 +21,8 @@ const reducers = combineReducers({
scorebar: scorebarReducer,
board: boardReducer,
message: messageReducer,
troggles: troggleReducer
troggles: troggleReducer,
grid: gridReducer
});
const store = createStore(reducers);

@ -0,0 +1,67 @@
import { SETTINGS } from '../App.js';
import * as ScorebarActions from '../actions/board/scorebar.actions';
import * as MessageActions from '../actions/board/message.actions';
import TroggleLogic from './troggle.logic';
import MessageLogic from './message.logic';
import MuncherLogic from './muncher.logic';
import GridLogic from './grid.logic';
const level = 0;
let dispatch;
const BoardLogic = {
setDispatch: (d) => {
dispatch: d,
GridLogic.setDispatch(d);
MuncherLogic.setDispatch(d);
},
munch() {
const index = MuncherLogic.getY() * SETTINGS.GRID_WIDTH + MuncherLogic.getX();
if (GridLogic.getValues()[index].valid) {
GridLogic.hideValue(index);
if (GridLogic.isCompleted() === true) {
dispatch(MessageActions.exclaim());
}
}
else {
const msg = Values.getError(values[index].value, level);
dispatch(MessageActions.show(msg));
}
},
keyListener(e) {
if (e.keyCode === 32 && GridLogic.isCompleted() === true) {
this.nextLevel();
dispatch(MessageActions.hide());
}
else if (e.keyCode === 32 && MessageLogic.isShowing() === true) {
dispatch(MessageActions.hide());
}
else if (e.keyCode === 32 && MessageLogic.isShowing() === false) {
this.munch();
}
else if (MessageLogic.isShowing() === false) {
MuncherLogic.move(e);
}
},
nextLevel() {
GridLogic.generateValues(level);
// TroggleLogic.clearAll(this.props.dispatch);
// TroggleLogic.createTroggles(this.props.dispatch);
},
// if (troggles[i].x === muncher.x && troggles[i].y === muncher.y) {
// this.props.dispatch(MessageActions.show("You've been eaten by a troggle!"));
// this.props.dispatch(ScorebarActions.munchFailed());
// TroggleLogic.frozen = true;
// ReactDOM.findDOMNode(this.refs.message).focus();
// }
};
export default BoardLogic;

@ -0,0 +1,27 @@
import GridActions from '../actions/board/grid.actions';
import ValuesLogic from './values.logic';
import { SETTINGS } from '../App';
let values;
let dispatch;
const GridLogic = {
setDispatch: d => dispatch = d,
getValues: () => values,
generateValues: (level) => {
values = ValuesLogic.generate(SETTINGS.GRID_WIDTH * SETTINGS.GRID_HEIGHT, level);
dispatch(GridActions.update());
},
isCompleted: (level) => {
return ValuesLogic.checkComplete(values, level)
},
hideValue: (index) => {
values[index].show = false;
dispatch(GridActions.update());
}
};
export default GridLogic;

@ -0,0 +1,9 @@
let show = false;
const MessageLogic = {
hide: () => show = false,
show: () => show = true,
isShowing: () => show
};
export default MessageLogic;

@ -0,0 +1,46 @@
import * as MuncherActions from '../actions/board/muncher.actions';
import { SETTINGS } from '../App';
let x = 0;
let y = 0;
let dispatch;
const MuncherLogic = {
getX: () => x,
getY: () => y,
setDispatch: d => dispatch = d,
move: (e) => {
switch (e.keyCode) {
case 37:
if (x !== 0) {
x -= 1;
dispatch(MuncherActions.update());
}
break;
case 38:
if (y !== 0) {
y -= 1;
dispatch(MuncherActions.update());
}
break;
case 39:
if (x !== SETTINGS.GRID_WIDTH - 1) {
x += 1;
dispatch(MuncherActions.update());
}
break;
case 40:
if (y !== SETTINGS.GRID_HEIGHT - 1) {
y += 1;
dispatch(MuncherActions.update());
}
break;
}
}
};
export default MuncherLogic;

@ -4,7 +4,7 @@ const validate = function(value, level) {
return ((value || -1) % (level + 2) === 0);
};
const Values = {
const ValuesLogic = {
// Anagrams, multiples, equality
generate(n, level) {
const values = [];
@ -41,4 +41,4 @@ const Values = {
}
};
export default Values;
export default ValuesLogic;

@ -0,0 +1,20 @@
const Immutable = require('immutable');
import * as GridActions from '../../actions/board/grid.actions';
import GridLogic from '../../logic/grid.logic.js';
const initial = [];
const reducer = (state = initial, action) => {
if (action.type !== GridActions.GRID_ACTION) {
return state;
}
if (action.action === GridActions.UPDATE) {
return Immutable.List(GridLogic.getValues()).toArray();
}
return state;
};
export default reducer;

@ -1,5 +1,8 @@
const Immutable = require('immutable');
import * as MessageActions from '../../actions/board/message.actions';
import MessageLogic from '../../logic/message.logic';
const exclamations = [
'Congratulations!',
'Yippee!',
@ -11,9 +14,6 @@ const exclamations = [
'Shazam!'
];
import * as MessageActions from '../../actions/board/message.actions';
import TroggleLogic from '../../logic/troggle.logic.js';
const initial = { message: '', hidden: true };
const reducer = (state = initial, action) => {
@ -23,7 +23,7 @@ const reducer = (state = initial, action) => {
switch (action.action) {
case MessageActions.EXCLAIM:
TroggleLogic.frozen = true;
MessageLogic.show();
const msg = exclamations[Math.floor(Math.random() * exclamations.length)];
return Immutable.Map(state)
.set('hidden', false)
@ -31,14 +31,14 @@ const reducer = (state = initial, action) => {
.toObject();
case MessageActions.SHOW:
TroggleLogic.frozen = true;
MessageLogic.show();
return Immutable.Map(state)
.set('hidden', false)
.set('message', action.message)
.toObject();
case MessageActions.HIDE:
TroggleLogic.frozen = false;
MessageLogic.hide();
return Immutable.Map(state)
.set('hidden', true)
.toObject();

@ -1,5 +1,6 @@
const Immutable = require('immutable');
import * as MuncherActions from '../../actions/board/muncher.actions';
import MuncherLogic from '../../logic/muncher.logic';
import { SETTINGS } from '../../App';
const initial = { x: 0, y: 0, frozen: false };
@ -9,24 +10,12 @@ const reducer = (state = initial, action) => {
return state;
}
switch (action.action) {
case MuncherActions.LEFT:
return Immutable.Map(state).set('x', state.x - 1).toObject();
case MuncherActions.RIGHT:
return Immutable.Map(state).set('x', state.x + 1).toObject();
case MuncherActions.UP:
return Immutable.Map(state).set('y', state.y - 1).toObject();
case MuncherActions.DOWN:
return Immutable.Map(state).set('y', state.y + 1).toObject();
case MuncherActions.FREEZE:
return Immutable.Map(state).set('frozen', true).toObject();
case MuncherActions.UNFREEZE:
return Immutable.Map(state).set('frozen', false).toObject();
if (action.action === MuncherActions.UPDATE) {
return Immutable.Map(state)
.set('x', MuncherLogic.getX())
.set('y', MuncherLogic.getY())
.set('frozen', false)
.toObject();
}
return state;

Loading…
Cancel
Save