changed style for leduc

This commit is contained in:
Lei Pan 2020-02-24 10:47:33 -08:00
parent cee7ea7474
commit 22aea96775
13 changed files with 248 additions and 138 deletions

View File

@ -8,7 +8,6 @@
margin-right: auto;
padding: 5px;
display: flex;
.stretch {
flex: 1;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -1,5 +1,13 @@
@import "cards.css";
.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 {
font-size: 12px;
@ -8,17 +16,41 @@
display: flex;
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 {
display: table;
width: 280px;
height: 100px;
span {
display: table-cell;
vertical-align: middle;
text-align: center;
font-size: 16px;
}
width: 80px;
height: 40px;
}
}
@ -37,14 +69,11 @@
font-size: 16px;
width: 130px;
height: 130px;
border-radius: 25px;
border: 2px solid #73AD21;
display: table;
div {
text-align: center;
}
span {
white-space: pre;
display: table-cell;
vertical-align: middle;
text-align: center;
}
}
@ -96,16 +125,17 @@
margin-top: -75px;
width: 130px;
height: 150px;
border-radius: 25px;
border: 2px solid blue;
display: table;
.info-area {
display: table-cell;
vertical-align: middle;
text-align: center;
font-size: 20px;
font-weight: bold;
text-shadow: 0 2px 2px rgba(0, 0, 0, 0.87);
color: #F2F6FC;
}
.playingCards {
transform: translate(3px, 10px);
}

View File

@ -2,17 +2,65 @@ import React from 'react';
import { translateCardData, millisecond2Second } from '../../utils'
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 {
constructor(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) {
const [rankClass, suitClass, rankText, suitText] = translateCardData(card);
return (
<div className="playingCards faceImages">
<div className={`card ${rankClass} ${suitClass}`}>
<div className="playingCards faceImages unselectable">
<div className={`card ${rankClass} full-content ${suitClass}`}>
<span className="rank">{rankText}</span>
<span className="suit">{suitText}</span>
</div>
@ -22,9 +70,13 @@ class LeducHoldemGameBoard extends React.Component {
playerDecisionArea(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{
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);
return (
<div className="playingCards faceImages">
<div className={`card ${rankClass} ${suitClass}`}>
<div className={`card ${rankClass} full-content ${suitClass}`}>
<span className="rank">{rankText}</span>
<span className="suit">{suitText}</span>
</div>
@ -65,14 +117,15 @@ class LeducHoldemGameBoard extends React.Component {
topId = found.id;
}
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 className="played-card-area">
{bottomIdx >= 0 ? this.playerDecisionArea(bottomIdx) : ""}
</div>
<div className="player-main-area">
<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>
{bottomIdx >= 0 ? <div className="player-hand">{this.computeHand(this.props.hands[bottomIdx])}</div> : <div className="player-hand-placeholder"><span>Waiting...</span></div>}
</div>
@ -80,7 +133,8 @@ class LeducHoldemGameBoard extends React.Component {
<div id={"top-player"}>
<div className="player-main-area">
<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>
{topIdx >= 0 ? <div className="player-hand">{this.computeHand(this.props.hands[topIdx])}</div> : <div className="player-hand-placeholder"><span>Waiting...</span></div>}
</div>

View File

@ -2,9 +2,10 @@ import React from 'react';
import axios from 'axios';
import '../assets/gameview.scss';
import {LeducHoldemGameBoard} from '../components/GameBoard';
import Navbar from '../components/Navbar';
import {deepCopy} from "../utils";
import { Layout } from 'element-react';
import { Layout, Message, Loading } from 'element-react';
import Slider from '@material-ui/core/Slider';
import Button from '@material-ui/core/Button';
import Paper from '@material-ui/core/Paper';
@ -46,12 +47,12 @@ class LeducHoldemGameView extends React.Component {
this.state = {
gameInfo: this.initGameState,
gameStateLoop: null,
gameSpeed: 0
gameSpeed: 0,
fullScreenLoading: false
}
}
generateNewState(){
// console.log(this.state.gameInfo.latestAction);
let gameInfo = deepCopy(this.state.gameInfo);
const turn = this.state.gameInfo.turn;
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]){
gameInfo.pot[gameInfo.currentPlayer] = gameInfo.pot[(gameInfo.currentPlayer+2-1)%2];
}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;
case "Fold":
@ -101,7 +106,11 @@ class LeducHoldemGameView extends React.Component {
}, 200);
return gameInfo;
default:
console.log("Error in player's latest action");
Message({
message: "Error in player's latest action",
type: "error",
showClose: true
});
}
gameInfo.turn++;
if(gameInfo.round !== 0 && gameInfo.turn === this.moveHistory[gameInfo.round].length){
@ -119,14 +128,22 @@ class LeducHoldemGameView extends React.Component {
gameInfo.gameStatus = "playing";
this.setState({ gameInfo: gameInfo });
}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(gameInfo.turn === this.gameStateHistory[gameInfo.round].length){
this.gameStateHistory[gameInfo.round].push(gameInfo);
}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;
}
@ -172,6 +189,8 @@ class LeducHoldemGameView extends React.Component {
// for test use
const replayId = 0;
// start full screen loading
this.setState({fullScreenLoading: true});
axios.get(`${this.apiUrl}/replay/leduc_holdem/${replayId}`)
.then(res => {
res = res.data;
@ -187,7 +206,7 @@ class LeducHoldemGameView extends React.Component {
if(this.gameStateHistory.length !== 0 && this.gameStateHistory[0].length === 0){
this.gameStateHistory[gameInfo.round].push(gameInfo);
}
this.setState({gameInfo: gameInfo}, ()=>{
this.setState({gameInfo: gameInfo, fullScreenLoading: false}, ()=>{
if(this.gameStateTimeout){
window.clearTimeout(this.gameStateTimeout);
this.gameStateTimeout = null;
@ -242,11 +261,14 @@ class LeducHoldemGameView extends React.Component {
currentMove = this.moveHistory[this.state.gameInfo.round][this.state.gameInfo.turn];
}
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 (
<div className={"playing"} style={style}>
<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>
{currentMove !== null ?
(<div className={"non-card"}>
@ -316,111 +338,116 @@ class LeducHoldemGameView extends React.Component {
];
return (
<div className={"leduc-view-container"}>
<Layout.Row style={{"height": "540px"}}>
<Layout.Col style={{"height": "100%"}} span="17">
<div style={{"height": "100%"}}>
<Paper className={"leduc-gameboard-paper"} elevation={3}>
<LeducHoldemGameBoard
playerInfo={this.state.gameInfo.playerInfo}
hands={this.state.gameInfo.hands}
latestAction={this.state.gameInfo.latestAction}
mainPlayerId={this.state.gameInfo.mainViewerId}
currentPlayer={this.state.gameInfo.currentPlayer}
considerationTime={this.state.gameInfo.considerationTime}
round={this.state.gameInfo.round}
turn={this.state.gameInfo.turn}
pot={this.state.gameInfo.pot}
publicCard={this.state.gameInfo.publicCard}
/>
</Paper>
</div>
</Layout.Col>
<Layout.Col span="7" style={{"height": "100%"}}>
<Paper className={"leduc-probability-paper"} elevation={3}>
<div className={"probability-player"}>
{
this.state.gameInfo.playerInfo.length > 0 ?
<span>Current Player: {this.state.gameInfo.currentPlayer}</span>
:
<span>Waiting...</span>
}
<div>
<Navbar gameName="Leduc Hold'em" />
<div className={"leduc-view-container"}>
<Layout.Row style={{"height": "540px"}}>
<Layout.Col style={{"height": "100%"}} span="17">
<div style={{"height": "100%"}}>
<Paper className={"leduc-gameboard-paper"} elevation={3}>
<LeducHoldemGameBoard
playerInfo={this.state.gameInfo.playerInfo}
hands={this.state.gameInfo.hands}
latestAction={this.state.gameInfo.latestAction}
mainPlayerId={this.state.gameInfo.mainViewerId}
currentPlayer={this.state.gameInfo.currentPlayer}
considerationTime={this.state.gameInfo.considerationTime}
round={this.state.gameInfo.round}
turn={this.state.gameInfo.turn}
pot={this.state.gameInfo.pot}
publicCard={this.state.gameInfo.publicCard}
/>
</Paper>
</div>
<Divider />
<div className={"probability-table"}>
<div className={"probability-item"}>
{this.computeProbabilityItem(0)}
</Layout.Col>
<Layout.Col span="7" style={{"height": "100%"}}>
<Paper className={"leduc-probability-paper"} elevation={3}>
<div className={"probability-player"}>
{
this.state.gameInfo.playerInfo.length > 0 ?
<span>Current Player: {this.state.gameInfo.currentPlayer}</span>
:
<span>Waiting...</span>
}
</div>
<div className={"probability-item"}>
{this.computeProbabilityItem(1)}
</div>
<div className={"probability-item"}>
{this.computeProbabilityItem(2)}
</div>
<div className={"probability-item"}>
{this.computeProbabilityItem(3)}
</div>
</div>
</Paper>
</Layout.Col>
</Layout.Row>
<div className="progress-bar">
<LinearProgress variant="determinate" value={this.state.gameInfo.completedPercent} />
</div>
<div className="game-controller">
<Paper className={"game-controller-paper"} elevation={3}>
<Layout.Row style={{"height": "51px"}}>
<Layout.Col span="7" style={{"height": "51px", "lineHeight": "48px"}}>
<div>
<Button
variant="contained"
color="primary"
disabled={this.state.gameInfo.gameStatus !== "paused" || (this.state.gameInfo.round === 0 && this.state.gameInfo.turn === 0)}
onClick={()=>{this.go2PrevGameState()}}
>
<SkipPreviousIcon />
</Button>
{ this.gameStatusButton(this.state.gameInfo.gameStatus) }
<Button
variant="contained"
color="primary"
disabled={this.state.gameInfo.gameStatus !== "paused"}
onClick={()=>{this.go2NextGameState()}}
>
<SkipNextIcon />
</Button>
</div>
</Layout.Col>
<Layout.Col span="1" style={{"height": "100%", "width": "1px"}}>
<Divider orientation="vertical" />
</Layout.Col>
<Layout.Col span="3" style={{"height": "51px", "lineHeight": "51px", "marginLeft": "-1px", "marginRight": "-1px"}}>
<div style={{"textAlign": "center"}}>{`Turn: ${this.state.gameInfo.turn}`}</div>
</Layout.Col>
<Layout.Col span="1" style={{"height": "100%", "width": "1px"}}>
<Divider orientation="vertical" />
</Layout.Col>
<Layout.Col span="14">
<div>
<label className={"form-label-left"}>Game Speed</label>
<div style={{"marginLeft": "100px", "marginRight": "10px"}}>
<Slider
value={this.state.gameSpeed}
getAriaValueText={sliderValueText}
onChange={(e, newVal)=>{this.changeGameSpeed(newVal)}}
aria-labelledby="discrete-slider-custom"
step={1}
min={-3}
max={3}
track={false}
valueLabelDisplay="off"
marks={gameSpeedMarks}
/>
<Divider />
<div className={"probability-table"}>
<div className={"probability-item"}>
{this.computeProbabilityItem(0)}
</div>
<div className={"probability-item"}>
{this.computeProbabilityItem(1)}
</div>
<div className={"probability-item"}>
{this.computeProbabilityItem(2)}
</div>
<div className={"probability-item"}>
{this.computeProbabilityItem(3)}
</div>
</div>
</Layout.Col>
</Layout.Row>
</Paper>
</Paper>
</Layout.Col>
</Layout.Row>
<div className="progress-bar">
<LinearProgress variant="determinate" value={this.state.gameInfo.completedPercent} />
</div>
<Loading loading={this.state.fullScreenLoading}>
<div className="game-controller">
<Paper className={"game-controller-paper"} elevation={3}>
<Layout.Row style={{"height": "51px"}}>
<Layout.Col span="7" style={{"height": "51px", "lineHeight": "48px"}}>
<div>
<Button
variant="contained"
color="primary"
disabled={this.state.gameInfo.gameStatus !== "paused" || (this.state.gameInfo.round === 0 && this.state.gameInfo.turn === 0)}
onClick={()=>{this.go2PrevGameState()}}
>
<SkipPreviousIcon />
</Button>
{ this.gameStatusButton(this.state.gameInfo.gameStatus) }
<Button
variant="contained"
color="primary"
disabled={this.state.gameInfo.gameStatus !== "paused"}
onClick={()=>{this.go2NextGameState()}}
>
<SkipNextIcon />
</Button>
</div>
</Layout.Col>
<Layout.Col span="1" style={{"height": "100%", "width": "1px"}}>
<Divider orientation="vertical" />
</Layout.Col>
<Layout.Col span="3" style={{"height": "51px", "lineHeight": "51px", "marginLeft": "-1px", "marginRight": "-1px"}}>
<div style={{"textAlign": "center"}}>{`Turn: ${this.state.gameInfo.turn}`}</div>
</Layout.Col>
<Layout.Col span="1" style={{"height": "100%", "width": "1px"}}>
<Divider orientation="vertical" />
</Layout.Col>
<Layout.Col span="14">
<div>
<label className={"form-label-left"}>Game Speed</label>
<div style={{"marginLeft": "100px", "marginRight": "10px"}}>
<Slider
value={this.state.gameSpeed}
getAriaValueText={sliderValueText}
onChange={(e, newVal)=>{this.changeGameSpeed(newVal)}}
aria-labelledby="discrete-slider-custom"
step={1}
min={-3}
max={3}
track={false}
valueLabelDisplay="off"
marks={gameSpeedMarks}
/>
</div>
</div>
</Layout.Col>
</Layout.Row>
</Paper>
</div>
</Loading>
</div>
</div>
);