commit 54701cc9c08d684a25a1f5157a4c036ac5bc9fd6 (patch)
parent e7aa87e3756fbf4b44aa572dbd8d00fc6c8a50ac
Author: Chris Karle <chriskarle@hotmail.com>
Date: Mon, 20 Apr 2020 01:46:42 -0400
TrumpPicker, CardTable
Creates TrumpPicker to give buttons for pass/pick and drop
menu for vote-2.
Completes basic play of tricks and new trump.
Need: score display, pause on final card (server update),
bug fixes.
Diffstat:
3 files changed, 409 insertions(+), 46 deletions(-)
diff --git a/assets/app.scss b/assets/app.scss
@@ -74,13 +74,19 @@
align-items: center;
}
.partner__info {
+ width: 100%;
display: flex;
justify-content: space-evenly;
}
.my__stack {
float: right;
+}
+.my__hinfo {
font-size: 1.5rem;
}
+.my__tinfo {
+ font-size: 1.3rem;
+}
.mh__card {
width: 100px;
}
@@ -124,6 +130,32 @@
// .tb__center {
// background-color: rgb(217, 249, 255);
// }
+.trick__card {
+ width: 80px;
+}
+.trick__holder, .trick__outer, .trick__grid, .trick__row {
+ height: 100%;
+}
+.left__trick, .right__trick {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+}
+.mid__trick {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+.me {
+ justify-content: flex-end;
+}
+.partner {
+ justify-content: flex-start;
+}
+.both {
+ justify-content: space-between;
+}
.trump__card {
width: 80px;
@@ -153,6 +185,13 @@
flex-direction: row;
justify-content: flex-end;
}
+.tp1__stack {
+ display: flex;
+ flex-direction: column;
+ .bx--btn, .bx--dropdown__wrapper{
+ margin-bottom: 3px;
+ }
+}
.table__header {
height: 10vh;
diff --git a/assets/components/CardTable.js b/assets/components/CardTable.js
@@ -6,8 +6,15 @@ import {Logout32} from '@carbon/icons-react';
import SeatPicker from './SeatPicker';
import MainHand from './MainHand';
import HiddenHand from './HiddenHand';
+import TrumpPicker from './TrumpPicker';
const trumpPlacement = ['me', 'left', 'partner', 'right'];
+const suit = {
+ H: 'Hearts',
+ D: 'Diamonds',
+ S: 'Spades',
+ C: 'Clubs'
+}
export default class CardTable extends React.Component {
@@ -20,11 +27,25 @@ export default class CardTable extends React.Component {
myHandInfo: 'mhi',
myTurnInfo: 'mti',
phase: 'lobby',
- left: { name: '', seat: -1, handInfo: '', turnInfo: ' ' },
- partner: { name: '', seat: -1, handInfo: '', turnInfo: ' ' },
- right: { name: '', seat: -1, handInfo: '', turnInfo: '' },
+ leftName: '',
+ leftSeat: -1,
+ leftHandInfo: '',
+ leftTurnInfo: '',
+ partnerName: '',
+ partnerSeat: -1,
+ partnerHandInfo: '',
+ partnerTurnInfo: '',
+ rightName: '',
+ rightSeat: -1,
+ rightHandInfo: '',
+ rightTurnInfo: '',
+ trump: '',
trumpPlace: '',
- trumpNom: ''
+ trumpNom: '',
+ turnSeat: -1,
+ dealSeat: -1,
+ table: [],
+ handLengths: []
};
};
@@ -47,6 +68,12 @@ export default class CardTable extends React.Component {
case 'vote':
this.processVote(msg);
break;
+ case 'dealer_swap':
+ this.processSwap(msg);
+ break;
+ case 'play':
+ this.processPlay(msg);
+ break;
default:
break;
}
@@ -69,13 +96,116 @@ export default class CardTable extends React.Component {
processVote = (msg) => {
if (this.state.phase == 'lobby') {
this.gameStartSetup(msg);
+ } else if (this.state.phase == 'play') {
+ this.trumpStartSetup(msg);
}
+ const {leftSeat, rightSeat, partnerSeat, mySeat} = this.state;
+ const phaseString = msg.game.pass_count > 3 ? 'vote2' : 'vote';
+ let turnInfo = ['', '', '', ''];
+ turnInfo[msg.game.turn] = 'trump?';
this.setState({
- phase: 'vote',
- myCards: msg.hand
+ phase: phaseString,
+ myCards: msg.hand,
+ turnSeat: msg.game.turn,
+ leftTurnInfo: turnInfo[leftSeat],
+ rightTurnInfo: turnInfo[rightSeat],
+ partnerTurnInfo: turnInfo[partnerSeat],
+ myTurnInfo: turnInfo[mySeat]
});
};
+ processSwap = msg => {
+ const {leftSeat, rightSeat, partnerSeat, mySeat, dealSeat} = this.state;
+ let turnInfo = ['', '', '', ''];
+ turnInfo[dealSeat] = 'Swapping...';
+ this.setState({
+ phase: 'swap',
+ leftTurnInfo: turnInfo[leftSeat],
+ rightTurnInfo: turnInfo[rightSeat],
+ partnerTurnInfo: turnInfo[partnerSeat],
+ myTurnInfo: turnInfo[mySeat]
+ });
+ }
+
+ trickMsg = (num, action) => {
+ let retVal;
+ if (num == 0) {
+ retVal = action ? 'action' : '';
+ } else {
+ retVal = num == 1 ? '1 trick' : (num + ' tricks');
+ if (action) {
+ retVal = retVal + ', action';
+ }
+ }
+ return retVal;
+ }
+
+ processPlay = msg => {
+ const {leftSeat, rightSeat, partnerSeat, mySeat, dealSeat, phase} = this.state;
+ let turnInfo = [];
+ if (phase == 'vote' || phase == 'vote2' || phase == 'swap') {
+ this.handStartSetup(msg);
+ }
+ for (let i = 0; i < 4; i++) {
+ const tricks = msg.game.tricks[i];
+ let tInf = this.trickMsg(tricks, (msg.game.turn == i));
+ turnInfo.push(tInf);
+ }
+ this.setState({
+ phase: 'play',
+ myCards: msg.hand,
+ table: msg.game.table,
+ handLengths: msg.game.hand_lengths,
+ leftTurnInfo: turnInfo[leftSeat],
+ rightTurnInfo: turnInfo[rightSeat],
+ partnerTurnInfo: turnInfo[partnerSeat],
+ myTurnInfo: turnInfo[mySeat]
+ });
+
+ }
+
+ handStartSetup = msg => {
+ const {leftSeat, rightSeat, partnerSeat, mySeat, dealSeat} = this.state;
+ let handInfo = ['', '', '', ''];
+ const caller = msg.game.out_player > -1 ? 'Alone' : 'Caller';
+ const callSeat = msg.game.caller;
+ if (callSeat == dealSeat) {
+ handInfo[dealSeat] = 'Dealer, ' + caller;
+ } else {
+ handInfo[dealSeat] = 'Dealer';
+ handInfo[callSeat] = caller;
+ }
+ this.setState({
+ trump: msg.game.trump,
+ leftHandInfo: handInfo[leftSeat],
+ rightHandInfo: handInfo[rightSeat],
+ partnerHandInfo: handInfo[partnerSeat],
+ myHandInfo: handInfo[mySeat]
+ });
+
+ }
+
+ trumpStartSetup = (msg) => {
+ const {leftSeat, rightSeat, partnerSeat, mySeat, dealSeat} = this.state;
+ let handInfo = ['', '', '', ''];
+ const newDeal = msg.game.dealer;
+ handInfo[newDeal] = 'Dealer';
+ let tpIndex = msg.game.dealer - mySeat;
+ tpIndex = (tpIndex < 0) ? tpIndex + 4 : tpIndex;
+ const trumpPlace = trumpPlacement[tpIndex];
+ this.setState({
+ trump: '',
+ trumpPlace: trumpPlace,
+ dealSeat: newDeal,
+ trumpNom: msg.game.trump_nominee,
+ leftHandInfo: handInfo[leftSeat],
+ rightHandInfo: handInfo[rightSeat],
+ partnerHandInfo: handInfo[partnerSeat],
+ myHandInfo: handInfo[mySeat]
+ });
+
+ }
+
gameStartSetup = (msg) => {
const { playerNames, mySeat } = this.state;
let handInfo = [' ', ' ', ' ', ' '];
@@ -90,28 +220,23 @@ export default class CardTable extends React.Component {
const trumpPlace = trumpPlacement[tpIndex];
console.log('trumpPlace:', trumpPlace);
this.setState ({
- left : {
- name: playerNames[leftSeat],
- seat: leftSeat,
- handInfo: handInfo[leftSeat],
- turnInfo: turnInfo[leftSeat]
- },
- partner : {
- name: playerNames[partnerSeat],
- seat: partnerSeat,
- handInfo: handInfo[partnerSeat],
- turnInfo: turnInfo[partnerSeat]
- },
- right : {
- name: playerNames[rightSeat],
- seat: rightSeat,
- handInfo: handInfo[rightSeat],
- turnInfo: turnInfo[rightSeat]
- },
+ leftName: playerNames[leftSeat],
+ leftSeat: leftSeat,
+ leftHandInfo: handInfo[leftSeat],
+ leftTurnInfo: turnInfo[leftSeat],
+ partnerName: playerNames[partnerSeat],
+ partnerSeat: partnerSeat,
+ partnerHandInfo: handInfo[partnerSeat],
+ partnerTurnInfo: turnInfo[partnerSeat],
+ rightName: playerNames[rightSeat],
+ rightSeat: rightSeat,
+ rightHandInfo: handInfo[rightSeat],
+ rightTurnInfo: turnInfo[rightSeat],
myHandInfo : handInfo[mySeat],
myTurnInfo : turnInfo[mySeat],
trumpPlace : trumpPlace,
- trumpNom: msg.game.trump_nominee
+ trumpNom: msg.game.trump_nominee,
+ dealSeat: msg.game.dealer
});
};
@@ -133,23 +258,108 @@ export default class CardTable extends React.Component {
sendStart = (startDealer) => {
this.props.client.send(JSON.stringify({
action: 'start_game', start_seat: startDealer
- }))
+ }));
console.log('start game, dealer = ', startDealer);
};
+ sendVote = (voteObject) => {
+ const voteString = JSON.stringify(voteObject);
+ console.log('sendVote:', voteString);
+ this.props.client.send(voteString);
+ };
+
sendCard = (index) => {
- console.log('card click ', index);
+ const {phase, myCards} = this.state;
+ console.log('card click ', myCards[index]);
+ if (phase == 'swap') {
+ this.props.client.send(JSON.stringify({
+ action:'dealer_swap', card: myCards[index]
+ }));
+ } else if (phase == 'play') {
+ this.props.client.send(JSON.stringify({
+ action:'play_card', card: myCards[index]
+ }));
+ }
+ };
+
+ genTrick = () => {
+ let retVal = [];
+ const { table, mySeat, leftSeat, rightSeat, partnerSeat } = this.state;
+ const myCard = table[mySeat];
+ const leftCard = table[leftSeat];
+ const partnerCard = table[partnerSeat];
+ const rightCard = table[rightSeat];
+ const mySrc = 'cards/' + myCard + '.svg';
+ const leftSrc = 'cards/' + leftCard + '.svg';
+ const partnerSrc = 'cards/' + partnerCard + '.svg';
+ const rightSrc = 'cards/' + rightCard + '.svg';
+ let midClass = 'mid__trick';
+ if (myCard && partnerCard) {
+ midClass += ' both';
+ } else if (myCard) {
+ midClass += ' me';
+ } else if (partnerCard) {
+ midClass += ' partner';
+ }
+ retVal.push (
+ <div className="trick__outer">
+ <Grid className="trick__grid">
+ <Row className="trick__row">
+ <Column>
+ <div className="left__trick">
+ {leftCard && (
+ <div className="trick__div">
+ <img className="trick__card" src={leftSrc} />
+ </div>
+ )}
+ </div>
+ </Column>
+ <Column>
+ <div className={midClass}>
+ {partnerCard && (
+ <div className="trick__div">
+ <img className="trick__card" src={partnerSrc} />
+ </div>
+ )}
+ {myCard && (
+ <div className="trick__div">
+ <img className="trick__card" src={mySrc} />
+ </div>
+ )}
+ </div>
+ </Column>
+ <Column>
+ <div className="right__trick">
+ {rightCard && (
+ <div className="trick__div">
+ <img className="trick__card" src={rightSrc} />
+ </div>
+ )}
+ </div>
+ </Column>
+ </Row>
+ </Grid>
+ </div>
+ );
+ return retVal;
}
render () {
- const { playerNames, mySeat, phase, left, partner, right, myCards,
- myHandInfo, myTurnInfo, trumpPlace, trumpNom } = this.state;
+ const { playerNames, mySeat, phase, myCards, myHandInfo, myTurnInfo,
+ partnerName, partnerHandInfo, partnerTurnInfo, partnerSeat, leftName, leftTurnInfo, leftHandInfo, leftSeat,
+ rightName, rightHandInfo, rightTurnInfo, rightSeat, trumpPlace, trumpNom, turnSeat,
+ dealSeat, trump, handLengths } = this.state;
const {name, tableName} = this.props;
const showSeatPicker = phase == 'lobby';
- const showTrump = phase == 'vote';
+ const showTrump = (phase == 'vote') || (phase == 'vote2') || (phase == 'swap');
+ const showTrumpPicker = showTrump && (turnSeat == mySeat);
+ const showSwap = (phase == 'swap') && (dealSeat == mySeat);
+ const showInfo = !showSeatPicker && !showTrumpPicker && !showSwap;
const welcomeMsg = 'Welcome to the ' + tableName + ' table, ' + name + '!';
const tcp = "trump__holder " + trumpPlace;
- const trumpImage = 'cards/' + trumpNom + '.svg';
+ const trumpImage = phase == 'vote' ? 'cards/' + trumpNom + '.svg' : 'cards/1B.svg';
+ const trumpMsg = phase == 'play' ? suit[trump] + ' are trump' : '';
+ const trickDisplay = phase == 'play' ? this.genTrick() : [];
return (
<div id="table">
<Grid>
@@ -175,13 +385,13 @@ export default class CardTable extends React.Component {
<Column className="tt__center" sm={2}>
{!showSeatPicker && (
<div className="partner__stack">
- <div className="player__name">{partner.name}</div>
+ <div className="player__name">{partnerName}</div>
<div className="partner__info">
- <div className="play__hinfo">{partner.handInfo}</div>
- <div className="play__tinfo">{partner.turnInfo}</div>
+ <div className="play__hinfo">{partnerHandInfo}</div>
+ <div className="play__tinfo">{partnerTurnInfo}</div>
</div>
<HiddenHand
- numCards={5} />
+ numCards={handLengths[partnerSeat]} />
</div>)}
</Column>
<Column className="tt__right" sm={1}>
@@ -191,11 +401,11 @@ export default class CardTable extends React.Component {
<Column className="tm__left" sm={1}>
{!showSeatPicker && (
<div className="vert__stack">
- <div className="player__name">{left.name}</div>
- <div className="play__hinfo">{left.handInfo}</div>
- <div className="play__tinfo">{left.turnInfo}</div>
+ <div className="player__name">{leftName}</div>
+ <div className="play__hinfo">{leftHandInfo}</div>
+ <div className="play__tinfo">{leftTurnInfo}</div>
<HiddenHand
- numCards={5} />
+ numCards={handLengths[leftSeat]} />
</div>)}
</Column>
<Column className="tm__center" sm={2}>
@@ -214,24 +424,40 @@ export default class CardTable extends React.Component {
</div>
</div>
)}
+ { (phase=='play') && (
+ <div className="trick__holder">{trickDisplay}</div>
+ )}
</Column>
<Column className="tm__right" sm={1}>
{!showSeatPicker && (
<div className="vert__stack">
- <div className="player__name">{right.name}</div>
- <div className="play__hinfo">{right.handInfo}</div>
- <div className="play__tinfo">{right.turnInfo}</div>
+ <div className="player__name">{rightName}</div>
+ <div className="play__hinfo">{rightHandInfo}</div>
+ <div className="play__tinfo">{rightTurnInfo}</div>
<HiddenHand
- numCards={5} />
+ numCards={handLengths[rightSeat]} />
</div>)}
</Column>
</Row>
<Row className="table__bot">
<Column className="tb__left" sm={1}>
- {!showSeatPicker && (
+ {showInfo && (
<div className="my__stack">
<div className="my__hinfo">You: {myHandInfo}</div>
<div className="my__tinfo">{myTurnInfo}</div>
+ <div className="my__tinfo">{trumpMsg}</div>
+ </div>
+ )}
+ {showTrumpPicker && (
+ <TrumpPicker
+ trumpCard={trumpNom}
+ phaseTwo={phase == 'vote2'}
+ myDeal={dealSeat == mySeat}
+ handleVote={this.sendVote} />
+ )}
+ {showSwap && (
+ <div className="my__stack">
+ <div className="my_tinfo">Click a card to discard:</div>
</div>
)}
</Column>
@@ -243,8 +469,6 @@ export default class CardTable extends React.Component {
/>
)}
</Column>
- {/* <Column className="tb__right" sm={1}>
- </Column> */}
</Row>
</Grid>
diff --git a/assets/components/TrumpPicker.js b/assets/components/TrumpPicker.js
@@ -0,0 +1,100 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import {Button, Dropdown} from 'carbon-components-react';
+
+const remain = { //HDSC order by Game.pm
+ H: ['Diamonds', 'Spades', 'Clubs'],
+ D: ['Hearts', 'Spades', 'Clubs'],
+ S: ['Hearts', 'Diamonds', 'Clubs'],
+ C: ['Hearts', 'Diamonds', 'Spades']
+}
+//NB usage w subs: voteOptions.order(<suit>)
+const voteOptions = {
+ pass: {action: 'order', vote: 'pass'},
+ order: suit => ({action: 'order', vote: suit, loner: 0}),
+ alone: suit => ({action: 'order', vote: suit, loner: 1})
+}
+
+class TrumpPicker extends React.Component {
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ suitPick: 'U'
+ }
+ };
+
+ componentDidUpdate (prevProps) {
+ const { trumpCard, phaseTwo } = this.props;
+ if ((trumpCard != prevProps.trumpCard) || (phaseTwo != prevProps.phaseTwo)){
+ this.setState ({
+ suitPick: 'U'
+ })
+ }
+ }
+
+ suitChange = event => {
+ const pick = event.selectedItem;
+ this.setState({
+ suitPick: pick.substring(0,1)
+ });
+ };
+
+
+ render () {
+ const { trumpCard, phaseTwo, myDeal, handleVote } = this.props;
+ const { suitPick } = this.state;
+ const trumpSuit = trumpCard ? trumpCard.substring(1) : 'U';
+ const orderLabel = myDeal ? 'Pick up' : 'Order';
+ const aloneLabel = myDeal ? 'Pick, Alone' : 'Order, Alone';
+ const pickerLabels = remain[trumpSuit];
+ const voteSuit = phaseTwo ? suitPick : trumpSuit;
+ const orderVote = voteOptions.order(voteSuit);
+ const aloneVote = voteOptions.alone(voteSuit);
+ const disableOrder = phaseTwo && suitPick == 'U';
+ return (
+ <div id="TrumpPicker" className="trump__picker">
+ <div className="tp1__stack">
+ <Button
+ className="p1p__button"
+ kind="primary"
+ size="small"
+ onClick={()=>{handleVote(voteOptions.pass)}}
+ >Pass</Button>
+ {phaseTwo && (
+ <Dropdown
+ id="trump__drop"
+ className="trump__drop"
+ label="Choose Suit..."
+ size="sm"
+ itemToElement={null}
+ items={pickerLabels}
+ onChange={(event)=>this.suitChange(event)}
+ />
+ )}
+ <Button
+ className="p1o__button"
+ kind="primary"
+ size="small"
+ disabled={disableOrder}
+ onClick={()=>{handleVote(orderVote)}}
+ >{orderLabel}</Button>
+ <Button
+ className="p1a__button"
+ kind="primary"
+ size="small"
+ disabled={disableOrder}
+ onClick={()=>{handleVote(aloneVote)}}
+ >{aloneLabel}</Button>
+ </div>
+ </div>
+ );
+ }
+}
+TrumpPicker.propTypes = {
+ trumpCard: PropTypes.string,
+ phaseTwo: PropTypes.bool,
+ myDeal: PropTypes.bool,
+ handleVote: PropTypes.func,
+}
+export default TrumpPicker;