|
|
|
@ -27,7 +27,7 @@ import TractorFullImg from './../../../assets/img/tractor-with-spikes.svg'
|
|
|
|
|
import HarvesterImg from './../../../assets/img/harvester.svg'
|
|
|
|
|
import VolcanoImg from './../../../assets/img/volcano2.gif'
|
|
|
|
|
|
|
|
|
|
import React, { Fragment } from 'react'
|
|
|
|
|
import React, { Fragment, useState } from 'react'
|
|
|
|
|
import ReactDOM from 'react-dom'
|
|
|
|
|
import { connect } from 'react-redux'
|
|
|
|
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|
|
|
@ -191,7 +191,13 @@ class PlayerResources extends React.Component {
|
|
|
|
|
|
|
|
|
|
// http://stackoverflow.com/questions/149055
|
|
|
|
|
function formatMoney(n) {
|
|
|
|
|
return n.toFixed(1).replace(/(\d)(?=(\d{3})+\.)/g, '$1,').slice(0, -2); }
|
|
|
|
|
if (typeof n === 'number') {
|
|
|
|
|
return n.toFixed(1).replace(/(\d)(?=(\d{3})+\.)/g, '$1,').slice(0, -2);
|
|
|
|
|
} else {
|
|
|
|
|
console.trace(n);
|
|
|
|
|
return 'NaN';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MoneySummary extends React.Component {
|
|
|
|
|
render () {
|
|
|
|
@ -1916,60 +1922,141 @@ class Board extends React.Component {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// handler, buttonText, children
|
|
|
|
|
class AlertOverlay extends React.Component {
|
|
|
|
|
constructor(props) {
|
|
|
|
|
super(props);
|
|
|
|
|
this.state = { visible: typeof this.props.visible !== 'undefined' ?
|
|
|
|
|
this.props.visible : true };
|
|
|
|
|
}
|
|
|
|
|
const AlertOverlay = ({ visible, alertHandled, hideHandler, id, handler, cancelHandler, preventHiding,
|
|
|
|
|
children, disabled, buttonText, cancelButtonText, cancelDisabled }) => {
|
|
|
|
|
const [isVisible, setIsVisible] = useState(typeof visible !== 'undefined' ? visible : true);
|
|
|
|
|
|
|
|
|
|
hide = e => {
|
|
|
|
|
const hide = (e) => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
this.setState({ visible: false });
|
|
|
|
|
this.props.alertHandled(this.props.id);
|
|
|
|
|
this.props.hideHandler();
|
|
|
|
|
setIsVisible(false);
|
|
|
|
|
alertHandled(id);
|
|
|
|
|
hideHandler();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buttonClick = e => {
|
|
|
|
|
this.hide(e);
|
|
|
|
|
this.props.handler();
|
|
|
|
|
const buttonClick = (e) => {
|
|
|
|
|
hide(e);
|
|
|
|
|
handler();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cancelButtonClick = e => {
|
|
|
|
|
const cancelButtonClick = (e) => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
this.props.cancelHandler();
|
|
|
|
|
cancelHandler();
|
|
|
|
|
}
|
|
|
|
|
// <label><input type='checkbox' onClick={this.hidePermanent} /> {`Don't show again`}</label>
|
|
|
|
|
|
|
|
|
|
render() {
|
|
|
|
|
return (
|
|
|
|
|
<div className={'alert-overlay' + (this.state.visible ? '' : ' hidden') }>
|
|
|
|
|
{!this.props.preventHiding ? (
|
|
|
|
|
<div onClick={this.hide} className='alert-overlay-hide'>
|
|
|
|
|
<div className={'alert-overlay' + (isVisible ? '' : ' hidden') }>
|
|
|
|
|
{!preventHiding ? (
|
|
|
|
|
<div onClick={hide} className='alert-overlay-hide'>
|
|
|
|
|
<FontAwesomeIcon icon={faTimes} />
|
|
|
|
|
</div>
|
|
|
|
|
) : (<></>)}
|
|
|
|
|
<div className='alert-container'>
|
|
|
|
|
<div className='alert-overlay-contents'>
|
|
|
|
|
{this.props.children}
|
|
|
|
|
{children}
|
|
|
|
|
<br />
|
|
|
|
|
<div>
|
|
|
|
|
<Button onClick={this.buttonClick} disabled={!!this.props.disabled}>{this.props.buttonText}</Button>
|
|
|
|
|
{this.props.cancelButtonText ? (
|
|
|
|
|
<Button onClick={buttonClick} disabled={!!disabled}>{buttonText}</Button>
|
|
|
|
|
{cancelButtonText ? (
|
|
|
|
|
<>
|
|
|
|
|
{' '}
|
|
|
|
|
<Button onClick={this.cancelButtonClick} disabled={!!this.props.cancelDisabled}>
|
|
|
|
|
{this.props.cancelButtonText}
|
|
|
|
|
<Button onClick={cancelButtonClick} disabled={!!cancelDisabled}>
|
|
|
|
|
{cancelButtonText}
|
|
|
|
|
</Button>
|
|
|
|
|
</>
|
|
|
|
|
): (<></>)}
|
|
|
|
|
</div>
|
|
|
|
|
{!this.props.preventHiding ? (<a onClick={this.hide}>close</a>) : (<></>)}
|
|
|
|
|
{!preventHiding ? (<a onClick={hide}>close</a>) : (<></>)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const gameOverTabs = { initial: 'Summary', harvest: 'Harvests', investments: 'Investments' };
|
|
|
|
|
const GameOver = ({ id, alertHandled, contents, game, player}) => {
|
|
|
|
|
const [tab, setTab] = useState(gameOverTabs.initial);
|
|
|
|
|
|
|
|
|
|
const tabClass = (screen) =>
|
|
|
|
|
'tab border-top' + (tab === screen ? ' show ' : '');
|
|
|
|
|
|
|
|
|
|
const iconClass = (screen) =>
|
|
|
|
|
tab === screen ? 'is-active' : ' ';
|
|
|
|
|
|
|
|
|
|
const iconOnClick = (icon) =>
|
|
|
|
|
(e) => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
setTab(icon);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const playerRidgeValue = (player, otherPlayers) => {
|
|
|
|
|
const ridges = makeRidgeLookup(player, otherPlayers);
|
|
|
|
|
return (ridges.ridge1 ? 10 : 0) +
|
|
|
|
|
(ridges.ridge2 ? 15 : 0) +
|
|
|
|
|
(ridges.ridge3 ? 20 : 0) +
|
|
|
|
|
(ridges.ridge4 ? 25 : 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<AlertOverlay visible={true}
|
|
|
|
|
id={id}
|
|
|
|
|
alertHandled={alertHandled}
|
|
|
|
|
buttonText='Close'
|
|
|
|
|
hideHandler={() => 'nothing'}
|
|
|
|
|
handler={() => { return false; }}>
|
|
|
|
|
<div className="game-over">
|
|
|
|
|
<h1>Game Over!</h1>
|
|
|
|
|
<ul className='menu icons icons-top'>
|
|
|
|
|
{[gameOverTabs.initial, gameOverTabs.harvest, gameOverTabs.investments]
|
|
|
|
|
.map((icon, i) =>
|
|
|
|
|
(<li key={i} className={iconClass(icon)}>
|
|
|
|
|
<div></div>
|
|
|
|
|
<a onClick={iconOnClick(icon)}>
|
|
|
|
|
{icon}
|
|
|
|
|
</a>
|
|
|
|
|
</li>))}
|
|
|
|
|
</ul>
|
|
|
|
|
<div className="">
|
|
|
|
|
<div className={tabClass(gameOverTabs.initial)}>
|
|
|
|
|
{contents.results.map((e, i) => (
|
|
|
|
|
<p key={i}>{e}</p>
|
|
|
|
|
))}
|
|
|
|
|
<p>{contents.stats.pro}</p>
|
|
|
|
|
<p>{contents.stats.back}</p>
|
|
|
|
|
<p>{contents.stats.taxPerson}</p>
|
|
|
|
|
<p>{contents.stats.emergency}</p>
|
|
|
|
|
<p>{contents.stats.highRoller}</p>
|
|
|
|
|
<p>{contents.stats.lowRoller}</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={tabClass(gameOverTabs.harvest)}>
|
|
|
|
|
{contents.stats.players.map(p => (
|
|
|
|
|
<div key={p.name}>
|
|
|
|
|
<p><b>{p.name} Harvests:</b></p>
|
|
|
|
|
<p>Total: ${formatMoney(p.harvestTotal)} Expenses: ${formatMoney(Math.abs(p.operatingExpenses))}</p>
|
|
|
|
|
<p>Avg ${formatMoney(p.harvestAverage)} rolling {p.harvestRoll} for {p.numHarvests} harvests</p>
|
|
|
|
|
<p>Hay: ${formatMoney(p.hay)} Grain: ${formatMoney(p.grain)} Fruit: ${formatMoney(p.fruit)} Cows: ${formatMoney(p.cows)}</p>
|
|
|
|
|
</div>))}
|
|
|
|
|
</div>
|
|
|
|
|
<div className={tabClass(gameOverTabs.investments)}>
|
|
|
|
|
{contents.stats.players.map(p => {
|
|
|
|
|
const pObj = findPlayer(game, p.name) || player;
|
|
|
|
|
return (
|
|
|
|
|
<div key={p.name}>
|
|
|
|
|
<p><b>{p.name} Investments:</b></p>
|
|
|
|
|
<p>Total: ${formatMoney(assetsValue(pObj))}</p>
|
|
|
|
|
<p>Hay: {(p.hay / ((pObj.assets.hay * 2000) || 0.001)).toFixed(2)} {' '}
|
|
|
|
|
Grain: {(p.grain / ((pObj.assets.grain * 2000) || 0.001)).toFixed(2)} {' '}
|
|
|
|
|
Fruit: {(p.fruit / ((pObj.assets.fruit * 5000) || 0.001)).toFixed(2)} {' '}
|
|
|
|
|
Cows: {(p.cows / (((pObj.assets.cows * 500) + (playerRidgeValue(pObj, game.otherPlayers))) || 0.001)).toFixed(2)}
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</AlertOverlay>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class InfoBar extends React.Component {
|
|
|
|
@ -2255,34 +2342,11 @@ class BoardApp extends React.Component {
|
|
|
|
|
let alertOverlay;
|
|
|
|
|
const alert = this.props.ui.unhandledAlert;
|
|
|
|
|
if (alert && alert.type === ALERTS.endOfGame) {
|
|
|
|
|
alertOverlay = (
|
|
|
|
|
<AlertOverlay visible={true}
|
|
|
|
|
id={alert.id}
|
|
|
|
|
alertOverlay = (<GameOver id={alert.id}
|
|
|
|
|
game={this.props.game}
|
|
|
|
|
player={this.props.player}
|
|
|
|
|
alertHandled={this.props.alertHandled}
|
|
|
|
|
buttonText='Close'
|
|
|
|
|
hideHandler={() => 'nothing'}
|
|
|
|
|
handler={() => { return false; }}>
|
|
|
|
|
<div className="game-over">
|
|
|
|
|
<h1>Game Over!</h1>
|
|
|
|
|
{alert.contents.results.map((e, i) => (
|
|
|
|
|
<p key={i}>{e}</p>
|
|
|
|
|
))}
|
|
|
|
|
<p>{alert.contents.stats.pro}</p>
|
|
|
|
|
<p>{alert.contents.stats.back}</p>
|
|
|
|
|
<p>{alert.contents.stats.taxPerson}</p>
|
|
|
|
|
<p>{alert.contents.stats.emergency}</p>
|
|
|
|
|
<p>{alert.contents.stats.highRoller}</p>
|
|
|
|
|
<p>{alert.contents.stats.lowRoller}</p>
|
|
|
|
|
{alert.contents.stats.players.map(p => (
|
|
|
|
|
<div key={p.name}>
|
|
|
|
|
<p><b>{p.name} Harvests:</b></p>
|
|
|
|
|
<p>Total: ${formatMoney(p.harvestTotal)} Expenses: ${formatMoney(Math.abs(p.operatingExpenses))}</p>
|
|
|
|
|
<p>Avg ${formatMoney(p.harvestAverage)} rolling {p.harvestRoll} for {p.numHarvests} harvests</p>
|
|
|
|
|
<p>Hay: ${formatMoney(p.hay)} Grain: ${formatMoney(p.grain)} Fruit: ${formatMoney(p.fruit)} Cows: ${formatMoney(p.cows)}</p>
|
|
|
|
|
</div>))}
|
|
|
|
|
</div>
|
|
|
|
|
</AlertOverlay>
|
|
|
|
|
);
|
|
|
|
|
contents={alert.contents} />);
|
|
|
|
|
} else if (alert && alert.type === ALERTS.auditCalled) {
|
|
|
|
|
alertOverlay = (
|
|
|
|
|
<AlertOverlay visible={true}
|
|
|
|
|