Visual card trading.
This commit is contained in:
@@ -32,9 +32,9 @@ import ReactDOM from 'react-dom'
|
||||
import { connect } from 'react-redux'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faUser, faUsers, faTractor, faWindowRestore,
|
||||
faDollarSign, faTimes, faAsterisk, faExchangeAlt,
|
||||
faDollarSign, faTimes, faExchangeAlt,
|
||||
faInfoCircle, faArrowUp, faArrowDown, faAward,
|
||||
faTimesCircle, faBan } from '@fortawesome/free-solid-svg-icons'
|
||||
faBan, faArrowCircleLeft } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
import { GroupBox, Row, Col, Button } from '../widgets.jsx'
|
||||
import SpaceNode from './SpaceNode.jsx'
|
||||
@@ -48,7 +48,7 @@ import { setSelectedCard, setMessagePanelSpace, setMPDims, movePlayer,
|
||||
import { buy, roll, endTurn, loan, trade, submitTradeAccept,
|
||||
submitTradeDeny, submitTradeCancel, audit,
|
||||
buyUncleBert, skip, endAiTurn, startGame, readyToStart,
|
||||
leaveGame, kickPlayer } from './interface.js'
|
||||
leaveGame, kickPlayer, toggleRevealForTrade } from './interface.js'
|
||||
|
||||
function netWorth(player) {
|
||||
return ((player.assets.hay + player.assets.grain) * 2000) +
|
||||
@@ -65,116 +65,6 @@ function assetsValue(player) {
|
||||
((player.assets.harvester + player.assets.tractor) * 10000);
|
||||
}
|
||||
|
||||
function getElementValue(id) {
|
||||
return document.getElementById(id).value;
|
||||
}
|
||||
|
||||
function getString(id) {
|
||||
return getElementValue(id);
|
||||
}
|
||||
|
||||
function getInt(id) {
|
||||
const i = parseInt(getElementValue(id));
|
||||
return isNaN(i) ? 0 : i;
|
||||
}
|
||||
|
||||
function getChecked(id) {
|
||||
return document.getElementById(id).checked;
|
||||
}
|
||||
|
||||
function getOption(id) {
|
||||
let options = document.getElementById(id).selectedOptions;
|
||||
if (options.length > 0) {
|
||||
return options[0].value;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function submitTrade() {
|
||||
trade({ hay: getInt('trade-hay'), grain: getInt('trade-grain'),
|
||||
fruit: getInt('trade-fruit'), cows: getInt('trade-cows'),
|
||||
harvester: getInt('trade-harvesters'),
|
||||
tractor: getInt('trade-tractors'),
|
||||
ridge1: getChecked('trade-ridge1'),
|
||||
ridge2: getChecked('trade-ridge2'),
|
||||
ridge3: getChecked('trade-ridge3'),
|
||||
ridge4: getChecked('trade-ridge4'),
|
||||
player: getOption('trade-player'),
|
||||
money: getInt('trade-money'), cards: getString('trade-cards') });
|
||||
}
|
||||
|
||||
function tradeString(player, invert) {
|
||||
var r = '';
|
||||
let mult = invert ? -1 : 1;
|
||||
for (var k in player.trade) {
|
||||
if (k !== 'player' && k !== 'originator' && k !== 'cards' && k !== 'trade-number') {
|
||||
r += (player.trade[k] === true ? '' : player.trade[k] * mult) + ' ' + k + ', ';
|
||||
} else if (k === 'cards') {
|
||||
r += 'cards: ' + player.trade[k] + ', ';
|
||||
}
|
||||
}
|
||||
return r.slice(0, -2); // remove last ", "
|
||||
}
|
||||
|
||||
class PlayerTradeProposed extends React.Component {
|
||||
render () {
|
||||
if (this.props.player.trade.error) {
|
||||
return (<p><b>ERROR:</b> {this.props.player.trade.error}</p>);
|
||||
} else if (this.props.player.trade.player === undefined) {
|
||||
return (<p>You GAIN something if it is POSITIVE and you GIVE something if it is NEGATIVE.</p>);
|
||||
} else if (this.props.player.trade.originator === this.props.player.name) {
|
||||
return (<p>You proposed a trade with <b>{this.props.player.trade.player}</b> for
|
||||
{'\u00A0'}<b>{tradeString(this.props.player, false)}</b>.</p>);
|
||||
} else {
|
||||
return (<p><b>{this.props.player.trade.originator}</b> proposed a trade for
|
||||
{'\u00A0'}<b>{tradeString(this.props.player, true)}</b>.</p>);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function tradeFormSubmit(e, player) {
|
||||
e.preventDefault();
|
||||
if (player.trade.player === undefined) {
|
||||
submitTrade();
|
||||
} else if (player.trade.originator === player.name) {
|
||||
submitTradeCancel();
|
||||
} else {
|
||||
submitTradeAccept();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class PlayerTradeButton extends React.Component {
|
||||
tradeDeny = e => {
|
||||
e.preventDefault();
|
||||
submitTradeDeny();
|
||||
}
|
||||
|
||||
render() {
|
||||
var text = '';
|
||||
var receiver = false;
|
||||
if (this.props.player.trade.player === undefined) {
|
||||
text = 'Propose';
|
||||
} else if (this.props.player.trade.originator === this.props.player.name) {
|
||||
text = 'Cancel';
|
||||
} else {
|
||||
text = 'Accept';
|
||||
receiver = true;
|
||||
}
|
||||
if (!receiver) {
|
||||
return (<Button className='tiny' type='submit'>{text} Trade</Button>);
|
||||
} else {
|
||||
return (<Fragment>
|
||||
<Button className='tiny' type='submit'>{text} Trade</Button>
|
||||
<Button className='tiny' onClick={this.tradeDeny}>
|
||||
Deny Trade
|
||||
</Button>
|
||||
</Fragment>);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ResourceUnit extends React.Component {
|
||||
render () {
|
||||
const hslString = 'hsl(' + this.props.h + ', ' + this.props.s;
|
||||
@@ -197,61 +87,6 @@ class ResourceUnit extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
class PlayerTradeResources extends React.Component {
|
||||
render () {
|
||||
let player = this.props.player;
|
||||
return (
|
||||
<form onSubmit={e => tradeFormSubmit(e, player)}>
|
||||
<div className='player-trade-resources'>
|
||||
<ResourceUnit img={HayImg} h='120' s='100' label='acres of Hay' amount={''}>
|
||||
<input type='number' id='trade-hay' defaultValue='0' />
|
||||
</ResourceUnit> {' '}
|
||||
<ResourceUnit img={WheatImg} h='41' s='100' label='acres of Grain' amount={''}>
|
||||
<input type='number' id='trade-grain' defaultValue='0' />
|
||||
</ResourceUnit> {' '}
|
||||
<ResourceUnit img={FruitImg} h='0' s='100' label='acres of Fruit' amount={''}>
|
||||
<input type='number' id='trade-fruit' defaultValue='0' />
|
||||
</ResourceUnit> {' '}
|
||||
<ResourceUnit img={CowImg} h='0' s='59' label='head of Cows' amount={''}>
|
||||
<input type='number' id='trade-cows' defaultValue='0' />
|
||||
</ResourceUnit> {' '}
|
||||
<ResourceUnit img={HarvesterImg} h='240' s='100' label='Harvesters' amount={''}>
|
||||
<input type='number' id='trade-harvesters' defaultValue='0' />
|
||||
</ResourceUnit> {' '}
|
||||
<ResourceUnit img={TractorImg} h='240' s='100' label='Tractors' amount={''}>
|
||||
<input type='number' id='trade-tractors' defaultValue='0' />
|
||||
</ResourceUnit>
|
||||
<br />
|
||||
<b>Ridges</b>: <b>{ridgeNames[0][0]}</b>: <input type='checkbox' id='trade-ridge1' />{'\u00A0'}
|
||||
<b>R</b>: <input type='checkbox' id='trade-ridge2' />{'\u00A0'}
|
||||
<b>C</b>: <input type='checkbox' id='trade-ridge3' />{'\u00A0'}
|
||||
<b>T</b>: <input type='checkbox' id='trade-ridge4' />{'\u00A0'}
|
||||
<br /><br />
|
||||
<Row>
|
||||
<Col width='4 column-no-padding'>
|
||||
<label htmlFor='trade-player'><b>Player</b>:</label>
|
||||
<select id='trade-player'>
|
||||
{this.props.otherPlayers.map(p => (
|
||||
<option key={p.player.name} value={p.player.name}>{p.player.name}</option>
|
||||
))}
|
||||
</select>
|
||||
</Col>
|
||||
<Col width='4 column-no-padding'>
|
||||
<label htmlFor='trade-money'><b>Money</b>: </label>
|
||||
<input type='number' id='trade-money' defaultValue='0' />
|
||||
</Col>
|
||||
<Col width='4 column-no-padding'>
|
||||
<label htmlFor='trade-cards'><b>Cards</b>: </label>
|
||||
<input type='text' id='trade-cards' placeholder="12 46" />
|
||||
</Col>
|
||||
</Row>
|
||||
<PlayerTradeProposed player={this.props.player} />
|
||||
<PlayerTradeButton player={this.props.player} />
|
||||
</div>
|
||||
</form>);
|
||||
}
|
||||
}
|
||||
|
||||
class PlayerResources extends React.Component {
|
||||
render () {
|
||||
const player = this.props.player;
|
||||
@@ -495,13 +330,75 @@ class FarmsContainer extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
class TradeContainer extends React.Component {
|
||||
render() {
|
||||
class TradeCard extends React.Component {
|
||||
render () {
|
||||
const card = this.props.card;
|
||||
let action = (null);
|
||||
if (card.type === 'no-card') {
|
||||
action = (<span></span>);
|
||||
} else {
|
||||
action = (
|
||||
<div className='card-action'>
|
||||
<Row>
|
||||
<Col width="12">
|
||||
<Button onClick={() => this.props.tradeCard(card)}>Trade Card</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<GroupBox title='Trade'>
|
||||
<PlayerTradeResources otherPlayers={this.props.game.otherPlayers}
|
||||
player={this.props.player} />
|
||||
</GroupBox>
|
||||
<div className='game-card'>
|
||||
<GroupBox title={card.title}>
|
||||
<div className='card'
|
||||
dangerouslySetInnerHTML={{__html: card.contents}} />
|
||||
{action}
|
||||
</GroupBox>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const makeEmptyCard = () => { return { type: 'no-card', contents: '', total: 0, id: -1 }; }
|
||||
|
||||
class TradeCards extends React.Component {
|
||||
state = {
|
||||
selectedCard: makeEmptyCard()
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.player.cards.length > 0) {
|
||||
this.setState({ selectedCard: this.props.player.cards[0] });
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { player, cardsBeingTraded } = this.props;
|
||||
const isMe = this.props.me.name === player.name;
|
||||
return (
|
||||
<>
|
||||
<CardListComp ui={player}
|
||||
title={(
|
||||
<>
|
||||
<a onClick={this.props.goBack}>
|
||||
<FontAwesomeIcon icon={faArrowCircleLeft} />
|
||||
</a>
|
||||
{isMe ? (
|
||||
<>Your Cards</>
|
||||
) : (
|
||||
<>{player.name}'s Cards</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
visibleCards={isMe ? player.cards.filter(c => !cardsBeingTraded.includes(c.id)).map(c => c.id) :
|
||||
player.revealedCards.filter(c => !cardsBeingTraded.includes(c))}
|
||||
cardId={this.state.selectedCard.id}
|
||||
setCard={(c) => this.setState({ selectedCard: c })}
|
||||
setCardError={() => 'nothing'}
|
||||
/>
|
||||
<TradeCard card={this.state.selectedCard}
|
||||
tradeCard={this.props.tradeCard} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -531,7 +428,16 @@ const makeDefaultToTrade = () => {
|
||||
};
|
||||
}
|
||||
|
||||
class TradeContainer2 extends React.Component {
|
||||
|
||||
/* <Row>
|
||||
* <Col width="12">
|
||||
* <input type="text" placeholder="Cards"
|
||||
* defaultValue={toTrade.cards}
|
||||
* onChange={e => this.tradeAsset('cards', e.target.value)} />
|
||||
* </Col>
|
||||
* </Row> */
|
||||
|
||||
class TradeContainer extends React.Component {
|
||||
resources = [{ img: HayImg,
|
||||
h: '120',
|
||||
s: '100',
|
||||
@@ -584,11 +490,16 @@ class TradeContainer2 extends React.Component {
|
||||
|
||||
state = {
|
||||
otherPlayer: findPlayer(this.props.game, this.props.game.otherPlayers.length > 0 ? this.props.game.otherPlayers[0].player.name : ''),
|
||||
toTrade: makeDefaultToTrade()
|
||||
toTrade: makeDefaultToTrade(),
|
||||
showCards: false,
|
||||
showCardsPlayer: false,
|
||||
sendCards: [],
|
||||
receiveCards: []
|
||||
}
|
||||
|
||||
selectPlayer = e => {
|
||||
this.setState({ otherPlayer: findPlayer(this.props.game, e.target.value) });
|
||||
this.setState({ otherPlayer: findPlayer(this.props.game, e.target.value),
|
||||
receiveCards: [] });
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
@@ -596,8 +507,10 @@ class TradeContainer2 extends React.Component {
|
||||
prevProps.game.otherPlayers.length !== this.props.game.otherPlayers.length) {
|
||||
this.setState({ otherPlayer: findPlayer(this.props.game,
|
||||
this.props.game.otherPlayers.length > 0 ? this.props.game.otherPlayers[0].player.name : '') });
|
||||
} else if (this.state.otherPlayer && this.state.otherPlayer.name !== findPlayer(this.props.game, this.state.otherPlayer.name).name) {
|
||||
this.setState({ otherPlayer: findPlayer(this.props.game, this.state.otherPlayer.name) });
|
||||
} else if (this.state.otherPlayer && this.state.otherPlayer !== findPlayer(this.props.game, this.state.otherPlayer.name)) {
|
||||
this.setState({ otherPlayer: findPlayer(this.props.game, this.state.otherPlayer.name),
|
||||
receiveCards: [],
|
||||
sendCards: [] });
|
||||
}
|
||||
if (prevProps.player.trade.originator && !this.props.player.trade.originator) {
|
||||
this.setState({ otherPlayer: findPlayer(this.props.game,
|
||||
@@ -624,14 +537,22 @@ class TradeContainer2 extends React.Component {
|
||||
} else {
|
||||
tradeObj = this.props.player.trade;
|
||||
}
|
||||
const cards = tradeObj.cards.split(' ').map(i => parseInt(i)),
|
||||
myCards = this.props.player.cards.filter(c => cards.includes(c.id)),
|
||||
myCardsIds = myCards.map(c => c.id);
|
||||
console.log(cards);
|
||||
console.log(myCards)
|
||||
const otherPlayer = findPlayer(this.props.game, isOriginator ?
|
||||
this.props.player.trade.player : this.props.player.trade.originator);
|
||||
this.setState({
|
||||
toTrade: {
|
||||
...makeDefaultToTrade(),
|
||||
...tradeObj,
|
||||
money: tradeObj.money ? tradeObj.money / 1000 : 0
|
||||
},
|
||||
otherPlayer: findPlayer(this.props.game, isOriginator ?
|
||||
this.props.player.trade.player : this.props.player.trade.originator)
|
||||
receiveCards: otherPlayer.cards.filter(c => cards.includes(c.id) && !myCardsIds.includes(c.id)),
|
||||
sendCards: myCards,
|
||||
otherPlayer
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -659,11 +580,35 @@ class TradeContainer2 extends React.Component {
|
||||
|
||||
propose = () => {
|
||||
trade({ ...this.state.toTrade,
|
||||
cards: this.state.sendCards.map(c => c.id).concat(this.state.receiveCards.map(c => c.id)).join(' '),
|
||||
money: this.state.toTrade.money * 1000,
|
||||
player: this.state.otherPlayer.name
|
||||
})
|
||||
}
|
||||
|
||||
viewPlayerCards = (e, player) => {
|
||||
e.preventDefault();
|
||||
this.setState(state => {
|
||||
return { showCards: !state.showCards,
|
||||
showCardsPlayer: player };
|
||||
});
|
||||
}
|
||||
|
||||
tradeCard = (card) => {
|
||||
if (this.props.player === this.state.showCardsPlayer) {
|
||||
this.setState({ sendCards: [...this.state.sendCards, card],
|
||||
showCards: false });
|
||||
} else {
|
||||
this.setState({ receiveCards: [...this.state.receiveCards, card],
|
||||
showCards: false });
|
||||
}
|
||||
}
|
||||
|
||||
unTradeCard = (id) => {
|
||||
this.setState({ sendCards: this.state.sendCards.filter(c => c.id !== id),
|
||||
receiveCards: this.state.receiveCards.filter(c => c.id !== id) });
|
||||
}
|
||||
|
||||
render() {
|
||||
const player = this.props.player,
|
||||
otherPlayer = this.state.otherPlayer,
|
||||
@@ -671,59 +616,78 @@ class TradeContainer2 extends React.Component {
|
||||
tradeProposed = !!player.trade.originator;
|
||||
return (
|
||||
<GroupBox title='Trade'>
|
||||
<Row>
|
||||
<Col width="12">
|
||||
<div className="trade-player-container">
|
||||
<h4>{player.name}</h4>
|
||||
{Object.keys(player.ridges).map((ridge, idx) => (
|
||||
<Fragment key={'player-trade' + ridge}>
|
||||
{!tradeProposed && (player.ridges[ridge] > 0) && !toTrade[ridge] ? (
|
||||
<Button className="tiny"
|
||||
onClick={() => this.tradeAsset(ridge, player.ridges[ridge], true)}>
|
||||
<FontAwesomeIcon icon={faArrowDown} /> {ridgeNames[idx]} {'('}{player.ridges[ridge]} cows{')'}
|
||||
</Button>
|
||||
) : (<></>)}
|
||||
{' '}
|
||||
</Fragment>
|
||||
))}
|
||||
<div className='resource-unit-container'>
|
||||
{this.resources.map((o, i) => {
|
||||
let amount = o.key === 'money' ? Math.floor(player.cash / 1000) : player.assets[o.key];
|
||||
if (o.key === 'cows') { amount = player.assets.cows - playerRidgeCows(player); }
|
||||
return (
|
||||
<ResourceUnit img={o.img ? o.img : false} h={o.h} s={o.s} label={o.label}
|
||||
key={i}
|
||||
className={o.key === 'money' ? 'double-width' : false}
|
||||
amount={amount + Math.min(0, toTrade[o.key])}
|
||||
>
|
||||
{o.icon ? (
|
||||
<>
|
||||
<FontAwesomeIcon icon={o.icon} />(K)
|
||||
<br />
|
||||
</>
|
||||
) : ''}
|
||||
{amount + Math.min(0, toTrade[o.key])}
|
||||
{o.icon ? (<br />) : ''}
|
||||
{!tradeProposed && ((amount + Math.min(0, toTrade[o.key])) > 0 || toTrade[o.key] > 0) ? (
|
||||
<>
|
||||
<Button className="tiny"
|
||||
onClick={() => this.tradeAsset(o.key, o.amount * -1)}>
|
||||
<FontAwesomeIcon icon={faArrowDown} />
|
||||
</Button>
|
||||
{o.key === 'money' && (amount + Math.min(0, toTrade[o.key])) >= 10 ? (
|
||||
<Button className="tiny"
|
||||
onClick={() => this.tradeAsset(o.key, o.amount * -10)}>
|
||||
<FontAwesomeIcon icon={faArrowDown} />
|
||||
<FontAwesomeIcon icon={faArrowDown} />
|
||||
</Button>
|
||||
) : ''}
|
||||
</>
|
||||
) : (<></>)}
|
||||
</ResourceUnit>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
{this.state.showCards ? (
|
||||
<TradeCards player={this.state.showCardsPlayer}
|
||||
me={player}
|
||||
tradeCard={this.tradeCard}
|
||||
goBack={this.viewPlayerCards}
|
||||
cardsBeingTraded={this.state.sendCards.map(c => c.id).concat(this.state.receiveCards.map(c => c.id))}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<Row>
|
||||
<Col width="12">
|
||||
<div className="trade-player-container">
|
||||
<h4>
|
||||
{player.name}
|
||||
{player.cards.length > 0 ? (
|
||||
<>
|
||||
{' - '}
|
||||
<a onClick={e => this.viewPlayerCards(e, player)}>
|
||||
<FontAwesomeIcon icon={faWindowRestore} /> Trade Cards
|
||||
</a>
|
||||
</>
|
||||
) : (<></>)}
|
||||
</h4>
|
||||
{Object.keys(player.ridges).map((ridge, idx) => (
|
||||
<Fragment key={'player-trade' + ridge}>
|
||||
{!tradeProposed && (player.ridges[ridge] > 0) && !toTrade[ridge] ? (
|
||||
<Button className="tiny"
|
||||
onClick={() => this.tradeAsset(ridge, player.ridges[ridge], true)}>
|
||||
<FontAwesomeIcon icon={faArrowDown} /> {ridgeNames[idx]} {'('}{player.ridges[ridge]} cows{')'}
|
||||
</Button>
|
||||
) : (<></>)}
|
||||
{' '}
|
||||
</Fragment>
|
||||
))}
|
||||
<div className='resource-unit-container'>
|
||||
{this.resources.map((o, i) => {
|
||||
let amount = o.key === 'money' ? Math.floor(player.cash / 1000) : player.assets[o.key];
|
||||
if (o.key === 'cows') { amount = player.assets.cows - playerRidgeCows(player); }
|
||||
return (
|
||||
<ResourceUnit img={o.img ? o.img : false} h={o.h} s={o.s} label={o.label}
|
||||
key={i}
|
||||
className={o.key === 'money' ? 'double-width' : false}
|
||||
amount={amount + Math.min(0, toTrade[o.key])}
|
||||
>
|
||||
{o.icon ? (
|
||||
<>
|
||||
<FontAwesomeIcon icon={o.icon} />(K)
|
||||
<br />
|
||||
</>
|
||||
) : ''}
|
||||
{amount + Math.min(0, toTrade[o.key])}
|
||||
{o.icon ? (<br />) : ''}
|
||||
{!tradeProposed && ((amount + Math.min(0, toTrade[o.key])) > 0 || toTrade[o.key] > 0) ? (
|
||||
<>
|
||||
<Button className="tiny"
|
||||
onClick={() => this.tradeAsset(o.key, o.amount * -1)}>
|
||||
<FontAwesomeIcon icon={faArrowDown} />
|
||||
</Button>
|
||||
{o.key === 'money' && (amount + Math.min(0, toTrade[o.key])) >= 10 ? (
|
||||
<Button className="tiny"
|
||||
onClick={() => this.tradeAsset(o.key, o.amount * -10)}>
|
||||
<FontAwesomeIcon icon={faArrowDown} />
|
||||
<FontAwesomeIcon icon={faArrowDown} />
|
||||
</Button>
|
||||
) : ''}
|
||||
</>
|
||||
) : (<></>)}
|
||||
</ResourceUnit>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
@@ -739,6 +703,13 @@ class TradeContainer2 extends React.Component {
|
||||
{' '}
|
||||
</Fragment>
|
||||
))}
|
||||
{this.state.receiveCards.map((card, idx) => (
|
||||
<Button className="tiny"
|
||||
key={idx}
|
||||
onClick={() => this.unTradeCard(card.id)}>
|
||||
{card.summary}
|
||||
</Button>
|
||||
))}
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
@@ -769,6 +740,13 @@ class TradeContainer2 extends React.Component {
|
||||
{' '}
|
||||
</Fragment>
|
||||
))}
|
||||
{this.state.sendCards.map((card, idx) => (
|
||||
<Button className="tiny"
|
||||
key={idx}
|
||||
onClick={() => this.unTradeCard(card.id)}>
|
||||
{card.summary}
|
||||
</Button>
|
||||
))}
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
@@ -825,24 +803,21 @@ class TradeContainer2 extends React.Component {
|
||||
</Fragment>
|
||||
))}
|
||||
<select onChange={this.selectPlayer}
|
||||
value={otherPlayer.name}
|
||||
defaultValue={otherPlayer.name}>
|
||||
value={otherPlayer.name}>
|
||||
{this.props.game.otherPlayers.map(p => (
|
||||
<option key={p.player.name} value={p.player.name}>
|
||||
{p.player.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{otherPlayer && otherPlayer.revealedCards.length > 0 ? (
|
||||
<a onClick={e => this.viewPlayerCards(e, otherPlayer)}>
|
||||
<FontAwesomeIcon icon={faWindowRestore} /> Trade Cards
|
||||
</a>
|
||||
) : (<></>)}
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col width="12">
|
||||
<input type="text" placeholder="Cards"
|
||||
defaultValue={toTrade.cards}
|
||||
onChange={e => this.tradeAsset('cards', e.target.value)} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col width="12">
|
||||
{player.trade.error ? (
|
||||
@@ -862,6 +837,7 @@ class TradeContainer2 extends React.Component {
|
||||
) : (<></>)}
|
||||
</Col>
|
||||
</Row>
|
||||
</>)}
|
||||
</GroupBox>
|
||||
);
|
||||
}
|
||||
@@ -1988,7 +1964,7 @@ const SCREENS = { summary: 'summary', misc: 'misc', farms: 'farms',
|
||||
class BoardApp extends React.Component {
|
||||
iconToScreen = { user: SCREENS.summary, 'window-restore': SCREENS.cards,
|
||||
'dollar-sign': SCREENS.loans, users: SCREENS.farms,
|
||||
'exchange-alt': SCREENS.trade, asterisk: SCREENS.misc,
|
||||
'exchange-alt': SCREENS.trade,
|
||||
tractor: SCREENS.action, 'info-circle': SCREENS.info }
|
||||
unsubscribeAlert = () => null
|
||||
|
||||
@@ -2293,6 +2269,7 @@ class BoardApp extends React.Component {
|
||||
setCardError={this.props.setCardError}
|
||||
playerCash={this.props.player.displayCash}
|
||||
playerDebt={this.props.player.debt}
|
||||
revealedCards={this.props.player.revealedCards}
|
||||
card={this.state.card}
|
||||
cost={this.state.card.total / 1000}
|
||||
min={(this.state.card.total * this.props.game.settings.downPayment) / 1000}
|
||||
@@ -2310,7 +2287,7 @@ class BoardApp extends React.Component {
|
||||
otherPlayers={this.props.game.otherPlayers} />
|
||||
</div>
|
||||
<div className={this.tabClass(SCREENS.trade) + ' trade-tab'}>
|
||||
<TradeContainer2 player={this.props.player} game={this.props.game} />
|
||||
<TradeContainer player={this.props.player} game={this.props.game} />
|
||||
</div>
|
||||
<div className={this.tabClass(SCREENS.misc)}>
|
||||
<Misc />
|
||||
@@ -2419,7 +2396,11 @@ class Card extends React.Component {
|
||||
) : (<></>)}
|
||||
<Row collapse='true'>
|
||||
<Col width="12">
|
||||
<label className="small-text"><input type="checkbox" /> Reveal for trading</label>
|
||||
<label className="small-text">
|
||||
<input type="checkbox"
|
||||
onChange={() => toggleRevealForTrade(card.id)}
|
||||
checked={this.props.revealedCards.includes(card.id)} /> Reveal for trading
|
||||
</label>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
@@ -2451,7 +2432,7 @@ class CardListComp extends React.Component {
|
||||
case 'fruit': return '5 acres Fruit';
|
||||
case 'grain': return '10 acres Grain'}};
|
||||
const ui = this.props.ui,
|
||||
cards = ui.cards,
|
||||
cards = ui.cards.filter(this.props.visibleCards ? (c) => this.props.visibleCards.includes(c.id) : (c) => c),
|
||||
cardOps = cards.map((c, i) =>
|
||||
(<li key={i} className={c.id == this.props.cardId ? 'card-select-selected' : ''}
|
||||
onClick={() => { this.props.setCard(c); this.props.setCardError(false); }}>
|
||||
@@ -2459,7 +2440,7 @@ class CardListComp extends React.Component {
|
||||
</li>));
|
||||
|
||||
return (
|
||||
<GroupBox title='Cards'>
|
||||
<GroupBox title={this.props.title ? this.props.title : 'Cards'}>
|
||||
<ul className='card-select'>
|
||||
{cardOps}
|
||||
</ul>
|
||||
|
||||
@@ -31,7 +31,7 @@ import { itemCard, fateCard } from 'game.js'
|
||||
export { initialize, buy, roll, endTurn, loan, trade, submitTradeAccept,
|
||||
submitTradeDeny, submitTradeCancel, audit, handleMessage,
|
||||
nextAction, buyUncleBert, actionsFinished, skip, endAiTurn,
|
||||
startGame, readyToStart, leaveGame, kickPlayer }
|
||||
startGame, readyToStart, leaveGame, kickPlayer, toggleRevealForTrade }
|
||||
|
||||
let store;
|
||||
let movingTimer = 0;
|
||||
@@ -217,6 +217,10 @@ function kickPlayer(name) {
|
||||
sendCommand({ type: 'kick-player', name });
|
||||
}
|
||||
|
||||
function toggleRevealForTrade(id) {
|
||||
sendCommand({ type: 'toggle-reveal-for-trading', id });
|
||||
}
|
||||
|
||||
// TODO share with Board.jsx
|
||||
// http://stackoverflow.com/questions/149055
|
||||
function formatMoney(n) {
|
||||
|
||||
@@ -91,6 +91,8 @@ const initialState = {
|
||||
assets: { hay: 10, grain: 10, fruit: 0, cows: 0, harvester: 0, tractor: 0, birthday: 0 },
|
||||
color: '',
|
||||
name: '',
|
||||
cards: [],
|
||||
revealedCards: [],
|
||||
ridges: { ridge1: 0, ridge2: 0, ridge3: 0, ridge4: 0 },
|
||||
space: 0,
|
||||
hayDoubled: false,
|
||||
|
||||
@@ -86,7 +86,7 @@ class JoinGame extends React.Component {
|
||||
return (
|
||||
<GroupBox title={(
|
||||
<Fragment>
|
||||
<a href="#" onClick={this.handleBack}>
|
||||
<a onClick={this.handleBack}>
|
||||
<FontAwesomeIcon icon={faArrowCircleLeft} />
|
||||
</a>
|
||||
Join Game
|
||||
|
||||
@@ -115,6 +115,7 @@
|
||||
(harvest-mult initform: 1 accessor: player-harvest-mult)
|
||||
(otbs initform: '() accessor: player-otbs)
|
||||
(farmers-fates initform: '() accessor: player-farmers-fates)
|
||||
(revealed-cards initform: '() accessor: player-revealed-cards)
|
||||
(year-rules initform: '() accessor: player-year-rules)
|
||||
(next-year-rules initform: '() accessor: player-next-year-rules)
|
||||
(color initform: #f accessor: player-color)
|
||||
@@ -182,7 +183,8 @@
|
||||
(harvest-mult . ,(player-harvest-mult player))
|
||||
(otbs . ,(player-otbs player))
|
||||
(farmers-fates . ,(map (cut alist-ref 'id <>) (player-farmers-fates player)))
|
||||
(year-rules . ,(player-year-rules player)) ;; TODO check if all are serializable
|
||||
(revealed-cards . ,(player-revealed-cards player))
|
||||
(year-rules . ,(player-year-rules player))
|
||||
(next-year-rules . ,(player-next-year-rules player))
|
||||
(color . ,(player-color player))
|
||||
(name . ,(player-name player))
|
||||
@@ -306,18 +308,21 @@
|
||||
(set! *app* (sexp->app (read))))))
|
||||
|
||||
(define (sexp->player x)
|
||||
(apply make <player>
|
||||
'farmers-fates (let ((ffs (alist-ref 'farmers-fates x)))
|
||||
(list-copy
|
||||
(filter (lambda (card)
|
||||
(member (alist-ref 'id card) ffs))
|
||||
*farmers-fates-cards*)))
|
||||
(fold (lambda (k r) (cons k (cons (alist-ref k x) r)))
|
||||
'()
|
||||
'(cash debt space previous-space state assets ridges
|
||||
harvest-mult otbs user-id
|
||||
year-rules next-year-rules hay-doubled corn-doubled
|
||||
color name trade last-updated last-cash))))
|
||||
(let ((p (apply make <player>
|
||||
'farmers-fates (let ((ffs (alist-ref 'farmers-fates x)))
|
||||
(list-copy
|
||||
(filter (lambda (card)
|
||||
(member (alist-ref 'id card) ffs))
|
||||
*farmers-fates-cards*)))
|
||||
(fold (lambda (k r) (cons k (cons (alist-ref k x) r)))
|
||||
'()
|
||||
'(cash debt space previous-space state assets ridges
|
||||
harvest-mult otbs user-id revealed-cards
|
||||
year-rules next-year-rules hay-doubled corn-doubled
|
||||
color name trade last-updated last-cash)))))
|
||||
(when (not (player-revealed-cards p))
|
||||
(safe-set! (player-revealed-cards p) '()))
|
||||
p))
|
||||
|
||||
(define (shuffle l)
|
||||
(map cdr
|
||||
@@ -521,6 +526,7 @@
|
||||
(state . ,(symbol->string (player-state p)))
|
||||
(cards . ,(list->vector (append (player-farmers-fates p)
|
||||
(player-otbs p))))
|
||||
(revealedCards . ,(list->vector (player-revealed-cards p)))
|
||||
(color . ,(symbol->string (player-color p)))
|
||||
(name . ,(player-name p))
|
||||
(user-id . ,(player-user-id p))
|
||||
@@ -1334,6 +1340,16 @@
|
||||
(message-players! game player '() type: "update"))
|
||||
(create-ws-response player "update" '()))
|
||||
(begin (create-ws-response player "update" '()))))
|
||||
((string=? type "toggle-reveal-for-trading")
|
||||
(let ((id (alist-ref 'id msg)))
|
||||
(if (member id (player-revealed-cards player))
|
||||
(safe-set! (player-revealed-cards player)
|
||||
(filter (lambda (cid) (not (eqv? cid id)))
|
||||
(player-revealed-cards player)))
|
||||
(safe-set! (player-revealed-cards player)
|
||||
(cons id (player-revealed-cards player)))))
|
||||
(message-players! game player '() type: "update")
|
||||
(create-ws-response player "update" '()))
|
||||
;;;;;;;;;;;;;;;;;;;;; start ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
((string=? type "main-init")
|
||||
(create-start-response "start-init"))
|
||||
@@ -2384,3 +2400,4 @@
|
||||
;; TODO
|
||||
;; make sure two players can't have the same name
|
||||
;; "your turn to roll" showing up on mobile when on action screen
|
||||
;; trade cards better
|
||||
|
||||
Reference in New Issue
Block a user