diff --git a/assets/js/mine-seeker/app.js b/assets/js/mine-seeker/app.js
index ba85a36..9d22647 100644
--- a/assets/js/mine-seeker/app.js
+++ b/assets/js/mine-seeker/app.js
@@ -3,454 +3,464 @@ import Grid from './grid/grid';
import GridControl from './grid/grid-control';
class MineSeeker extends React.Component {
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- let gameAssoc = props.gameId !== '' ? props.gameId : this.makeGameAssoc(50);
- let channel = "mineseeker/channel/" + gameAssoc;
+ let gameAssoc = '' !== props.gameId ? props.gameId : this.makeGameAssoc(50);
+ let channel = 'mineseeker/channel/' + gameAssoc;
- this.state = {
- env: props.env,
- ssl: props.ssl,
- gameInherited: props.gameId !== '',
- gameAssoc: gameAssoc,
- channel: channel,
- session: null,
- createGrid: false,
- stepCache: [],
- connectionLost: false,
- end: false
- }
+ this.state = {
+ env: props.env,
+ ssl: props.ssl,
+ gameInherited: '' !== props.gameId,
+ gameAssoc: gameAssoc,
+ channel: channel,
+ session: null,
+ createGrid: false,
+ stepCache: [],
+ connectionLost: false,
+ end: false,
+ };
+ }
+
+ makeGameAssoc(len) {
+ let text = '';
+ let possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+ for (let i = 0; i < len; i++) {
+ text += possible.charAt(Math.floor(Math.random() * possible.length));
}
+ return text;
+ }
- makeGameAssoc(len) {
- let text = "";
- let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
- for (let i = 0; i < len; i++) {
- text += possible.charAt(Math.floor(Math.random() * possible.length));
- }
- return text;
- }
+ currectGridSize() {
+ let $field = $('#mine-wrapper .grid');
+ $field.height($field.width());
- currectGridSize() {
- let $field = $('#mine-wrapper .grid');
- $field.height($field.width());
+ $field = $('#mine-wrapper .grid .field-wrapper');
+ $field.height($field.width());
- $field = $('#mine-wrapper .grid .field-wrapper');
- $field.height($field.width());
+ $('#mine-wrapper .grid .field-wrapper .field')
+ .height($field.width())
+ .css('line-height', ($field.width() - 2) + 'px');
+ }
- $('#mine-wrapper .grid .field-wrapper .field')
- .height($field.width())
- .css('line-height', ($field.width() - 2) + 'px');
- }
+ /**
+ * STEP
+ *
+ * @param coords
+ * @returns {{red: *, blue: *}}
+ */
+ makePointsCalcAndStep(coords) {
+ let users = this.refs.gridControl.refs.userControl,
+ activePlayer = users.state.activePlayer ? 'blue' : 'red',
+ inactivePlayer = users.state.activePlayer ? 'red' : 'blue',
+ redPoints = 'red' === activePlayer
+ ? users.refs[activePlayer].state.mines
+ : users.refs[inactivePlayer].state.mines,
+ bluePoints = 'blue' === activePlayer
+ ? users.refs[activePlayer].state.mines
+ : users.refs[inactivePlayer].state.mines;
- /**
- * STEP
- *
- * @param coords
- * @returns {{red: *, blue: *}}
- */
- makePointsCalcAndStep(coords) {
- let users = this.refs.gridControl.refs.userControl,
- activePlayer = users.state.activePlayer ? 'blue' : 'red',
- inactivePlayer = users.state.activePlayer ? 'red' : 'blue',
- redPoints = activePlayer === 'red'
- ? users.refs[activePlayer].state.mines
- : users.refs[inactivePlayer].state.mines,
- bluePoints = activePlayer === 'blue'
- ? users.refs[activePlayer].state.mines
- : users.refs[inactivePlayer].state.mines;
+ this.refs.gridControl.stepEvent(coords);
- this.refs.gridControl.stepEvent(coords);
+ let mineCache = this.refs.gridControl.state.foundUserMineCache;
+ redPoints += 'red' === activePlayer ? mineCache : 0;
+ bluePoints += 'blue' === activePlayer ? mineCache : 0;
- let mineCache = this.refs.gridControl.state.foundUserMineCache;
- redPoints += activePlayer === 'red' ? mineCache : 0;
- bluePoints += activePlayer === 'blue' ? mineCache : 0;
+ return { red: redPoints, blue: bluePoints };
+ }
- return {red: redPoints, blue: bluePoints};
- }
+ /**
+ * START
+ *
+ * @param payload
+ */
+ makeGameStart(payload) {
+ /** every time the blue starts */
+ this.refs.gridControl.refs.userControl.setState({ activePlayer: 1 });
- /**
- * START
- *
- * @param payload
- */
- makeGameStart(payload) {
- /** every time the blue starts */
- this.refs.gridControl.refs.userControl.setState({activePlayer: 1});
+ /** Set up player names w/ server data */
+ this.refs.gridControl.refs.userControl.refs.red.setState({
+ name: '' !== payload.users.red ? payload.users.red : payload.users.redAnon,
+ });
- /** Set up player names w/ server data */
- this.refs.gridControl.refs.userControl.refs.red.setState({
- name: payload.users.red !== '' ? payload.users.red : payload.users.redAnon,
+ this.refs.gridControl.refs.userControl.refs.blue.setState({
+ name: '' !== payload.users.blue ? payload.users.blue : payload.users.blueAnon,
+ desc: 'blue' === this.refs.gridControl.state.webPlayer
+ ? this.refs.gridControl.state.desc.you
+ : this.refs.gridControl.state.desc.buddy,
+ active: true,
+ });
+
+ this.refs.gridControl.setState({ overlay: false });
+ }
+
+ /**
+ * THE END
+ *
+ * @param bluePoints
+ * @param redPoints
+ * @param resign
+ */
+ makeGameEndIfItEnds(bluePoints, redPoints, resign = false) {
+ let redWins = 25 < redPoints,
+ blueWins = 25 < bluePoints;
+
+ if (redWins || blueWins || resign) {
+ this.refs.gridControl.state.sound.won.play();
+
+ if (false === resign) {
+ this.refs.gridControl.setState({
+ overlay: true,
+ overlayTitle: (redWins ? 'Red' : 'Blue') + ' wins the game!',
+ overlaySubTitle: 'Play again!',
});
+ }
- this.refs.gridControl.refs.userControl.refs.blue.setState({
- name: payload.users.blue !== '' ? payload.users.blue : payload.users.blueAnon,
- desc: this.refs.gridControl.state.webPlayer === 'blue'
- ? this.refs.gridControl.state.desc.you
- : this.refs.gridControl.state.desc.buddy,
- active: true,
- });
+ this.refs.gridControl.showLeftMines();
- this.refs.gridControl.setState({overlay: false});
+ this.refs.gridControl.refs.userControl.setState({ activePlayer: false });
+ this.refs.gridControl.refs.userControl.refs.red.setState({ desc: '' });
+ this.refs.gridControl.refs.userControl.refs.blue.setState({ desc: '' });
}
+ }
+
+ resignProcess(color) {
+ this.refs.gridControl.setState({
+ overlay: true,
+ overlayTitle: color === this.refs.gridControl.state.webPlayer
+ ? 'You have been give up'
+ : 'Your opponent has been resigned',
+ overlaySubTitle: color === this.refs.gridControl.state.webPlayer
+ ? 'You LOSE!'
+ : 'You WIN!',
+ });
+
+ this.setState({ end: true });
+
+ this.makeGameEndIfItEnds(0, 0, true);
+ }
+
+ clickResign() {
+ /** PUBLISH */
+ this.state.session.publish(this.state.channel, {
+ 'resign': this.refs.gridControl.refs.userControl.state.activePlayer ? 'blue' : 'red',
+ });
+ this.resignProcess(this.refs.gridControl.state.webPlayer);
+ }
+
+ clickResignCancel() {
+ this.refs.gridControl.setState({
+ overlay: false,
+ });
+ }
+
+ /** RESIGN */
+ resign() {
+ let users = this.refs.gridControl.refs.userControl,
+ activePlayer = users.state.activePlayer ? 'blue' : 'red';
+
+ if (this.refs.gridControl.state.webPlayer === activePlayer) {
+ this.refs.gridControl.setState({
+ overlay: true,
+ overlayTitle: 'Are u sure u want to resign?!',
+ overlaySubTitle: (
+
+ ),
+ });
+ }
+ }
+
+ /**
+ * @see https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus
+ * @see https://developers.facebook.com/docs/sharing/reference/send-dialog
+ * @see https://developers.facebook.com/docs/plugins/share-button/
+ */
+ clickFBShare() {
+ let display = 'popup';
+
+ FB.getLoginStatus(function(response) {
+ display = 'connected' === response.status
+ ? 'dialog'
+ : 'popup';
+ });
+
+ FB.ui({
+ method: 'send',
+ display: display,
+ link: window.location.href + '/' + this.state.gameAssoc,
+ });
+ }
+
+ wInit(session, gridServer, gridClient) {
+ this.setState({ session: session });
+
+ /** save session to GridControl */
+ /** render grid fields - @see #12 */
+ this.refs.gridControl.setState({
+ grid: this.state.gameInherited ? gridServer : gridClient,
+ channel: this.state.channel,
+ desc: {
+ buddy: (
+
+ Your buddy is
+ making a
+ move.
+
+ ),
+ you: (
+
+ It is your turn!
+ Make a move.
+
+ ),
+ },
+ overlay: true,
+ overlayTitle: 'We are waiting for your opponent...',
+ overlaySubTitle: this.state.gameAssoc
+ ? (
+
+ ) : '',
+ renderGridFields: this.state.gameAssoc,
+ });
+ }
+
+ wSubscribe(payload, rpcUsers = null) {
+ 'dev' === this.state.env && console.info(
+ ('undefined' !== typeof payload.user ? payload.user : 'user') + ' has been subscribed to the channel!',
+ );
+
+ let firstUser = !rpcUsers;
+
+ null === this.refs.gridControl.state.webPlayer && this.refs.gridControl.setState({
+ webPlayer: payload.user === payload.users.blue
+ || (
+ firstUser && '' !== payload.users.blueAnon
+ || !firstUser && ('' === rpcUsers.blueAnon && '' === rpcUsers.blue)
+ )
+ ? 'blue' : 'red',
+ });
+
+ /** rwd */
+ (900 > $(document).width()) && this.currectGridSize();
+
+ /** every user has been came */
+ if (
+ 2 === payload.userCnt
+ && (
+ !this.state.connectionLost
+ || this.state.connectionLost && false === this.refs.gridControl.refs.userControl.state.activePlayer && !this.state.end
+ )
+ ) {
+ this.makeGameStart(payload);
+ }
+ }
+
+ wUnsubscribe(payload) {
+ 'dev' === this.state.env && console.info(payload.msg);
+
+ this.refs.gridControl.setState({
+ overlay: true,
+ overlayTitle: 'The connection has been lost w/ your friend...',
+ overlaySubTitle: 'Please, restart the game!',
+ });
+ }
+
+ wTopic(payload) {
+ /** Auto-Step if this player is not the current user */
+ if (this.refs.gridControl.state.webPlayer !== payload.data.player) {
+ if (null === payload.data.resign) {
+ 'dev' === this.state.env && console.warn(payload.user + ' has been stepped to coords: ' + payload.data.coords[0] + ', ' + payload.data.coords[1]);
+ 'dev' === this.state.env && console.warn('Opponent stepped: Auto-Step process');
+
+ this.refs.gridControl.refs.userControl.setState({ bombSelected: payload.data.bomb });
+
+ /** STEP */
+ let points = this.makePointsCalcAndStep(payload.data.coords);
+
+ /** THE END */
+ this.makeGameEndIfItEnds(points.blue, points.red);
+ } else {
+ /** RESIGN */
+ /** THE END */
+ this.resignProcess(payload.data.resign);
+ }
+ }
+ }
+
+ /** Connect - Subscribe */
+ subscribe(rpcUsers = null) {
+ this.state.session.subscribe(
+ this.state.channel,
+ (uri, payload) => {
+ let isTopicEvent = 'undefined' !== typeof payload.data,
+ isNotUnsubscribe = 'undefined' === typeof payload.msg;
+
+ /** CONNECTION */
+ if (isTopicEvent) {
+ this.wTopic(payload);
+ } else {
+ if (isNotUnsubscribe) {
+ this.wSubscribe(payload, rpcUsers);
+ } else {
+ this.wUnsubscribe(payload);
+ }
+ }
+
+ /** RECONNECTION */
+ if (2 === payload.userCnt && this.state.connectionLost) {
+ 'dev' === this.state.env && console.info('Reconnection process');
+
+ /** PUBLISH */
+ let cache = this.state.stepCache;
+ cache.forEach(item => this.state.session.publish(this.state.channel, item));
+ this.setState({ connectionLost: false, stepCache: [] });
+ }
+ });
+ }
+
+ connectWithWebsocket() {
+ /** Create Websocket w/ Bahnhof.js */
+ let websocket = WS.connect(
+ ('true' === this.state.ssl ? 'wss' : 'ws') + '://' + window.location.hostname + '/ws/',
+ );
/**
- * THE END
- *
- * @param bluePoints
- * @param redPoints
- * @param resign
+ * Connect
+ * Session is an Autobahn JS WAMP session.
*/
- makeGameEndIfItEnds(bluePoints, redPoints, resign = false) {
- let redWins = redPoints > 25,
- blueWins = bluePoints > 25;
+ websocket.on('socket/connect', session => {
+ 'dev' === this.state.env && console.info('Successfully connected to the Server!');
- if (redWins || blueWins || resign) {
- this.refs.gridControl.state.sound.won.play();
+ if (!this.state.connectionLost) {
+ let gridClient = this.state.gameInherited || new Grid().state.grid;
- if (false === resign) {
+ /**
+ * Connect - RPC
+ * Send grid information to the server
+ */
+ session
+ .call(
+ this.state.gameInherited ? 'mineseeker-rpc/connectGame' : 'mineseeker-rpc/startGame',
+ this.state.gameInherited ? this.state.gameAssoc : [window.btoa(JSON.stringify(gridClient)), this.state.gameAssoc],
+ )
+ .then(
+ data => {
+ 'dev' === this.state.env && console.info('RPC has been called');
+
+ let serverData = true !== data[0]
+ ? JSON.parse(window.atob(data))
+ : data;
+
+ /** Check the grid if the user is inherited @see #30 */
+ if ((this.state.gameInherited && 'undefined' !== typeof serverData.grid) || !this.state.gameInherited) {
+ this.wInit(session, serverData.grid, gridClient);
+ this.subscribe(this.state.gameInherited && serverData.users);
+ } else {
this.refs.gridControl.setState({
- overlay: true,
- overlayTitle: (redWins ? 'Red' : 'Blue') + " wins the game!",
- overlaySubTitle: "Play again!"
+ overlay: true,
+ overlayTitle: 'This channel does not exists!',
+ overlaySubTitle: Restart game!,
});
- }
- this.refs.gridControl.showLeftMines();
-
- this.refs.gridControl.refs.userControl.setState({activePlayer: false});
- this.refs.gridControl.refs.userControl.refs.red.setState({desc: ""});
- this.refs.gridControl.refs.userControl.refs.blue.setState({desc: ""});
- }
- }
-
- resignProcess(color) {
- this.refs.gridControl.setState({
- overlay: true,
- overlayTitle: color === this.refs.gridControl.state.webPlayer
- ? "You have been give up"
- : "Your opponent has been resigned",
- overlaySubTitle: color === this.refs.gridControl.state.webPlayer
- ? "You LOSE!"
- : "You WIN!"
- });
-
- this.setState({end: true});
-
- this.makeGameEndIfItEnds(0, 0, true);
- }
-
- clickResign() {
- /** PUBLISH */
- this.state.session.publish(this.state.channel, {
- 'resign': this.refs.gridControl.refs.userControl.state.activePlayer ? 'blue' : 'red'
- });
- this.resignProcess(this.refs.gridControl.state.webPlayer);
- }
-
- clickResignCancel() {
- this.refs.gridControl.setState({
- overlay: false
- });
- }
-
- /** RESIGN */
- resign() {
- let users = this.refs.gridControl.refs.userControl,
- activePlayer = users.state.activePlayer ? 'blue' : 'red';
-
- if (this.refs.gridControl.state.webPlayer === activePlayer) {
- this.refs.gridControl.setState({
- overlay: true,
- overlayTitle: "Are u sure u want to resign?!",
- overlaySubTitle:
- });
- }
- }
-
- /**
- * @see https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus
- * @see https://developers.facebook.com/docs/sharing/reference/send-dialog
- * @see https://developers.facebook.com/docs/plugins/share-button/
- */
- clickFBShare() {
- let display = 'popup';
-
- FB.getLoginStatus(function (response) {
- display = response.status === 'connected'
- ? 'dialog'
- : 'popup';
- });
-
- FB.ui({
- method: 'send',
- display: display,
- link: window.location.href + '/' + this.state.gameAssoc,
- });
- }
-
- wInit(session, gridServer, gridClient) {
- this.setState({session: session});
-
- /** save session to GridControl */
- /** render grid fields - @see #12 */
- this.refs.gridControl.setState({
- grid: this.state.gameInherited ? gridServer : gridClient,
- channel: this.state.channel,
- desc: {
- buddy:
- Your buddy is
- making a
- move.
-
,
- you:
- It is your turn!
- Make a move.
-
+ console.error('This channel does not exists!');
+ }
},
- overlay: true,
- overlayTitle: "We are waiting for your opponent...",
- overlaySubTitle: this.state.gameAssoc
- ?
-
- : '',
- renderGridFields: this.state.gameAssoc
- });
- }
-
- wSubscribe(payload, rpcUsers = null) {
- this.state.env === 'dev' && console.info(
- (typeof payload.user !== 'undefined' ? payload.user : 'user') + " has been subscribed to the channel!"
- );
-
- let firstUser = !rpcUsers;
-
- this.refs.gridControl.state.webPlayer === null && this.refs.gridControl.setState({
- webPlayer: payload.user === payload.users.blue ||
- (
- firstUser && payload.users.blueAnon !== '' ||
- !firstUser && (rpcUsers.blueAnon === '' && rpcUsers.blue === '')
- )
- ? 'blue' : 'red'
- });
-
- /** rwd */
- (900 > $(document).width()) && this.currectGridSize();
-
- /** every user has been came */
- if (
- payload.userCnt === 2 &&
- (
- !this.state.connectionLost ||
- this.state.connectionLost && false === this.refs.gridControl.refs.userControl.state.activePlayer && !this.state.end
- )
- ) {
- this.makeGameStart(payload);
- }
- }
-
- wUnsubscribe(payload) {
- this.state.env === 'dev' && console.info(payload.msg);
-
- this.refs.gridControl.setState({
- overlay: true,
- overlayTitle: "The connection has been lost w/ your friend...",
- overlaySubTitle: "Please, restart the game!"
- });
- }
-
- wTopic(payload) {
- /** Auto-Step if this player is not the current user */
- if (this.refs.gridControl.state.webPlayer !== payload.data.player) {
- if (null === payload.data.resign) {
- this.state.env === 'dev' && console.warn(payload.user + " has been stepped to coords: " + payload.data.coords[0] + ', ' + payload.data.coords[1]);
- this.state.env === 'dev' && console.warn('Opponent stepped: Auto-Step process');
-
- this.refs.gridControl.refs.userControl.setState({bombSelected: payload.data.bomb});
-
- /** STEP */
- let points = this.makePointsCalcAndStep(payload.data.coords);
-
- /** THE END */
- this.makeGameEndIfItEnds(points.blue, points.red);
- } else {
- /** RESIGN */
- /** THE END */
- this.resignProcess(payload.data.resign);
- }
- }
- }
-
- /** Connect - Subscribe */
- subscribe(rpcUsers = null) {
- this.state.session.subscribe(
- this.state.channel,
- (uri, payload, log) => {
- let isTopicEvent = typeof payload.data !== 'undefined',
- isNotUnsubscribe = typeof payload.msg === 'undefined';
-
- /** CONNECTION */
- if (isTopicEvent) {
- this.wTopic(payload);
- } else {
- if (isNotUnsubscribe) {
- this.wSubscribe(payload, rpcUsers);
- } else {
- this.wUnsubscribe(payload);
- }
- }
-
- /** RECONNECTION */
- if (payload.userCnt === 2 && this.state.connectionLost) {
- this.state.env === 'dev' && console.info('Reconnection process');
-
- /** PUBLISH */
- let cache = this.state.stepCache;
- cache.forEach((item) => this.state.session.publish(this.state.channel, item));
- this.setState({connectionLost: false, stepCache: []});
- }
- });
- }
-
- connectWithWebsocket() {
- /** Create Websocket w/ Bahnhof.js */
- let websocket = WS.connect(
- (this.state.ssl === 'true' ? "wss" : "ws") + "://" + window.location.hostname + "/ws/"
- );
-
- /**
- * Connect
- * Session is an Autobahn JS WAMP session.
- */
- websocket.on("socket/connect", (session) => {
- this.state.env === 'dev' && console.info("Successfully connected to the Server!");
-
- if (!this.state.connectionLost) {
- let gridClient = this.state.gameInherited || new Grid().state.grid;
-
- /**
- * Connect - RPC
- * Send grid information to the server
- */
- session
- .call(
- this.state.gameInherited ? "mineseeker-rpc/connectGame" : "mineseeker-rpc/startGame",
- this.state.gameInherited ? this.state.gameAssoc : [window.btoa(JSON.stringify(gridClient)), this.state.gameAssoc]
- )
- .then(
- (data) => {
- this.state.env === 'dev' && console.info('RPC has been called');
-
- let serverData = data[0] !== true
- ? JSON.parse(window.atob(data))
- : data;
-
- /** Check the grid if the user is inherited @see #30 */
- if ((this.state.gameInherited && typeof serverData.grid !== 'undefined') || !this.state.gameInherited) {
- this.wInit(session, serverData.grid, gridClient);
- this.subscribe(this.state.gameInherited && serverData.users);
- } else {
- this.refs.gridControl.setState({
- overlay: true,
- overlayTitle: "This channel does not exists!",
- overlaySubTitle: Restart game!
- });
-
- console.error("This channel does not exists!");
- }
- },
- (error, desc) => this.state.env === 'dev' && console.error(["RPC Error", error, desc])
- );
- } else {
- this.setState({session: session});
- this.subscribe();
- }
- });
-
- /**
- * DisConnect
- * Error provides us with some insight into the disconnection: error.reason and error.code
- */
- websocket.on("socket/disconnect", (error) => {
- this.state.env === 'dev' && console.error("Disconnected for " + error.reason + " with code " + error.code);
-
- error.code === 6 && this.setState({connectionLost: true});
- error.code === 3 && setTimeout(this.componentDidMount.bind(this), 500);
- });
- }
-
- /** After rendering */
- componentDidMount() {
- this.connectWithWebsocket();
- }
+ (error, desc) => 'dev' === this.state.env && console.error(['RPC Error', error, desc]),
+ );
+ } else {
+ this.setState({ session: session });
+ this.subscribe();
+ }
+ });
/**
- * Cache the steps unless reconnection
- *
- * @param dataPack
+ * DisConnect
+ * Error provides us with some insight into the disconnection: error.reason and error.code
*/
- cachePublish(dataPack) {
- let cache = this.state.stepCache;
- cache.push(dataPack);
- this.setState({stepCache: cache});
+ websocket.on('socket/disconnect', error => {
+ 'dev' === this.state.env && console.error('Disconnected for ' + error.reason + ' with code ' + error.code);
+
+ 6 === error.code && this.setState({ connectionLost: true });
+ 3 === error.code && setTimeout(this.componentDidMount.bind(this), 500);
+ });
+ }
+
+ /** After rendering */
+ componentDidMount() {
+ this.connectWithWebsocket();
+ }
+
+ /**
+ * Cache the steps unless reconnection
+ *
+ * @param dataPack
+ */
+ cachePublish(dataPack) {
+ let cache = this.state.stepCache;
+ cache.push(dataPack);
+ this.setState({ stepCache: cache });
+ }
+
+ onClick(coords) {
+ let activePlayer = this.refs.gridControl.refs.userControl.state.activePlayer ? 'blue' : 'red';
+
+ /** if the clicked field is NEVER CLICKED */
+ if (this.refs.gridControl.checkFieldHasBeenNeverClicked(coords[0], coords[1])) {
+ /** Player step and it is the current player */
+ if (activePlayer === this.refs.gridControl.state.webPlayer) {
+ /** STEP */
+ let points = this.makePointsCalcAndStep(coords);
+
+ /** THE END */
+ this.makeGameEndIfItEnds(points.blue, points.red);
+
+ let dataPack = {
+ 'coords': coords,
+ 'player': activePlayer,
+ 'bomb': this.refs.gridControl.refs.userControl.state.bombSelected,
+ 'redPoints': points.red,
+ 'bluePoints': points.blue,
+ 'resign': null,
+ 'redExplodedBomb': 'red' === activePlayer && this.refs.gridControl.refs.userControl.state.bombSelected,
+ 'blueExplodedBomb': 'blue' === activePlayer && this.refs.gridControl.refs.userControl.state.bombSelected,
+ };
+
+ /** PUBLISH */
+ !this.state.connectionLost
+ ? this.state.session.publish(this.state.channel, dataPack)
+ : this.cachePublish(dataPack);
+ }
}
+ }
- onClick(coords) {
- let activePlayer = this.refs.gridControl.refs.userControl.state.activePlayer ? 'blue' : 'red';
-
- /** if the clicked field is NEVER CLICKED */
- if (this.refs.gridControl.checkFieldHasBeenNeverClicked(coords[0], coords[1])) {
- /** Player step and it is the current player */
- if (activePlayer === this.refs.gridControl.state.webPlayer) {
- /** STEP */
- let points = this.makePointsCalcAndStep(coords);
-
- /** THE END */
- this.makeGameEndIfItEnds(points.blue, points.red);
-
- let dataPack = {
- 'coords': coords,
- 'player': activePlayer,
- 'bomb': this.refs.gridControl.refs.userControl.state.bombSelected,
- 'redPoints': points.red,
- 'bluePoints': points.blue,
- 'resign': null,
- 'redExplodedBomb': activePlayer === 'red' && this.refs.gridControl.refs.userControl.state.bombSelected,
- 'blueExplodedBomb': activePlayer === 'blue' && this.refs.gridControl.refs.userControl.state.bombSelected
- };
-
- /** PUBLISH */
- !this.state.connectionLost
- ? this.state.session.publish(this.state.channel, dataPack)
- : this.cachePublish(dataPack);
- }
- }
- }
-
- render() {
- return (
-
- );
- }
+ render() {
+ return (
+
+ );
+ }
}
export default MineSeeker;
diff --git a/assets/js/mine-seeker/grid/grid-control.js b/assets/js/mine-seeker/grid/grid-control.js
index 1a0dc62..3ad8677 100644
--- a/assets/js/mine-seeker/grid/grid-control.js
+++ b/assets/js/mine-seeker/grid/grid-control.js
@@ -1,445 +1,447 @@
import React from 'react';
import GridField from './grid-field';
import UserControl from '../user/user-control';
-import {Howl, Howler} from 'howler';
+import { Howl } from 'howler';
class GridControl extends React.Component {
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- let click = new Howl({src: ['/sound/click.mp3']}),
- bomb = new Howl({src: ['/sound/bomb.mp3']}),
- mine = new Howl({src: ['/sound/mine.mp3']}),
- warning = new Howl({src: ['/sound/warning.mp3']}),
- won = new Howl({src: ['/sound/won.mp3']});
+ let click = new Howl({ src: ['/sound/click.mp3'] }),
+ bomb = new Howl({ src: ['/sound/bomb.mp3'] }),
+ mine = new Howl({ src: ['/sound/mine.mp3'] }),
+ warning = new Howl({ src: ['/sound/warning.mp3'] }),
+ won = new Howl({ src: ['/sound/won.mp3'] });
- this.state = {
- env: props.env,
- webPlayer: null,
- grid: null,
- desc: null,
- renderGridFields: false,
- gridFields: [],
- updatedFieldCache: [],
- bombFieldCache: [],
- foundUserMineCache: 0,
- playBomb: false,
- overlay: false,
- overlayTitle: "",
- overlaySubTitle: "",
- sound: {
- click: click,
- bomb: bomb,
- mine: mine,
- warning: warning,
- won: won
- },
- lastClicked: {
- red: null,
- blue: null
- }
- };
+ this.state = {
+ env: props.env,
+ webPlayer: null,
+ grid: null,
+ desc: null,
+ renderGridFields: false,
+ gridFields: [],
+ updatedFieldCache: [],
+ bombFieldCache: [],
+ foundUserMineCache: 0,
+ playBomb: false,
+ overlay: false,
+ overlayTitle: '',
+ overlaySubTitle: '',
+ sound: {
+ click: click,
+ bomb: bomb,
+ mine: mine,
+ warning: warning,
+ won: won,
+ },
+ lastClicked: {
+ red: null,
+ blue: null,
+ },
+ };
+ }
+
+ refString(row, col) {
+ return 'gridField_' + row + '_' + col;
+ }
+
+ checkMine(row, col) {
+ return 'undefined' !== typeof this.state.grid[row] && 'undefined' !== typeof this.state.grid[row][col] && 'm' !== this.state.grid[row][col];
+ }
+
+ checkFieldHasBeenNeverClicked(row, col) {
+ return 0 > this.state.updatedFieldCache.indexOf(this.refString(row, col)) && !this.refs[this.refString(row, col)].state.active;
+ }
+
+ getBombRadius(row, col) {
+ let isBombTargetCenter = 1 < row && row < this.state.grid.length - 2 && 1 < col && col < this.state.grid[row].length - 2;
+
+ /** if the (5x5) target not fits the grid */
+ if (!isBombTargetCenter) {
+ col = 2 > col ? 2 : col;
+ row = 2 > row ? 2 : row;
+ row = row > this.state.grid.length - 3 ? this.state.grid.length - 3 : row;
+ col = col > this.state.grid[0].length - 3 ? this.state.grid[0].length - 3 : col;
}
- refString(row, col) {
- return 'gridField_' + row + '_' + col;
- }
+ return [
+ [row, col], [row - 2, col - 2], [row - 2, col], [row - 2, col + 2], [row, col - 2], [row, col + 2],
+ [row + 2, col - 2], [row + 2, col], [row + 2, col + 2], [row - 2, col + 1], [row - 2, col - 1],
+ [row - 1, col - 2], [row - 1, col - 1], [row - 1, col], [row - 1, col + 1], [row - 1, col + 2],
+ [row, col - 1], [row, col + 1], [row + 1, col - 2], [row + 1, col - 1], [row + 1, col],
+ [row + 1, col + 1], [row + 1, col + 2], [row + 2, col - 1], [row + 2, col + 1],
+ ];
+ }
- checkMine(row, col) {
- return typeof this.state.grid[row] !== 'undefined' && typeof this.state.grid[row][col] !== 'undefined' && this.state.grid[row][col] !== 'm';
- }
+ getBombFieldRadius() {
+ return [
+ [null, null], [0, 0], [1, 0], [2, 0], [0, 1], [2, 1], [0, 2], [1, 2], [2, 2],
+ [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null],
+ [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null],
+ [null, null], [null, null],
+ ];
+ }
- checkFieldHasBeenNeverClicked(row, col) {
- return this.state.updatedFieldCache.indexOf(this.refString(row, col)) < 0 && !this.refs[this.refString(row, col)].state.active;
- }
+ getNeighbourRadius(row, col) {
+ return [
+ [row - 1, col], [row - 1, col - 1], [row - 1, col + 1], [row, col - 1], [row, col + 1], [row + 1, col],
+ [row + 1, col + 1], [row + 1, col - 1],
+ ];
+ }
- getBombRadius(row, col) {
- let isBombTargetCenter = row > 1 && row < this.state.grid.length - 2 && col > 1 && col < this.state.grid[row].length - 2;
+ checkNeighbourItem(row, col) {
+ if (this.checkMine(row, col)) {
+ var currentField = this.refs[this.refString(row, col)];
- /** if the (5x5) target not fits the grid */
- if (!isBombTargetCenter) {
- col = col < 2 ? 2 : col;
- row = row < 2 ? 2 : row;
- row = row > this.state.grid.length - 3 ? this.state.grid.length - 3 : row;
- col = col > this.state.grid[0].length - 3 ? this.state.grid[0].length - 3 : col;
- }
+ /**
+ * It must be cached because the GridField.state not updated until
+ * all showAppropriateFields() method runned out!!
+ */
+ if (this.checkFieldHasBeenNeverClicked(row, col)) {
+ this.state.updatedFieldCache.push(this.refString(row, col));
- return [
- [row, col], [row - 2, col - 2], [row - 2, col], [row - 2, col + 2], [row, col - 2], [row, col + 2],
- [row + 2, col - 2], [row + 2, col], [row + 2, col + 2], [row - 2, col + 1], [row - 2, col - 1],
- [row - 1, col - 2], [row - 1, col - 1], [row - 1, col], [row - 1, col + 1], [row - 1, col + 2],
- [row, col - 1], [row, col + 1], [row + 1, col - 2], [row + 1, col - 1], [row + 1, col],
- [row + 1, col + 1], [row + 1, col + 2], [row + 2, col - 1], [row + 2, col + 1]
- ];
- }
-
- getBombFieldRadius() {
- return [
- [null, null], [0, 0], [1, 0], [2, 0], [0, 1], [2, 1], [0, 2], [1, 2], [2, 2],
- [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null],
- [null, null], [null, null], [null, null], [null, null], [null, null], [null, null], [null, null],
- [null, null], [null, null]
- ];
- }
-
- getNeighbourRadius(row, col) {
- return [
- [row - 1, col], [row - 1, col - 1], [row - 1, col + 1], [row, col - 1], [row, col + 1], [row + 1, col],
- [row + 1, col + 1], [row + 1, col - 1]
- ];
- }
-
- checkNeighbourItem(row, col) {
- if (this.checkMine(row, col)) {
- var currentField = this.refs[this.refString(row, col)];
-
- /**
- * It must be cached because the GridField.state not updated until
- * all showAppropriateFields() method runned out!!
- */
- if (this.checkFieldHasBeenNeverClicked(row, col)) {
- this.state.updatedFieldCache.push(this.refString(row, col));
-
- currentField.setState({
- currentImage: this.state.grid[row][col],
- currentObj: this.state.grid[row][col],
- active: true
- });
-
- if (this.state.grid[row][col] === 0) {
- return {
- row: row,
- col: col
- };
- }
- }
- }
-
- return false;
- }
-
- checkNeighbours(row, col) {
- let anotherFields = [],
- neighbours = this.getNeighbourRadius(row, col);
-
- for (let i = 0, j = neighbours.length; i < j; i++) {
- anotherFields.push(this.checkNeighbourItem(neighbours[i][0], neighbours[i][1]));
- }
-
- return anotherFields;
- }
-
- bombClear() {
- if (this.state.bombFieldCache.length) {
- for (var i = 0, j = this.state.bombFieldCache.length; i < j; i++) {
- var cacheItem = this.state.bombFieldCache[i];
- this.refs[this.refString(cacheItem[0], cacheItem[1])]
- .setState({bombTargetArea: null});
- }
- this.state.bombFieldCache = [];
- }
- }
-
- bombCreate(row, col) {
- var bombFieldSymbols = this.getBombFieldRadius(),
- bombFields = this.getBombRadius(row, col);
-
- for (var i = 0, j = bombFields.length; i < j; i++) {
- this.state.bombFieldCache.push(bombFields[i]);
-
- this.refs[this.refString(bombFields[i][0], bombFields[i][1])]
- .setState({bombTargetArea: bombFieldSymbols[i]});
- }
- }
-
- showLeftMines() {
- for (let i = 0, j = this.state.grid.length; i < j; i++) {
- for (let k = 0, l = this.state.grid[i].length; k < l; k++) {
- let currentField = this.refs[this.refString(i, k)];
-
- if (this.state.grid[i][k] === 'm' && this.checkFieldHasBeenNeverClicked(i, k)) {
- currentField.setState({
- currentImage: currentField.state.icons.root + currentField.state.icons.left
- });
- }
- }
- }
- }
-
- /** set __ACTIVE__ player in the UserControl !!!! */
- changePlayer(idx, max, currentObject) {
- var userControl = this.refs.userControl,
- activePlayer = userControl.state.activePlayer ? 'blue' : 'red',
- inactivePlayer = userControl.state.activePlayer ? 'red' : 'blue';
-
- if (
- userControl.state.bombSelected && idx === (max - 1) ||
- !idx && !userControl.state.bombSelected && currentObject !== 'm'
- ) {
- userControl.setState({
- activePlayer: userControl.state.activePlayer ? 0 : 1
- });
-
- /** the desc is inversely because the user.active is not changed yet !!! */
- userControl.refs[activePlayer].setState({
- active: false,
- desc: ""
- });
-
- userControl.refs[inactivePlayer].setState({
- active: true,
- desc: activePlayer === this.state.webPlayer
- ? this.state.desc.buddy
- : this.state.desc.you
- });
- }
- }
-
- /**
- * Show all fields that needed after click
- *
- * @param currentField
- * @param row
- * @param col
- */
- showAppropriateFields(currentField, row, col) {
currentField.setState({
- currentObj: this.state.grid[row][col],
- active: true
+ currentImage: this.state.grid[row][col],
+ currentObj: this.state.grid[row][col],
+ active: true,
});
- if (this.checkFieldHasBeenNeverClicked(row, col)) {
- this.state.updatedFieldCache.push(this.refString(row, col));
- }
-
- if (this.state.grid[row][col] === 0) {
- var neighbours = this.checkNeighbours(row, col);
-
- neighbours
- .filter((i) => {
- return i !== false;
- })
- .forEach((element, index, array) => {
- var currentField = this.refs[this.refString(element.row, element.col)];
- this.showAppropriateFields(currentField, element.row, element.col);
- });
+ if (0 === this.state.grid[row][col]) {
+ return {
+ row: row,
+ col: col,
+ };
}
+ }
}
- /**
- * Player control method
- *
- * @param currentObject {int|string} Current object from Grid class
- * @param row {int}
- * @param col {int}
- * @param justOnFirstIteration {int} When bomb is being used check the whole explosion area
- */
- handleGridField(currentObject, row, col, justOnFirstIteration = 0) {
- var userControl = this.refs.userControl,
- gridFieldControl = this.refs[this.refString(row, col)],
- activePlayer = userControl.state.activePlayer ? 'blue' : 'red',
- inactivePlayer = userControl.state.activePlayer ? 'red' : 'blue';
+ return false;
+ }
- /** if the clicked field is NEVER CLICKED */
- if (this.checkFieldHasBeenNeverClicked(row, col)) {
- /** update LAST CLICKED grid field */
- if (!justOnFirstIteration) {
- if (this.state.lastClicked[activePlayer] !== null) {
- this.refs[this.refString(this.state.lastClicked[activePlayer][0], this.state.lastClicked[activePlayer][1])].setState({
- lastClickedRed: false,
- lastClickedBlue: false
- });
- }
- }
+ checkNeighbours(row, col) {
+ let anotherFields = [],
+ neighbours = this.getNeighbourRadius(row, col);
- this.state.lastClicked[activePlayer] = [row, col];
+ for (let i = 0, j = neighbours.length; i < j; i++) {
+ anotherFields.push(this.checkNeighbourItem(neighbours[i][0], neighbours[i][1]));
+ }
- /** if you found mine */
- if (currentObject === 'm') {
- this.state.foundUserMineCache++;
+ return anotherFields;
+ }
- if (!justOnFirstIteration) {
- /** set last clicked field w/ color */
- this.state.lastClicked[activePlayer] = [row, col];
+ bombClear() {
+ if (this.state.bombFieldCache.length) {
+ for (var i = 0, j = this.state.bombFieldCache.length; i < j; i++) {
+ var cacheItem = this.state.bombFieldCache[i];
+ this.refs[this.refString(cacheItem[0], cacheItem[1])]
+ .setState({ bombTargetArea: null });
+ }
+ this.state.bombFieldCache = [];
+ }
+ }
- this.state.sound[
- (userControl.refs[activePlayer].state.mines + this.state.foundUserMineCache) > 20
- ? 'warning'
- : 'mine'
- ].play();
- }
+ bombCreate(row, col) {
+ var bombFieldSymbols = this.getBombFieldRadius(),
+ bombFields = this.getBombRadius(row, col);
- /** set current image in field */
- gridFieldControl.setState({
- currentImage: gridFieldControl.state.icons.root + gridFieldControl.state.icons.flag[activePlayer]
- });
- } else {
- this.state.sound.click.play();
+ for (var i = 0, j = bombFields.length; i < j; i++) {
+ this.state.bombFieldCache.push(bombFields[i]);
- /** set current image in field - WHEN it is a number */
- if (!isNaN(currentObject)) {
- gridFieldControl.setState({
- currentImage: currentObject
- });
- }
- }
+ this.refs[this.refString(bombFields[i][0], bombFields[i][1])]
+ .setState({ bombTargetArea: bombFieldSymbols[i] });
+ }
+ }
- /**
- * set bombs status - we must add one mine (currentObject === 'm' ? 1 : 0) to current mine
- * when it found NOW because the status is not refreshed unless the handleGridField() ends
- */
- userControl.refs[activePlayer].setState({
- enabledBomb: userControl.refs[activePlayer].state.mines + (currentObject === 'm' ? 1 : 0) <= userControl.refs[inactivePlayer].state.mines
- });
+ showLeftMines() {
+ for (let i = 0, j = this.state.grid.length; i < j; i++) {
+ for (let k = 0, l = this.state.grid[i].length; k < l; k++) {
+ let currentField = this.refs[this.refString(i, k)];
- userControl.refs[inactivePlayer].setState({
- enabledBomb: userControl.refs[activePlayer].state.mines + (currentObject === 'm' ? 1 : 0) >= userControl.refs[inactivePlayer].state.mines
- });
-
- /** set-up last clicked */
- if (!justOnFirstIteration) {
- gridFieldControl.setState({
- lastClickedRed: activePlayer === 'red',
- lastClickedBlue: activePlayer === 'blue'
- });
- }
+ if ('m' === this.state.grid[i][k] && this.checkFieldHasBeenNeverClicked(i, k)) {
+ currentField.setState({
+ currentImage: currentField.state.icons.root + currentField.state.icons.left,
+ });
}
+ }
+ }
+ }
+
+ /** set __ACTIVE__ player in the UserControl !!!! */
+ changePlayer(idx, max, currentObject) {
+ var userControl = this.refs.userControl,
+ activePlayer = userControl.state.activePlayer ? 'blue' : 'red',
+ inactivePlayer = userControl.state.activePlayer ? 'red' : 'blue';
+
+ if (
+ userControl.state.bombSelected && idx === (max - 1)
+ || !idx && !userControl.state.bombSelected && 'm' !== currentObject
+ ) {
+ userControl.setState({
+ activePlayer: userControl.state.activePlayer ? 0 : 1,
+ });
+
+ /** the desc is inversely because the user.active is not changed yet !!! */
+ userControl.refs[activePlayer].setState({
+ active: false,
+ desc: '',
+ });
+
+ userControl.refs[inactivePlayer].setState({
+ active: true,
+ desc: activePlayer === this.state.webPlayer
+ ? this.state.desc.buddy
+ : this.state.desc.you,
+ });
+ }
+ }
+
+ /**
+ * Show all fields that needed after click
+ *
+ * @param currentField
+ * @param row
+ * @param col
+ */
+ showAppropriateFields(currentField, row, col) {
+ currentField.setState({
+ currentObj: this.state.grid[row][col],
+ active: true,
+ });
+
+ if (this.checkFieldHasBeenNeverClicked(row, col)) {
+ this.state.updatedFieldCache.push(this.refString(row, col));
}
- /**
- * Show elems w/ conditions
- *
- * @param row
- * @param col
- * @param idx
- * @param max
- */
- show(row, col, idx = 0, max = 0) {
- this.handleGridField(this.state.grid[row][col], row, col, idx);
- this.showAppropriateFields(this.refs[this.refString(row, col)], row, col);
- this.changePlayer(idx, max, this.state.grid[row][col]);
+ if (0 === this.state.grid[row][col]) {
+ let neighbours = this.checkNeighbours(row, col);
+
+ neighbours
+ .filter(i => false !== i)
+ .forEach(element => {
+ let currentField = this.refs[this.refString(element.row, element.col)];
+ this.showAppropriateFields(currentField, element.row, element.col);
+ });
}
+ }
- /**
- * STEP one
- *
- * @param coords
- */
- stepEvent(coords) {
- /** if the clicked field is NEVER CLICKED */
- if (this.checkFieldHasBeenNeverClicked(coords[0], coords[1])) {
- var activePlayer = this.refs.userControl.state.activePlayer ? 'blue' : 'red';
+ /**
+ * Player control method
+ *
+ * @param currentObject {int|string} Current object from Grid class
+ * @param row {int}
+ * @param col {int}
+ * @param justOnFirstIteration {int} When bomb is being used check the whole explosion area
+ */
+ handleGridField(currentObject, row, col, justOnFirstIteration = 0) {
+ var userControl = this.refs.userControl,
+ gridFieldControl = this.refs[this.refString(row, col)],
+ activePlayer = userControl.state.activePlayer ? 'blue' : 'red',
+ inactivePlayer = userControl.state.activePlayer ? 'red' : 'blue';
- this.state.foundUserMineCache = 0;
- this.state.playBomb = true;
-
- /** Show elements */
- if (this.refs.userControl.state.bombSelected) {
- this.state.sound.bomb.play();
-
- var bombRadius = this.getBombRadius(coords[0], coords[1]);
- for (var i = 0, j = bombRadius.length; i < j; i++) {
- this.show(bombRadius[i][0], bombRadius[i][1], i, j);
- }
-
- /** remove BOMB from activePlayer */
- this.refs.userControl.refs[activePlayer].setState({
- haveBomb: false
- });
- } else {
- this.show(coords[0], coords[1]);
- }
-
- /** Mine score handling */
- if (this.state.foundUserMineCache) {
- this.refs.userControl.setState({
- mines: this.refs.userControl.state.mines - this.state.foundUserMineCache,
- foundMines: true
- }, () => {
- /** because of CSS animation in .found-mine */
- setTimeout(() => this.refs.userControl.setState({foundMines: false}), 500);
-
- /** add the found mines to the active Player */
- this.refs.userControl.refs[activePlayer].setState({
- mines: this.refs.userControl.refs[activePlayer].state.mines + this.state.foundUserMineCache
- });
- });
- }
-
- /** Reset BOMB status */
- if (this.refs.userControl.state.bombSelected) {
- /** reset bomb selected status */
- this.refs.userControl.setState({bombSelected: false});
-
- /** clear cache, reset symbols */
- this.bombClear();
- }
+ /** if the clicked field is NEVER CLICKED */
+ if (this.checkFieldHasBeenNeverClicked(row, col)) {
+ /** update LAST CLICKED grid field */
+ if (!justOnFirstIteration) {
+ if (null !== this.state.lastClicked[activePlayer]) {
+ this.refs[this.refString(this.state.lastClicked[activePlayer][0], this.state.lastClicked[activePlayer][1])].setState({
+ lastClickedRed: false,
+ lastClickedBlue: false,
+ });
}
- }
+ }
- /**
- * On Hover when you want to drop BOMB
- * Target grid field
- * @param coords
- */
- onHoverGridField(coords) {
- if (this.refs.userControl.state.bombSelected) {
- var activePlayer = this.refs.userControl.state.activePlayer ? 'blue' : 'red';
+ this.state.lastClicked[activePlayer] = [row, col];
- if (activePlayer === this.state.webPlayer) {
- /** clear cache, reset symbols */
- this.bombClear();
+ /** if you found mine */
+ if ('m' === currentObject) {
+ this.state.foundUserMineCache++;
- /** new cache && field activate */
- this.bombCreate(coords[0], coords[1]);
- } else {
- this.refs.userControl.setState({bombSelected: false});
- }
+ if (!justOnFirstIteration) {
+ /** set last clicked field w/ color */
+ this.state.lastClicked[activePlayer] = [row, col];
+
+ this.state.sound[
+ 20 < (userControl.refs[activePlayer].state.mines + this.state.foundUserMineCache)
+ ? 'warning'
+ : 'mine'
+ ].play();
}
- }
- renderGridFields() {
- for (let i = 0, j = this.state.grid.length; i < j; i++) {
- for (let k = 0, l = this.state.grid[i].length; k < l; k++) {
- this.state.gridFields.push(
-
- );
- }
+ /** set current image in field */
+ gridFieldControl.setState({
+ currentImage: gridFieldControl.state.icons.root + gridFieldControl.state.icons.flag[activePlayer],
+ });
+ } else {
+ this.state.sound.click.play();
+
+ /** set current image in field - WHEN it is a number */
+ if (!isNaN(currentObject)) {
+ gridFieldControl.setState({
+ currentImage: currentObject,
+ });
}
+ }
+
+ /**
+ * set bombs status - we must add one mine (currentObject === 'm' ? 1 : 0) to current mine
+ * when it found NOW because the status is not refreshed unless the handleGridField() ends
+ */
+ userControl.refs[activePlayer].setState({
+ enabledBomb: userControl.refs[activePlayer].state.mines + ('m' === currentObject ? 1 : 0) <= userControl.refs[inactivePlayer].state.mines,
+ });
+
+ userControl.refs[inactivePlayer].setState({
+ enabledBomb: userControl.refs[activePlayer].state.mines + ('m' === currentObject ? 1 : 0) >= userControl.refs[inactivePlayer].state.mines,
+ });
+
+ /** set-up last clicked */
+ if (!justOnFirstIteration) {
+ gridFieldControl.setState({
+ lastClickedRed: 'red' === activePlayer,
+ lastClickedBlue: 'blue' === activePlayer,
+ });
+ }
}
+ }
- render() {
- /** Render the grid fields just one time in one party #12 */
- this.state.renderGridFields && this.renderGridFields();
- this.state.renderGridFields = false;
+ /**
+ * Show elems w/ conditions
+ *
+ * @param row
+ * @param col
+ * @param idx
+ * @param max
+ */
+ show(row, col, idx = 0, max = 0) {
+ this.handleGridField(this.state.grid[row][col], row, col, idx);
+ this.showAppropriateFields(this.refs[this.refString(row, col)], row, col);
+ this.changePlayer(idx, max, this.state.grid[row][col]);
+ }
- return (
-
-
-
-
{this.state.overlayTitle}
- {this.state.overlaySubTitle}
-
-
-
-
-
- <>
- {this.state.gridFields}
- >
-
-
-
+ /**
+ * STEP one
+ *
+ * @param coords
+ */
+ stepEvent(coords) {
+ /** if the clicked field is NEVER CLICKED */
+ if (this.checkFieldHasBeenNeverClicked(coords[0], coords[1])) {
+ var activePlayer = this.refs.userControl.state.activePlayer ? 'blue' : 'red';
+
+ this.state.foundUserMineCache = 0;
+ this.state.playBomb = true;
+
+ /** Show elements */
+ if (this.refs.userControl.state.bombSelected) {
+ this.state.sound.bomb.play();
+
+ var bombRadius = this.getBombRadius(coords[0], coords[1]);
+ for (var i = 0, j = bombRadius.length; i < j; i++) {
+ this.show(bombRadius[i][0], bombRadius[i][1], i, j);
+ }
+
+ /** remove BOMB from activePlayer */
+ this.refs.userControl.refs[activePlayer].setState({
+ haveBomb: false,
+ });
+ } else {
+ this.show(coords[0], coords[1]);
+ }
+
+ /** Mine score handling */
+ if (this.state.foundUserMineCache) {
+ this.refs.userControl.setState({
+ mines: this.refs.userControl.state.mines - this.state.foundUserMineCache,
+ foundMines: true,
+ }, () => {
+ /** because of CSS animation in .found-mine */
+ setTimeout(() => this.refs.userControl.setState({ foundMines: false }), 500);
+
+ /** add the found mines to the active Player */
+ this.refs.userControl.refs[activePlayer].setState({
+ mines: this.refs.userControl.refs[activePlayer].state.mines + this.state.foundUserMineCache,
+ });
+ });
+ }
+
+ /** Reset BOMB status */
+ if (this.refs.userControl.state.bombSelected) {
+ /** reset bomb selected status */
+ this.refs.userControl.setState({ bombSelected: false });
+
+ /** clear cache, reset symbols */
+ this.bombClear();
+ }
+ }
+ }
+
+ /**
+ * On Hover when you want to drop BOMB
+ * Target grid field
+ * @param coords
+ */
+ onHoverGridField(coords) {
+ if (this.refs.userControl.state.bombSelected) {
+ var activePlayer = this.refs.userControl.state.activePlayer ? 'blue' : 'red';
+
+ if (activePlayer === this.state.webPlayer) {
+ /** clear cache, reset symbols */
+ this.bombClear();
+
+ /** new cache && field activate */
+ this.bombCreate(coords[0], coords[1]);
+ } else {
+ this.refs.userControl.setState({ bombSelected: false });
+ }
+ }
+ }
+
+ renderGridFields() {
+ for (let i = 0, j = this.state.grid.length; i < j; i++) {
+ for (let k = 0, l = this.state.grid[i].length; k < l; k++) {
+ this.state.gridFields.push(
+ ,
);
+ }
}
+ }
+
+ render() {
+ /** Render the grid fields just one time in one party #12 */
+ this.state.renderGridFields && this.renderGridFields();
+ this.state.renderGridFields = false;
+
+ return (
+
+
+
+
{this.state.overlayTitle}
+ {this.state.overlaySubTitle}
+
+
+
+
+
+ <>
+ {this.state.gridFields}
+ >
+
+
+
+ );
+ }
}
export default GridControl;
diff --git a/assets/js/mine-seeker/grid/grid-field.js b/assets/js/mine-seeker/grid/grid-field.js
index f649740..497e0c7 100644
--- a/assets/js/mine-seeker/grid/grid-field.js
+++ b/assets/js/mine-seeker/grid/grid-field.js
@@ -1,145 +1,156 @@
import React from 'react';
class GridField extends React.Component {
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- this.state = {
- currentObj: 'w',
- currentImage: null,
- active: false,
- lastClickedRed: false,
- lastClickedBlue: false,
- bombTargetArea: null,
- icons: {
- root: '/images/',
- water: {
- 1: 'bg-wave-1-outbg.png',
- 2: 'bg-wave-1-outbg.png',
- 3: 'bg-wave-2-outbg.png'
- },
- flag: {
- red: 'bg-flag-red-outbg.png',
- blue: 'bg-flag-blue-outbg.png'
- },
- target: {
- lastBlue: 'bg-last-blue-outbg.png',
- lastRed: 'bg-last-red-outbg.png',
- crosshair: 'bg-target-outbg.png',
- crosshairBomb: 'bg-target-bomb-outbg.png'
- },
- left: 'bg-left-mine-outbg.png'
- }
- };
+ this.state = {
+ currentObj: 'w',
+ currentImage: null,
+ active: false,
+ lastClickedRed: false,
+ lastClickedBlue: false,
+ bombTargetArea: null,
+ icons: {
+ root: '/images/',
+ water: {
+ 1: 'bg-wave-1-outbg.png',
+ 2: 'bg-wave-1-outbg.png',
+ 3: 'bg-wave-2-outbg.png',
+ },
+ flag: {
+ red: 'bg-flag-red-outbg.png',
+ blue: 'bg-flag-blue-outbg.png',
+ },
+ target: {
+ lastBlue: 'bg-last-blue-outbg.png',
+ lastRed: 'bg-last-red-outbg.png',
+ crosshair: 'bg-target-outbg.png',
+ crosshairBomb: 'bg-target-bomb-outbg.png',
+ },
+ left: 'bg-left-mine-outbg.png',
+ },
+ };
+ }
+
+ componentWillMount() {
+ var wave = Math.floor(Math.random() * 3) + 1;
+
+ this.setState({
+ currentImage: this.state.icons.root + this.state.icons.water[wave],
+ });
+ }
+
+ classNameWhenActive() {
+ return 'field'
+ + (true === this.state.active ? ' active' : '')
+ + (true === this.state.active && 'm' === this.state.currentObj ? ' mine' : '')
+ + ' color-' + this.state.currentObj;
+ }
+
+ currentImage() {
+ return isNaN(this.state.currentImage)
+ ? (
+
+

+
+
+ ) : this.state.currentImage ? {this.state.currentImage}
: '';
+ }
+
+ lastClickedClass() {
+ return 'field-'
+ + (this.state.lastClickedRed ? 'red' : '')
+ + (this.state.lastClickedBlue ? 'blue' : '') + '-last last-clicked';
+ }
+
+ lastClickedSrc() {
+ return this.state.lastClickedRed
+ ? '/images/bg-last-red-outbg.png'
+ : '/images/bg-last-blue-outbg.png';
+ }
+
+ currentLastClicked() {
+ return this.state.lastClickedRed || this.state.lastClickedBlue
+ ? (
+
+ ) : '';
+ }
+
+ createBombTarget() {
+ if (null !== this.state.bombTargetArea) {
+ let vert, hor = '';
+
+ switch (this.state.bombTargetArea[0]) {
+ case 0:
+ vert = 'left';
+ break;
+ case 1:
+ vert = 'center';
+ break;
+ case 2:
+ vert = 'right';
+ break;
+ default:
+ vert = null;
+ break;
+ }
+
+ switch (this.state.bombTargetArea[1]) {
+ case 0:
+ hor = 'top';
+ break;
+ case 1:
+ hor = 'middle';
+ break;
+ case 2:
+ hor = 'bottom';
+ break;
+ default:
+ vert = null;
+ break;
+ }
+
+ var src = null === vert
+ ? '/images/bg-bomb-empty-outbg.png'
+ : '/images/bg-bomb-' + hor + '-' + vert + '-outbg.png';
+
+ return (
+
+ );
}
+ }
- componentWillMount() {
- var wave = Math.floor(Math.random() * 3) + 1;
-
- this.setState({
- currentImage: this.state.icons.root + this.state.icons.water[wave]
- });
- }
-
- classNameWhenActive() {
- return 'field'
- + (this.state.active === true ? ' active' : '')
- + (this.state.active === true && this.state.currentObj === 'm' ? ' mine' : '')
- + ' color-' + this.state.currentObj;
- }
-
- currentImage() {
- return isNaN(this.state.currentImage)
- ?
-
-

-
-
- : this.state.currentImage ? {this.state.currentImage}
: '';
- }
-
- lastClickedClass() {
- return 'field-'
- + (this.state.lastClickedRed ? 'red' : '')
- + (this.state.lastClickedBlue ? 'blue' : '') + '-last last-clicked';
- }
-
- lastClickedSrc() {
- return this.state.lastClickedRed
- ? "/images/bg-last-red-outbg.png"
- : "/images/bg-last-blue-outbg.png";
- }
-
- currentLastClicked() {
- return this.state.lastClickedRed || this.state.lastClickedBlue
- ?
- : '';
- }
-
- createBombTarget() {
- if (this.state.bombTargetArea !== null) {
- var vert = '', hor = '';
-
- switch (this.state.bombTargetArea[0]) {
- case 0:
- vert = 'left';
- break;
- case 1:
- vert = 'center';
- break;
- case 2:
- vert = 'right';
- break;
- default:
- vert = null;
- break;
- }
-
- switch (this.state.bombTargetArea[1]) {
- case 0:
- hor = 'top';
- break;
- case 1:
- hor = 'middle';
- break;
- case 2:
- hor = 'bottom';
- break;
- default:
- vert = null;
- break;
- }
-
- var src = vert === null
- ? '/images/bg-bomb-empty-outbg.png'
- : '/images/bg-bomb-' + hor + '-' + vert + '-outbg.png';
-
- return
- }
- }
-
- render() {
- return (
-
-

- {this.createBombTarget()}
- {this.currentLastClicked()}
-
-
- {this.currentImage()}
-
-
-
- );
- }
+ render() {
+ return (
+
+

+ {this.createBombTarget()}
+ {this.currentLastClicked()}
+
+
+ {this.currentImage()}
+
+
+
+ );
+ }
}
export default GridField;
diff --git a/assets/js/mine-seeker/grid/grid.js b/assets/js/mine-seeker/grid/grid.js
index 66857c7..d8306a3 100644
--- a/assets/js/mine-seeker/grid/grid.js
+++ b/assets/js/mine-seeker/grid/grid.js
@@ -1,101 +1,101 @@
import React from 'react';
class Grid extends React.Component {
- constructor() {
- super();
+ constructor() {
+ super();
- this.state = {
- row: 16,
- col: 16,
- mines: 51,
- set: []
- };
+ this.state = {
+ row: 16,
+ col: 16,
+ mines: 51,
+ set: [],
+ };
- this.state.grid = this.numberingGrid(
- this.createGrid(
- this.shuffleSet(
- this.createSet(
- this.state.set
- )
- )
- )
- );
+ this.state.grid = this.numberingGrid(
+ this.createGrid(
+ this.shuffleSet(
+ this.createSet(
+ this.state.set,
+ ),
+ ),
+ ),
+ );
+ }
+
+ createSet(obj) {
+ for (let i = 0, j = this.state.row * this.state.col; i < j; i++) {
+ obj.push(
+ 0 < this.state.mines
+ ? 'm'
+ : 'w',
+ );
+ this.state.mines--;
}
- createSet(obj) {
- for (var i = 0, j = this.state.row * this.state.col; i < j; i++) {
- obj.push(
- this.state.mines > 0
- ? "m"
- : "w"
- );
- this.state.mines--;
+ return obj;
+ }
+
+ shuffleSet(obj) {
+ return obj.sort(function() {
+ return Math.round(Math.random()) - .5;
+ });
+ }
+
+ createGrid(obj) {
+ let grid = [[]],
+ row = 0,
+ col = 0;
+
+ for (let i = 0, j = obj.length; i < j; i++) {
+ grid[row][col] = obj[i];
+
+ if (15 === col && 15 !== row) {
+ row++;
+ col = 0;
+ grid.push([]);
+ } else {
+ col++;
+ }
+ }
+
+ return grid;
+ }
+
+ checkMine(field, i, j) {
+ return 'undefined' !== typeof field[i] && 'undefined' !== typeof field[i][j] && 'm' === field[i][j];
+ }
+
+ isThereMine(obj, row, col) {
+ if (this.checkMine(obj, row, col)) {
+ return 1;
+ }
+ return 0;
+ }
+
+ numberingGrid(obj) {
+ let nbr = 0;
+
+ for (let i = 0; i < this.state.row; i++) {
+ for (let j = 0; j < this.state.col; j++) {
+ if ('w' === obj[i][j]) {
+ nbr = 0;
+
+ nbr += this.isThereMine(obj, i - 1, j);
+ nbr += this.isThereMine(obj, i - 1, j - 1);
+ nbr += this.isThereMine(obj, i - 1, j + 1);
+ nbr += this.isThereMine(obj, i, j - 1);
+ nbr += this.isThereMine(obj, i, j + 1);
+ nbr += this.isThereMine(obj, i + 1, j);
+ nbr += this.isThereMine(obj, i + 1, j + 1);
+ nbr += this.isThereMine(obj, i + 1, j - 1);
+
+ obj[i][j] = nbr;
}
-
- return obj;
+ }
}
- shuffleSet(obj) {
- return obj.sort(function () {
- return Math.round(Math.random()) - .5;
- });
- }
-
- createGrid(obj) {
- var grid = [[]],
- row = 0,
- col = 0;
-
- for (var i = 0, j = obj.length; i < j; i++) {
- grid[row][col] = obj[i];
-
- if (col === 15 && row !== 15) {
- row++;
- col = 0;
- grid.push([]);
- } else {
- col++;
- }
- }
-
- return grid;
- }
-
- checkMine(field, i, j) {
- return typeof field[i] !== 'undefined' && typeof field[i][j] !== 'undefined' && field[i][j] === 'm';
- }
-
- isThereMine(obj, row, col) {
- if (this.checkMine(obj, row, col)) {
- return 1;
- }
- return 0;
- }
-
- numberingGrid(obj) {
- var nbr = 0;
-
- for (var i = 0; i < this.state.row; i++) {
- for (var j = 0; j < this.state.col; j++) {
- if (obj[i][j] === 'w') {
- nbr = 0;
-
- nbr += this.isThereMine(obj, i - 1, j);
- nbr += this.isThereMine(obj, i - 1, j - 1);
- nbr += this.isThereMine(obj, i - 1, j + 1);
- nbr += this.isThereMine(obj, i, j - 1);
- nbr += this.isThereMine(obj, i, j + 1);
- nbr += this.isThereMine(obj, i + 1, j);
- nbr += this.isThereMine(obj, i + 1, j + 1);
- nbr += this.isThereMine(obj, i + 1, j - 1);
-
- obj[i][j] = nbr;
- }
- }
- }
-
- return obj;
- }
+ return obj;
+ }
}
export default Grid;
diff --git a/assets/js/mine-seeker/user/user-control.js b/assets/js/mine-seeker/user/user-control.js
index 86afcd4..17e16d9 100644
--- a/assets/js/mine-seeker/user/user-control.js
+++ b/assets/js/mine-seeker/user/user-control.js
@@ -2,77 +2,81 @@ import React from 'react';
import User from './user';
class UserControl extends React.Component {
- constructor() {
- super();
+ constructor() {
+ super();
- /**
- * activePlayer - red: 0, blue: 1
- * @type {{activePlayer: boolean, mines: number, bombSelected: boolean, foundMines: boolean}}
- */
- this.state = {
- activePlayer: false,
- mines: 51,
- bombSelected: false,
- foundMines: false
- };
+ /**
+ * activePlayer - red: 0, blue: 1
+ * @type {{activePlayer: boolean, mines: number, bombSelected: boolean, foundMines: boolean}}
+ */
+ this.state = {
+ activePlayer: false,
+ mines: 51,
+ bombSelected: false,
+ foundMines: false,
+ };
+ }
+
+ youCanSelectBomb(activePlayer, clickedPlayer) {
+ return this.refs[activePlayer].state.haveBomb
+ && this.refs[activePlayer].state.enabledBomb
+ && this.state.activePlayer === clickedPlayer;
+ }
+
+ onClickBombSelector(clickedPlayer) {
+ let activePlayer = this.state.activePlayer ? 'blue' : 'red';
+
+ if (this.youCanSelectBomb(activePlayer, clickedPlayer)) {
+ this.state.bombSelected = !this.state.bombSelected;
+
+ if (!this.state.bombSelected) {
+ this.props.bombClear();
+ }
}
+ }
- youCanSelectBomb(activePlayer, clickedPlayer) {
- return this.refs[activePlayer].state.haveBomb &&
- this.refs[activePlayer].state.enabledBomb &&
- this.state.activePlayer === clickedPlayer;
- }
+ getResignClass(webPlayer) {
+ let activePlayer = 1 === this.state.activePlayer ? 'blue' : 'red';
+ return 'resign' + (webPlayer !== activePlayer ? ' disabled' : '');
+ }
- onClickBombSelector(clickedPlayer) {
- let activePlayer = this.state.activePlayer ? 'blue' : 'red';
+ activeMines() {
+ return 'active-mines' + (this.state.foundMines ? ' found-mine' : '');
+ }
- if (this.youCanSelectBomb(activePlayer, clickedPlayer)) {
- this.state.bombSelected = !this.state.bombSelected;
-
- if (!this.state.bombSelected) {
- this.props.bombClear();
- }
- }
- }
-
- getResignClass(webPlayer) {
- let activePlayer = this.state.activePlayer === 1 ? 'blue' : 'red';
- return "resign" + (webPlayer !== activePlayer ? ' disabled' : '');
- }
-
- activeMines() {
- return "active-mines" + (this.state.foundMines ? ' found-mine' : '');
- }
-
- render() {
- return (
-
- );
- }
+ render() {
+ return (
+
+ );
+ }
}
export default UserControl;
diff --git a/assets/js/mine-seeker/user/user.js b/assets/js/mine-seeker/user/user.js
index 851d082..ff93fa3 100644
--- a/assets/js/mine-seeker/user/user.js
+++ b/assets/js/mine-seeker/user/user.js
@@ -1,90 +1,90 @@
import React from 'react';
class User extends React.Component {
- constructor(props) {
- super(props);
+ constructor(props) {
+ super(props);
- this.state = {
- name: "...",
- desc: "",
- active: props.active,
- color: props.color === 'blue' ? 1 : 0,
- mines: 0,
- srcRoot: '/images/',
- haveBomb: true,
- enabledBomb: true
- };
+ this.state = {
+ name: '...',
+ desc: '',
+ active: props.active,
+ color: 'blue' === props.color ? 1 : 0,
+ mines: 0,
+ srcRoot: '/images/',
+ haveBomb: true,
+ enabledBomb: true,
+ };
+ }
+
+ setColor(color) {
+ return 'user-container user-' + color;
+ }
+
+ getSrc(color) {
+ return this.state.srcRoot + 'bg-flag-' + color + '-outbg.png';
+ }
+
+ getBombBuzzClass(webPlayer) {
+ let activePlayer = 1 === this.state.color ? 'blue' : 'red';
+
+ return 'bomb-container'
+ + (
+ this.state.active && (activePlayer === webPlayer) && this.state.haveBomb && this.state.enabledBomb
+ ? ' buzz'
+ : ''
+ );
+ }
+
+ getBomb() {
+ let src = this.state.srcRoot;
+
+ if (this.state.haveBomb) {
+ src += this.state.enabledBomb && this.state.active
+ ? 'bg-bomb-outbg.png'
+ : 'bg-bomb-disabled-outbg.png';
+ } else {
+ src += 'bg-bomb-exploded-outbg.png';
}
- setColor(color) {
- return 'user-container user-' + color;
- }
+ return src;
+ }
- getSrc(color) {
- return this.state.srcRoot + 'bg-flag-' + color + '-outbg.png';
- }
+ getFigure(color) {
+ return this.state.srcRoot + 'bg-figure-' + color + '-outbg.png';
+ }
- getBombBuzzClass(webPlayer) {
- let activePlayer = this.state.color === 1 ? 'blue' : 'red';
+ getCursor(state, color) {
+ return state
+ ?
+ : '';
+ }
- return "bomb-container" +
- (
- this.state.active && (activePlayer === webPlayer) && this.state.haveBomb && this.state.enabledBomb
- ? ' buzz'
- : ''
- );
- }
-
- getBomb() {
- let src = this.state.srcRoot;
-
- if (this.state.haveBomb) {
- src += this.state.enabledBomb && this.state.active
- ? 'bg-bomb-outbg.png'
- : 'bg-bomb-disabled-outbg.png';
- } else {
- src += 'bg-bomb-exploded-outbg.png';
- }
-
- return src;
- }
-
- getFigure(color) {
- return this.state.srcRoot + 'bg-figure-' + color + '-outbg.png';
- }
-
- getCursor(state, color) {
- return state
- ?
- : '';
- }
-
- render() {
- return (
-
-
-
{this.props.color}
- {this.getCursor(this.props.active, this.props.color)}
-
})
-
-
{this.state.name}
-
-
{this.state.desc}
-
-
})
-
- {this.state.mines}
-
-
-
-
})
-
-
-
-
+ render() {
+ return (
+
+
+
{this.props.color}
+ {this.getCursor(this.props.active, this.props.color)}
+
})
+
+
{this.state.name}
+
+
{this.state.desc}
+
+
})
+
+ {this.state.mines}
+
+
+
+
- );
- }
+
+
+
+
+ );
+ }
}
export default User;