From 54701cc9c08d684a25a1f5157a4c036ac5bc9fd6 Mon Sep 17 00:00:00 2001 From: Chris Karle Date: Mon, 20 Apr 2020 01:46:42 -0400 Subject: [PATCH] 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. --- assets/app.scss | 39 +++++++++++++++++++++++++++++++++++++++ assets/components/CardTable.js | 316 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------- assets/components/TrumpPicker.js | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 409 insertions(+), 46 deletions(-) create mode 100644 assets/components/TrumpPicker.js diff --git a/assets/app.scss b/assets/app.scss index f4cba11..a1a7dac 100644 --- 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 index 063639e..2199273 100644 --- 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 ( +
+ + + +
+ {leftCard && ( +
+ +
+ )} +
+
+ +
+ {partnerCard && ( +
+ +
+ )} + {myCard && ( +
+ +
+ )} +
+
+ +
+ {rightCard && ( +
+ +
+ )} +
+
+
+
+
+ ); + 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 (
@@ -175,13 +385,13 @@ export default class CardTable extends React.Component { {!showSeatPicker && (
-
{partner.name}
+
{partnerName}
-
{partner.handInfo}
-
{partner.turnInfo}
+
{partnerHandInfo}
+
{partnerTurnInfo}
+ numCards={handLengths[partnerSeat]} />
)}
@@ -191,11 +401,11 @@ export default class CardTable extends React.Component { {!showSeatPicker && (
-
{left.name}
-
{left.handInfo}
-
{left.turnInfo}
+
{leftName}
+
{leftHandInfo}
+
{leftTurnInfo}
+ numCards={handLengths[leftSeat]} />
)}
@@ -214,24 +424,40 @@ export default class CardTable extends React.Component {
)} + { (phase=='play') && ( +
{trickDisplay}
+ )} {!showSeatPicker && (
-
{right.name}
-
{right.handInfo}
-
{right.turnInfo}
+
{rightName}
+
{rightHandInfo}
+
{rightTurnInfo}
+ numCards={handLengths[rightSeat]} />
)}
- {!showSeatPicker && ( + {showInfo && (
You: {myHandInfo}
{myTurnInfo}
+
{trumpMsg}
+
+ )} + {showTrumpPicker && ( + + )} + {showSwap && ( +
+
Click a card to discard:
)}
@@ -243,8 +469,6 @@ export default class CardTable extends React.Component { /> )} - {/* - */}
diff --git a/assets/components/TrumpPicker.js b/assets/components/TrumpPicker.js new file mode 100644 index 0000000..f42e551 --- /dev/null +++ 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() +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 ( +
+
+ + {phaseTwo && ( + this.suitChange(event)} + /> + )} + + +
+
+ ); + } +} +TrumpPicker.propTypes = { + trumpCard: PropTypes.string, + phaseTwo: PropTypes.bool, + myDeal: PropTypes.bool, + handleVote: PropTypes.func, +} +export default TrumpPicker; -- libgit2 1.1.1