Skip to content

Commit

Permalink
Merge pull request #2 from SKatiyar/f/seed
Browse files Browse the repository at this point in the history
F/seed
  • Loading branch information
skatiyar committed Jul 14, 2015
2 parents e84b634 + de0588c commit bb00f11
Show file tree
Hide file tree
Showing 20 changed files with 722 additions and 0 deletions.
2 changes: 2 additions & 0 deletions client/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dist
node_modules
Empty file added client/README.md
Empty file.
3 changes: 3 additions & 0 deletions client/config/development.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"env" : "development"
}
3 changes: 3 additions & 0 deletions client/config/production.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"env" : "production"
}
42 changes: 42 additions & 0 deletions client/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "entrapped",
"version": "1.0.0",
"description": "Tiny little minefield of our dreams.",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server --hot --progress --colors --port 3000",
"build": "webpack --progress --colors"
},
"repository": {
"type": "git",
"url": "https://github.com/SKatiyar/entrapped"
},
"keywords": [
"mine",
"field",
"boom"
],
"author": "Rabi C Shah",
"license": "ISC",
"bugs": {
"url": "https://github.com/SKatiyar/entrapped/issues"
},
"homepage": "https://github.com/SKatiyar/entrapped",
"devDependencies": {
"babel": "^5.6.14",
"babel-core": "^5.6.18",
"babel-loader": "^5.3.1",
"file-loader": "^0.8.4",
"node-libs-browser": "^0.5.2",
"react-hot-loader": "^1.2.8",
"webpack": "^1.10.1",
"webpack-dev-server": "^1.10.1"
},
"dependencies": {
"flux": "^2.0.3",
"object-assign": "^3.0.0",
"react": "^0.13.3",
"react-router": "^0.13.3"
}
}
43 changes: 43 additions & 0 deletions client/src/api/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use strict';

var MinesStore = require('../../src/stores/minestore.js');
var AppDispatcher = require('../dispatchers/app_dispatcher.js');

var _ = require('../../src/utility/utils.js');

var apiUrl = "ws://192.168.0.103:7000";

/* websocket reference */
var conn = null;

module.exports = {
connect: function(nickname) {
console.log('inside connect');
if (window["WebSocket"]) {
conn = new WebSocket(apiUrl + '/players/' + nickname);

conn.onclose = function(evt) {
console.log('connection closed.');
};

conn.onmessage = function(evt) {
//console.log('data from server', evt);
var data = _.getObject(evt.data);

//console.log('data', data);
AppDispatcher.handleServerAction(data);
};
} else {
console.log($("Your browser does not support WebSockets."));
}
},

send: function(data) {
//console.log('sending ', data);
conn.send(data);
},

close: function() {
conn.close();
}
};
28 changes: 28 additions & 0 deletions client/src/app.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use strict';

import React from 'react';
import Router from 'react-router';
import { DefaultRoute, Route, RouteHandler } from 'react-router';

import Home from './components/Home.jsx';
import Minefield from './components/Minefield.jsx';

let App = React.createClass({
render() {
return (
<RouteHandler />
);
}
});

let Routes = (
<Route name="app" path="/" handler={App}>
<Route name="home" path="/home" handler={Home}/>
<Route name="minefield" path="/minefield" handler={Minefield}/>
<DefaultRoute handler={Home} />
</Route>
)

Router.run(Routes, function(Handler) {
React.render(<Handler/>, document.body);
});
72 changes: 72 additions & 0 deletions client/src/components/Blocks.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React from 'react/addons';

import Api from '../api/api.js';
/**
* Returns a random integer between min (inclusive) and max (inclusive)
* Using Math.round() will give you a non-uniform distribution!
*/
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}

class Block extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}

render() {
var cx = React.addons.classSet;
var classes = cx({
'block': true,
'block__visited': this.props.status === 0 || this.props.status === 9,
'block__dead': this.props.status === -2
});

return(
<td className={classes} onClick={this.handleClick}></td>
)
}

handleClick() {
var msg = "data:open:[idx=" + this.props.index + "]:[help=9]";
Api.send(msg);
}
};
Block.propTypes = { status: React.PropTypes.number, index: React.PropTypes.number };
Block.defaultProps = { status: 0, index: 0 };

class Blocks extends React.Component {
constructor(props) {
super(props);
}

render() {
var nodes = [];
var size = this.props.size;

/* construct blocks */
for (var i = 0; i < size; i++) {
var _blocks = [];

for (var j = 0; j < size; j++) {
var index = i * size + j;
_blocks.push(<Block key={'block-' + index} status={this.props.mines[index]} index={index} />);
}

nodes.push((<tr key={'blocks-' + i}>{_blocks}</tr>));
}

return (
<table className="blocks">
<tbody>
{nodes}
</tbody>
</table>
);
}
};
Blocks.propTypes = { size: React.PropTypes.number, mines: React.PropTypes.array };
Blocks.defaultProps = { size: 7, mines: [] }

export default Blocks;
45 changes: 45 additions & 0 deletions client/src/components/Field.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react/addons';

import Blocks from './Blocks.jsx';

class Field extends React.Component {
constructor(props) {
super(props);
}

render() {
var cx = React.addons.classSet;
var classes = cx({
'minefield': true,
'minefield__enemy': this.props.of === "enemy",
'minefield__user': this.props.of === "player"
});

var nodes = [];
for (var i = 1; i <= 5; i++) {
var classname = "fa fa-2x fa-heartbeat heart-icons";

if (i <= this.props.player.life) {
classname = classname + " life-status__active";
}

nodes.push(<i key={"heart" + i} className={classname}></i>);
}

return (
<div className={classes}>
<Blocks size={7} mines={this.props.player.mines} />
<div className="life-status">
<span>
{nodes}
</span>
</div>
<h2 className="minefield__text--instructions">{this.props.player.username}</h2>
</div>
)
}
};
Field.propTypes = { of: React.PropTypes.string, player: React.PropTypes.object };
Field.defaultProps = { of: 'user', player: {} };

export default Field;
25 changes: 25 additions & 0 deletions client/src/components/Home.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';
import { Router, Link } from 'react-router';

import MinesStore from '../stores/minestore.js';

class Home extends React.Component {
handleChange(e) {
MinesStore.addUsername(e.target.value);
}

render() {
return (
<div className="home">
<h1 className="home__title">Entrapped v0.0</h1>
<blockquote>Tiny little minefield of our dreams.</blockquote>
<div className="nickname">
<input className="nickname__input" placeholder="nickname" onChange={this.handleChange}/>
</div>
<Link to="/minefield">Play</Link>
</div>
)
}
};

export default Home;
66 changes: 66 additions & 0 deletions client/src/components/Minefield.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React from 'react';

import Field from './Field.jsx';
import MinesStore from '../stores/minestore.js';
import Api from '../api/api.js';

class Minefield extends React.Component {
constructor() {
super();

this.state = {
player: MinesStore.getUser(),
enemy: MinesStore.getEnemy()
};

// connect
Api.connect(MinesStore.getUsername());
MinesStore.addChangeListener(this._onChange.bind(this));
}

componentWillUnmount() {
MinesStore.removeChangeListener(this._onChange);
}

_onChange() {
this.setState({
player: MinesStore.getUser(),
enemy: MinesStore.getEnemy()
});
}

render() {

var content = (
<div className="minefield__wrapper">
<Field of="enemy" player={this.state.player} />
<Field of="player" player={this.state.enemy} />
</div>
);

if (!this.state.player.mines || !this.state.player.mines.length) {
content = (
<div className="minefield__waiting">
<h1 className="minefield__text--waiting">Waiting for an opponent...</h1>
</div>
);
}

if (!this.state.player.life || !this.state.enemy.life) {
var winner = this.state.player.life ? this.state.player.username : this.state.enemy.username;
content = (
<div className="minefield__waiting">
<h1 className="minefield__text--waiting">Game over. {winner} won.</h1>
</div>
)
}

return (
<div>
{content}
</div>
)
}
};

export default Minefield;
15 changes: 15 additions & 0 deletions client/src/constants/app_constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module.exports = {
ActionTypes : {
GET_MINES_LOAD: null,
GET_MINES_SUCCESS: null,
GET_MINES_FAIL: null,

LOGIN_LOAD: null,
LOGIN_SUCCESS: null,
LOGIN_FAIL: null
},

PayloadSources: {
SERVER_ACTION: "SERVER_ACTION"
}
};
22 changes: 22 additions & 0 deletions client/src/dispatchers/app_dispatcher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
var Dispatcher = require('flux').Dispatcher;
var assign = require('object-assign');

/* constants */
var AppConstants = require('../constants/app_constants.js');
var PayloadSources = AppConstants.PayloadSources;

var AppDispatcher = assign(new Dispatcher(), {
/**
* @param {object} action The details of the action, including the action's
* type and additional data coming from the server.
*/
handleServerAction: function(action) {
var payload = {
source: PayloadSources.SERVER_ACTION,
action: action
};
this.dispatch(payload);
}
});

module.exports = AppDispatcher;
Binary file added client/src/public/font/1942.ttf
Binary file not shown.
Loading

0 comments on commit bb00f11

Please sign in to comment.