changed style for leduc
|
@ -8,7 +8,6 @@
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
.stretch {
|
.stretch {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 8.2 KiB |
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 8.4 KiB |
After Width: | Height: | Size: 7.8 KiB |
|
@ -1,5 +1,13 @@
|
||||||
@import "cards.css";
|
@import "cards.css";
|
||||||
.leduc-holdem-wrapper {
|
.leduc-holdem-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #C3CDFF;
|
||||||
|
// background-image: url("./images/table.png");
|
||||||
|
// background-repeat: no-repeat;
|
||||||
|
// background-size: 100% 70%;
|
||||||
|
// background-position: bottom;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
.played-card-area {
|
.played-card-area {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
@ -8,17 +16,41 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
|
.timer.fade-in {
|
||||||
|
visibility: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timer.fade-out {
|
||||||
|
visibility: hidden;
|
||||||
|
transition: visibility 0.1s, opacity 0.05s;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timer {
|
||||||
|
visibility: visible;
|
||||||
|
transition: visibility 0s, opacity 0.2s, transform 0.3s;
|
||||||
|
opacity: 1;
|
||||||
|
width: 51px;
|
||||||
|
height: 60px;
|
||||||
|
.timer-text {
|
||||||
|
color: #303133;
|
||||||
|
margin-top: 3px;
|
||||||
|
font-size: 23px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-shadow: 0 2px 2px #909399;
|
||||||
|
line-height: 57px;
|
||||||
|
}
|
||||||
|
text-align: center;
|
||||||
|
background-image: url("./images/timer.png");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.non-card {
|
.non-card {
|
||||||
display: table;
|
display: table;
|
||||||
width: 280px;
|
width: 80px;
|
||||||
height: 100px;
|
height: 40px;
|
||||||
|
|
||||||
span {
|
|
||||||
display: table-cell;
|
|
||||||
vertical-align: middle;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,14 +69,11 @@
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
width: 130px;
|
width: 130px;
|
||||||
height: 130px;
|
height: 130px;
|
||||||
border-radius: 25px;
|
div {
|
||||||
border: 2px solid #73AD21;
|
text-align: center;
|
||||||
display: table;
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
display: table-cell;
|
|
||||||
vertical-align: middle;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,16 +125,17 @@
|
||||||
margin-top: -75px;
|
margin-top: -75px;
|
||||||
width: 130px;
|
width: 130px;
|
||||||
height: 150px;
|
height: 150px;
|
||||||
border-radius: 25px;
|
|
||||||
border: 2px solid blue;
|
|
||||||
display: table;
|
display: table;
|
||||||
|
|
||||||
.info-area {
|
.info-area {
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-shadow: 0 2px 2px rgba(0, 0, 0, 0.87);
|
||||||
|
color: #F2F6FC;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playingCards {
|
.playingCards {
|
||||||
transform: translate(3px, 10px);
|
transform: translate(3px, 10px);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,17 +2,65 @@ import React from 'react';
|
||||||
import { translateCardData, millisecond2Second } from '../../utils'
|
import { translateCardData, millisecond2Second } from '../../utils'
|
||||||
|
|
||||||
import '../../assets/leducholdem.scss';
|
import '../../assets/leducholdem.scss';
|
||||||
|
import Player1 from '../../assets/images/Portrait/Player1.png'
|
||||||
|
import Player2 from '../../assets/images/Portrait/Player2.png'
|
||||||
|
import PlaceHolderPlayer from '../../assets/images/Portrait/Player.png';
|
||||||
|
|
||||||
|
import Chip from '@material-ui/core/Chip';
|
||||||
|
import Avatar from '@material-ui/core/Avatar';
|
||||||
|
|
||||||
class LeducHoldemGameBoard extends React.Component {
|
class LeducHoldemGameBoard extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
computePlayerPortrait(playerId, playerIdx){
|
||||||
|
if(this.props.playerInfo.length > 0){
|
||||||
|
return this.props.playerInfo[playerIdx].id === 0 ?
|
||||||
|
<div>
|
||||||
|
<img src={Player1} alt={"Player 1"} height="70%" width="70%" />
|
||||||
|
<Chip
|
||||||
|
avatar={<Avatar>ID</Avatar>}
|
||||||
|
label={playerId}
|
||||||
|
clickable
|
||||||
|
color="primary"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
:
|
||||||
|
<div>
|
||||||
|
<img src={Player2} alt={"Player 2"} height="70%" width="70%" />
|
||||||
|
<Chip
|
||||||
|
avatar={<Avatar>ID</Avatar>}
|
||||||
|
label={playerId}
|
||||||
|
clickable
|
||||||
|
color="primary"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}else
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<img src={PlaceHolderPlayer} alt={"Player"} height="70%" width="70%" />
|
||||||
|
<Chip
|
||||||
|
avatar={<Avatar>ID</Avatar>}
|
||||||
|
label={playerId}
|
||||||
|
clickable
|
||||||
|
color="primary"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
computeActionImage(action) {
|
||||||
|
if (action.length > 0) {
|
||||||
|
return <img src={require('../../assets/images/Actions/' + action + '.png')} alt={action} height="80%" width="100%" />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
computeHand(card) {
|
computeHand(card) {
|
||||||
const [rankClass, suitClass, rankText, suitText] = translateCardData(card);
|
const [rankClass, suitClass, rankText, suitText] = translateCardData(card);
|
||||||
return (
|
return (
|
||||||
<div className="playingCards faceImages">
|
<div className="playingCards faceImages unselectable">
|
||||||
<div className={`card ${rankClass} ${suitClass}`}>
|
<div className={`card ${rankClass} full-content ${suitClass}`}>
|
||||||
<span className="rank">{rankText}</span>
|
<span className="rank">{rankText}</span>
|
||||||
<span className="suit">{suitText}</span>
|
<span className="suit">{suitText}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,9 +70,13 @@ class LeducHoldemGameBoard extends React.Component {
|
||||||
|
|
||||||
playerDecisionArea(playerIdx){
|
playerDecisionArea(playerIdx){
|
||||||
if(this.props.currentPlayer === playerIdx){
|
if(this.props.currentPlayer === playerIdx){
|
||||||
return <div className="non-card"><span>{`Consideration Time: ${millisecond2Second(this.props.considerationTime)}s`}</span></div>
|
return (
|
||||||
|
<div className={"timer"}>
|
||||||
|
<div className="timer-text">{millisecond2Second(this.props.considerationTime)}</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}else{
|
}else{
|
||||||
return <div className="non-card"><span>{this.props.latestAction[playerIdx]}</span></div>
|
return <div className="non-card">{this.computeActionImage(this.props.latestAction[playerIdx])}</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +91,7 @@ class LeducHoldemGameBoard extends React.Component {
|
||||||
const [rankClass, suitClass, rankText, suitText] = translateCardData(this.props.publicCard);
|
const [rankClass, suitClass, rankText, suitText] = translateCardData(this.props.publicCard);
|
||||||
return (
|
return (
|
||||||
<div className="playingCards faceImages">
|
<div className="playingCards faceImages">
|
||||||
<div className={`card ${rankClass} ${suitClass}`}>
|
<div className={`card ${rankClass} full-content ${suitClass}`}>
|
||||||
<span className="rank">{rankText}</span>
|
<span className="rank">{rankText}</span>
|
||||||
<span className="suit">{suitText}</span>
|
<span className="suit">{suitText}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -65,14 +117,15 @@ class LeducHoldemGameBoard extends React.Component {
|
||||||
topId = found.id;
|
topId = found.id;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="leduc-holdem-wrapper" style={{width: "100%", height: "100%", backgroundColor: "#ffcc99", position: "relative"}}>
|
<div className="leduc-holdem-wrapper">
|
||||||
<div id={"bottom-player"}>
|
<div id={"bottom-player"}>
|
||||||
<div className="played-card-area">
|
<div className="played-card-area">
|
||||||
{bottomIdx >= 0 ? this.playerDecisionArea(bottomIdx) : ""}
|
{bottomIdx >= 0 ? this.playerDecisionArea(bottomIdx) : ""}
|
||||||
</div>
|
</div>
|
||||||
<div className="player-main-area">
|
<div className="player-main-area">
|
||||||
<div className="player-info">
|
<div className="player-info">
|
||||||
<span>{`Player Id: ${bottomId}\nBet: ${this.props.pot[bottomIdx]}`}</span>
|
{this.computePlayerPortrait(bottomId, bottomIdx)}
|
||||||
|
<span>{`Bet: ${this.props.pot[bottomIdx]}`}</span>
|
||||||
</div>
|
</div>
|
||||||
{bottomIdx >= 0 ? <div className="player-hand">{this.computeHand(this.props.hands[bottomIdx])}</div> : <div className="player-hand-placeholder"><span>Waiting...</span></div>}
|
{bottomIdx >= 0 ? <div className="player-hand">{this.computeHand(this.props.hands[bottomIdx])}</div> : <div className="player-hand-placeholder"><span>Waiting...</span></div>}
|
||||||
</div>
|
</div>
|
||||||
|
@ -80,7 +133,8 @@ class LeducHoldemGameBoard extends React.Component {
|
||||||
<div id={"top-player"}>
|
<div id={"top-player"}>
|
||||||
<div className="player-main-area">
|
<div className="player-main-area">
|
||||||
<div className="player-info">
|
<div className="player-info">
|
||||||
<span>{`Player Id: ${topId}\nBet: ${this.props.pot[topIdx]}`}</span>
|
{this.computePlayerPortrait(topId, topIdx)}
|
||||||
|
<span>{`Bet: ${this.props.pot[topIdx]}`}</span>
|
||||||
</div>
|
</div>
|
||||||
{topIdx >= 0 ? <div className="player-hand">{this.computeHand(this.props.hands[topIdx])}</div> : <div className="player-hand-placeholder"><span>Waiting...</span></div>}
|
{topIdx >= 0 ? <div className="player-hand">{this.computeHand(this.props.hands[topIdx])}</div> : <div className="player-hand-placeholder"><span>Waiting...</span></div>}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,9 +2,10 @@ import React from 'react';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import '../assets/gameview.scss';
|
import '../assets/gameview.scss';
|
||||||
import {LeducHoldemGameBoard} from '../components/GameBoard';
|
import {LeducHoldemGameBoard} from '../components/GameBoard';
|
||||||
|
import Navbar from '../components/Navbar';
|
||||||
import {deepCopy} from "../utils";
|
import {deepCopy} from "../utils";
|
||||||
|
|
||||||
import { Layout } from 'element-react';
|
import { Layout, Message, Loading } from 'element-react';
|
||||||
import Slider from '@material-ui/core/Slider';
|
import Slider from '@material-ui/core/Slider';
|
||||||
import Button from '@material-ui/core/Button';
|
import Button from '@material-ui/core/Button';
|
||||||
import Paper from '@material-ui/core/Paper';
|
import Paper from '@material-ui/core/Paper';
|
||||||
|
@ -46,12 +47,12 @@ class LeducHoldemGameView extends React.Component {
|
||||||
this.state = {
|
this.state = {
|
||||||
gameInfo: this.initGameState,
|
gameInfo: this.initGameState,
|
||||||
gameStateLoop: null,
|
gameStateLoop: null,
|
||||||
gameSpeed: 0
|
gameSpeed: 0,
|
||||||
|
fullScreenLoading: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
generateNewState(){
|
generateNewState(){
|
||||||
// console.log(this.state.gameInfo.latestAction);
|
|
||||||
let gameInfo = deepCopy(this.state.gameInfo);
|
let gameInfo = deepCopy(this.state.gameInfo);
|
||||||
const turn = this.state.gameInfo.turn;
|
const turn = this.state.gameInfo.turn;
|
||||||
if(turn >= this.moveHistory[this.state.gameInfo.round].length){
|
if(turn >= this.moveHistory[this.state.gameInfo.round].length){
|
||||||
|
@ -85,7 +86,11 @@ class LeducHoldemGameView extends React.Component {
|
||||||
if(gameInfo.pot[(gameInfo.currentPlayer+2-1)%2] > gameInfo.pot[gameInfo.currentPlayer]){
|
if(gameInfo.pot[(gameInfo.currentPlayer+2-1)%2] > gameInfo.pot[gameInfo.currentPlayer]){
|
||||||
gameInfo.pot[gameInfo.currentPlayer] = gameInfo.pot[(gameInfo.currentPlayer+2-1)%2];
|
gameInfo.pot[gameInfo.currentPlayer] = gameInfo.pot[(gameInfo.currentPlayer+2-1)%2];
|
||||||
}else{
|
}else{
|
||||||
console.log("Current player choose call but has bet more or equal to the upstream player");
|
Message({
|
||||||
|
message: "Current player choose call but has bet more or equal to the upstream player",
|
||||||
|
type: "error",
|
||||||
|
showClose: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "Fold":
|
case "Fold":
|
||||||
|
@ -101,7 +106,11 @@ class LeducHoldemGameView extends React.Component {
|
||||||
}, 200);
|
}, 200);
|
||||||
return gameInfo;
|
return gameInfo;
|
||||||
default:
|
default:
|
||||||
console.log("Error in player's latest action");
|
Message({
|
||||||
|
message: "Error in player's latest action",
|
||||||
|
type: "error",
|
||||||
|
showClose: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
gameInfo.turn++;
|
gameInfo.turn++;
|
||||||
if(gameInfo.round !== 0 && gameInfo.turn === this.moveHistory[gameInfo.round].length){
|
if(gameInfo.round !== 0 && gameInfo.turn === this.moveHistory[gameInfo.round].length){
|
||||||
|
@ -119,14 +128,22 @@ class LeducHoldemGameView extends React.Component {
|
||||||
gameInfo.gameStatus = "playing";
|
gameInfo.gameStatus = "playing";
|
||||||
this.setState({ gameInfo: gameInfo });
|
this.setState({ gameInfo: gameInfo });
|
||||||
}else{
|
}else{
|
||||||
console.log("Mismatch in current player & move history");
|
Message({
|
||||||
|
message: "Mismatch in current player & move history",
|
||||||
|
type: "error",
|
||||||
|
showClose: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if current state is new to game state history, push it to the game state history array
|
// if current state is new to game state history, push it to the game state history array
|
||||||
if(gameInfo.turn === this.gameStateHistory[gameInfo.round].length){
|
if(gameInfo.turn === this.gameStateHistory[gameInfo.round].length){
|
||||||
this.gameStateHistory[gameInfo.round].push(gameInfo);
|
this.gameStateHistory[gameInfo.round].push(gameInfo);
|
||||||
}else{
|
}else{
|
||||||
console.log("inconsistent game state history length and turn number");
|
Message({
|
||||||
|
message: "Inconsistent game state history length and turn number",
|
||||||
|
type: "error",
|
||||||
|
showClose: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return gameInfo;
|
return gameInfo;
|
||||||
}
|
}
|
||||||
|
@ -172,6 +189,8 @@ class LeducHoldemGameView extends React.Component {
|
||||||
// for test use
|
// for test use
|
||||||
const replayId = 0;
|
const replayId = 0;
|
||||||
|
|
||||||
|
// start full screen loading
|
||||||
|
this.setState({fullScreenLoading: true});
|
||||||
axios.get(`${this.apiUrl}/replay/leduc_holdem/${replayId}`)
|
axios.get(`${this.apiUrl}/replay/leduc_holdem/${replayId}`)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
res = res.data;
|
res = res.data;
|
||||||
|
@ -187,7 +206,7 @@ class LeducHoldemGameView extends React.Component {
|
||||||
if(this.gameStateHistory.length !== 0 && this.gameStateHistory[0].length === 0){
|
if(this.gameStateHistory.length !== 0 && this.gameStateHistory[0].length === 0){
|
||||||
this.gameStateHistory[gameInfo.round].push(gameInfo);
|
this.gameStateHistory[gameInfo.round].push(gameInfo);
|
||||||
}
|
}
|
||||||
this.setState({gameInfo: gameInfo}, ()=>{
|
this.setState({gameInfo: gameInfo, fullScreenLoading: false}, ()=>{
|
||||||
if(this.gameStateTimeout){
|
if(this.gameStateTimeout){
|
||||||
window.clearTimeout(this.gameStateTimeout);
|
window.clearTimeout(this.gameStateTimeout);
|
||||||
this.gameStateTimeout = null;
|
this.gameStateTimeout = null;
|
||||||
|
@ -242,11 +261,14 @@ class LeducHoldemGameView extends React.Component {
|
||||||
currentMove = this.moveHistory[this.state.gameInfo.round][this.state.gameInfo.turn];
|
currentMove = this.moveHistory[this.state.gameInfo.round][this.state.gameInfo.turn];
|
||||||
}
|
}
|
||||||
let style = {};
|
let style = {};
|
||||||
style["backgroundColor"] = currentMove !== null ? `rgba(189,183,107,${currentMove.probabilities[idx].probability})` : "#bdbdbd";
|
style["backgroundColor"] = currentMove !== null ? `rgba(130, 151, 255, ${currentMove.probabilities[idx].probability})` : "#bdbdbd";
|
||||||
return (
|
return (
|
||||||
<div className={"playing"} style={style}>
|
<div className={"playing"} style={style}>
|
||||||
<div className="probability-move">
|
<div className="probability-move">
|
||||||
{currentMove !== null ? currentMove.probabilities[idx].move : <NotInterestedIcon fontSize="large" />}
|
{currentMove !== null ?
|
||||||
|
<img src={require('../assets/images/Actions/' + currentMove.probabilities[idx].move + '.png')} alt={currentMove.probabilities[idx].move} height="30%" width="30%" />
|
||||||
|
:
|
||||||
|
<NotInterestedIcon fontSize="large" />}
|
||||||
</div>
|
</div>
|
||||||
{currentMove !== null ?
|
{currentMove !== null ?
|
||||||
(<div className={"non-card"}>
|
(<div className={"non-card"}>
|
||||||
|
@ -316,6 +338,8 @@ class LeducHoldemGameView extends React.Component {
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<div>
|
||||||
|
<Navbar gameName="Leduc Hold'em" />
|
||||||
<div className={"leduc-view-container"}>
|
<div className={"leduc-view-container"}>
|
||||||
<Layout.Row style={{"height": "540px"}}>
|
<Layout.Row style={{"height": "540px"}}>
|
||||||
<Layout.Col style={{"height": "100%"}} span="17">
|
<Layout.Col style={{"height": "100%"}} span="17">
|
||||||
|
@ -367,6 +391,7 @@ class LeducHoldemGameView extends React.Component {
|
||||||
<div className="progress-bar">
|
<div className="progress-bar">
|
||||||
<LinearProgress variant="determinate" value={this.state.gameInfo.completedPercent} />
|
<LinearProgress variant="determinate" value={this.state.gameInfo.completedPercent} />
|
||||||
</div>
|
</div>
|
||||||
|
<Loading loading={this.state.fullScreenLoading}>
|
||||||
<div className="game-controller">
|
<div className="game-controller">
|
||||||
<Paper className={"game-controller-paper"} elevation={3}>
|
<Paper className={"game-controller-paper"} elevation={3}>
|
||||||
<Layout.Row style={{"height": "51px"}}>
|
<Layout.Row style={{"height": "51px"}}>
|
||||||
|
@ -422,6 +447,8 @@ class LeducHoldemGameView extends React.Component {
|
||||||
</Layout.Row>
|
</Layout.Row>
|
||||||
</Paper>
|
</Paper>
|
||||||
</div>
|
</div>
|
||||||
|
</Loading>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|