finalize translation for doudizhu demo

This commit is contained in:
Songyi Huang 2021-05-26 23:11:36 -07:00
parent c1d5b5cbb7
commit 3d9f7cebd9
6 changed files with 114 additions and 58 deletions

View File

@ -1,5 +1,4 @@
import React from 'react'; import React from 'react';
import { useTranslation } from 'react-i18next';
import { BrowserRouter as Router, Redirect, Route } from 'react-router-dom'; import { BrowserRouter as Router, Redirect, Route } from 'react-router-dom';
import Navbar from './components/Navbar'; import Navbar from './components/Navbar';
import LeaderBoard from './view/LeaderBoard'; import LeaderBoard from './view/LeaderBoard';
@ -14,9 +13,7 @@ const navbarSubtitleMap = {
}; };
function App() { function App() {
const { t } = useTranslation();
// todo: add 404 page // todo: add 404 page
return ( return (
<Router> <Router>
<Navbar subtitleMap={navbarSubtitleMap} /> <Navbar subtitleMap={navbarSubtitleMap} />

View File

@ -97,10 +97,10 @@
.form-label-left { .form-label-left {
float: left; float: left;
text-align: right; text-align: center;
font-size: 14px; font-size: 14px;
line-height: 1; line-height: 1;
padding: 11px 12px 11px 0; padding: 11px 6px 11px 6px;
box-sizing: border-box; box-sizing: border-box;
width: 80px; width: 80px;
} }

View File

@ -45,7 +45,6 @@ class DoudizhuGameBoard extends React.Component {
handleContainerMouseLeave() { handleContainerMouseLeave() {
if (this.isSelectingCards) { if (this.isSelectingCards) {
console.log('container leave');
this.isSelectingCards = false; this.isSelectingCards = false;
this.selectingCards = { start: null, cards: [] }; this.selectingCards = { start: null, cards: [] };
this.setState({ highlightedCards: [] }); this.setState({ highlightedCards: [] });
@ -54,7 +53,6 @@ class DoudizhuGameBoard extends React.Component {
handleContainerMouseUp() { handleContainerMouseUp() {
if (this.isSelectingCards) { if (this.isSelectingCards) {
console.log('container up');
this.isSelectingCards = false; this.isSelectingCards = false;
this.props.handleSelectedCards(this.selectingCards.cards); this.props.handleSelectedCards(this.selectingCards.cards);
this.selectingCards = { start: null, cards: [] }; this.selectingCards = { start: null, cards: [] };
@ -65,17 +63,14 @@ class DoudizhuGameBoard extends React.Component {
} }
handleCardMouseDown(card, idx) { handleCardMouseDown(card, idx) {
console.log('down');
this.isSelectingCards = true; this.isSelectingCards = true;
this.selectingCards.start = idx; this.selectingCards.start = idx;
this.selectingCards.cards = [card]; this.selectingCards.cards = [card];
this.setState({ highlightedCards: this.selectingCards.cards }); this.setState({ highlightedCards: this.selectingCards.cards });
console.log(this.selectingCards);
} }
handleCardMouseOver(allCards, card, idx) { handleCardMouseOver(allCards, card, idx) {
if (this.isSelectingCards) { if (this.isSelectingCards) {
console.log('over');
let tmpCards; let tmpCards;
if (idx > this.selectingCards.start) { if (idx > this.selectingCards.start) {
tmpCards = allCards.slice(this.selectingCards.start, idx + 1); tmpCards = allCards.slice(this.selectingCards.start, idx + 1);
@ -90,11 +85,12 @@ class DoudizhuGameBoard extends React.Component {
} }
computeSingleLineHand(inputCards, fadeClassName = '', cardSelectable = false) { computeSingleLineHand(inputCards, fadeClassName = '', cardSelectable = false) {
const t = this.props.t;
const cards = inputCards === 'pass' ? inputCards : sortDoudizhuCards(inputCards); const cards = inputCards === 'pass' ? inputCards : sortDoudizhuCards(inputCards);
if (cards === 'pass') { if (cards === 'pass') {
return ( return (
<div className="non-card"> <div className="non-card">
<span>PASS</span> <span>{t('doudizhu.pass')}</span>
</div> </div>
); );
} else { } else {
@ -200,6 +196,7 @@ class DoudizhuGameBoard extends React.Component {
} }
playerDecisionArea(playerIdx) { playerDecisionArea(playerIdx) {
const t = this.props.t;
let fadeClassName = ''; let fadeClassName = '';
if (this.props.toggleFade === 'fade-out' && (playerIdx + 2) % 3 === this.props.currentPlayer) if (this.props.toggleFade === 'fade-out' && (playerIdx + 2) % 3 === this.props.currentPlayer)
fadeClassName = 'fade-out'; fadeClassName = 'fade-out';
@ -214,7 +211,7 @@ class DoudizhuGameBoard extends React.Component {
</div> </div>
{this.props.gamePlayable ? ( {this.props.gamePlayable ? (
<> <>
<Button {/* <Button
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
this.props.handleMainPlayerAct('deselect'); this.props.handleMainPlayerAct('deselect');
@ -223,8 +220,8 @@ class DoudizhuGameBoard extends React.Component {
variant="contained" variant="contained"
color="primary" color="primary"
> >
Deselect {t('doudizhu.deselect')}
</Button> </Button> */}
<Button <Button
disabled={this.props.isHintDisabled} disabled={this.props.isHintDisabled}
onClick={(e) => { onClick={(e) => {
@ -235,7 +232,7 @@ class DoudizhuGameBoard extends React.Component {
variant="contained" variant="contained"
color="primary" color="primary"
> >
Hint {t('doudizhu.hint')}
</Button> </Button>
<Button <Button
disabled={this.props.isPassDisabled} disabled={this.props.isPassDisabled}
@ -247,7 +244,7 @@ class DoudizhuGameBoard extends React.Component {
variant="contained" variant="contained"
color="primary" color="primary"
> >
Pass {t('doudizhu.pass')}
</Button> </Button>
<Button <Button
disabled={!this.props.selectedCards || this.props.selectedCards.length === 0} disabled={!this.props.selectedCards || this.props.selectedCards.length === 0}
@ -259,7 +256,7 @@ class DoudizhuGameBoard extends React.Component {
variant="contained" variant="contained"
color="primary" color="primary"
> >
Play {t('doudizhu.play')}
</Button> </Button>
</> </>
) : undefined} ) : undefined}
@ -339,7 +336,7 @@ class DoudizhuGameBoard extends React.Component {
this.computeSideHand(this.props.hands[leftIdx]) this.computeSideHand(this.props.hands[leftIdx])
) : ( ) : (
<div className="player-hand-placeholder"> <div className="player-hand-placeholder">
<span>Waiting...</span> <span>{t('waiting...')}</span>
</div> </div>
)} )}
</div> </div>
@ -352,7 +349,7 @@ class DoudizhuGameBoard extends React.Component {
this.computeSideHand(this.props.hands[rightIdx]) this.computeSideHand(this.props.hands[rightIdx])
) : ( ) : (
<div className="player-hand-placeholder"> <div className="player-hand-placeholder">
<span>Waiting...</span> <span>{t('waiting...')}</span>
</div> </div>
)} )}
</div> </div>
@ -370,7 +367,7 @@ class DoudizhuGameBoard extends React.Component {
</div> </div>
) : ( ) : (
<div className="player-hand-placeholder"> <div className="player-hand-placeholder">
<span>Waiting...</span> <span>{t('waiting...')}</span>
</div> </div>
)} )}
</div> </div>

View File

@ -1,9 +1,30 @@
{ {
"hidden": "Hidden",
"waiting...": "Waiting...",
"play_again": "Play Again",
"cancel": "Cancel",
"turn": "Turn",
"doudizhu": { "doudizhu": {
"ai_hand_faceup": "AI Hand Face-Up", "ai_hand_faceup": "AI Hand Face-Up",
"play_as_landlord": "Play As Landlord", "play_as_landlord": "Play As Landlord",
"play_as_peasant": "Play As Peasant", "play_as_peasant": "Play As Peasant",
"landlord_up": "Landlord Up", "landlord_up": "Landlord Up",
"landlord_down": "Landlord Down" "landlord_down": "Landlord Down",
"peasants_win": "Peasants Win!",
"landlord_win": "Landlord Wins!",
"only_choice": "Only Choice",
"role": "Role",
"win": "Win",
"total": "Total",
"win_rate": "Win Rate",
"three_landlord_cards": "Three Landlord Cards",
"ai_thinking_time": "AI Thinking Time",
"landlord": "Landlord",
"expected_win_rate": "Expected Win Rate",
"pass": "Pass",
"deselect": "Deselect",
"hint": "Hint",
"play": "Play"
} }
} }

View File

@ -1,9 +1,30 @@
{ {
"hidden": "隐藏",
"waiting...": "等待中...",
"play_again": "再次游玩",
"cancel": "取消",
"turn": "回合",
"doudizhu": { "doudizhu": {
"ai_hand_faceup": "显示AI手牌", "ai_hand_faceup": "显示AI手牌",
"play_as_landlord": "扮演地主", "play_as_landlord": "扮演地主",
"play_as_peasant": "扮演农民", "play_as_peasant": "扮演农民",
"landlord_up": "地主上家", "landlord_up": "地主上家",
"landlord_down": "地主下家" "landlord_down": "地主下家",
"peasants_win": "农民胜利!",
"landlord_win": "地主胜利!",
"only_choice": "唯一选择",
"role": "角色",
"win": "胜场",
"total": "全部",
"win_rate": "胜率",
"three_landlord_cards": "地主牌",
"ai_thinking_time": "AI考虑时间",
"landlord": "地主",
"expected_win_rate": "预计胜率",
"pass": "不出",
"deselect": "取消选择",
"hint": "提示",
"play": "出牌"
} }
} }

View File

@ -277,7 +277,8 @@ function PvEDoudizhuDemoView() {
localStorage.setItem('GAME_STATISTICS', JSON.stringify(gameStatistics)); localStorage.setItem('GAME_STATISTICS', JSON.stringify(gameStatistics));
setTimeout(() => { setTimeout(() => {
gameEndDialogTitle = winner.role === 'peasant' ? 'Peasants win!' : 'Landlord wins!'; gameEndDialogTitle =
winner.role === 'peasant' ? t('doudizhu.peasants_win') : t('doudizhu.landlord_win');
statisticRows = [ statisticRows = [
{ {
role: 'Landlord', role: 'Landlord',
@ -403,13 +404,13 @@ function PvEDoudizhuDemoView() {
if (apiRes.data.legal_action === '') { if (apiRes.data.legal_action === '') {
proceedNextTurn([]); proceedNextTurn([]);
setPredictionRes({ setPredictionRes({
prediction: [['', 'Only Choice']], prediction: [['', t('doudizhu.only_choice')]],
hands: gameState.hands[gameState.currentPlayer].slice(), hands: gameState.hands[gameState.currentPlayer].slice(),
}); });
} else if (apiRes.data.legal_action.split(',').length === 1) { } else if (apiRes.data.legal_action.split(',').length === 1) {
proceedNextTurn(apiRes.data.legal_action.split('')); proceedNextTurn(apiRes.data.legal_action.split(''));
setPredictionRes({ setPredictionRes({
prediction: [[apiRes.data.legal_action, 'Only Choice']], prediction: [[apiRes.data.legal_action, t('doudizhu.only_choice')]],
hands: gameState.hands[gameState.currentPlayer].slice(), hands: gameState.hands[gameState.currentPlayer].slice(),
}); });
} else { } else {
@ -715,7 +716,7 @@ function PvEDoudizhuDemoView() {
if (computedCards === 'pass') { if (computedCards === 'pass') {
return ( return (
<div className={'non-card ' + toggleFade}> <div className={'non-card ' + toggleFade}>
<span>Pass</span> <span>{t('doudizhu.pass')}</span>
</div> </div>
); );
} else { } else {
@ -745,7 +746,7 @@ function PvEDoudizhuDemoView() {
return ( return (
<div className={'playing'}> <div className={'playing'}>
<div className={'non-card'}> <div className={'non-card'}>
<span>{'Hidden'}</span> <span>{t('hidden')}</span>
</div> </div>
</div> </div>
); );
@ -761,9 +762,9 @@ function PvEDoudizhuDemoView() {
</div> </div>
{predictionRes.prediction.length > idx ? ( {predictionRes.prediction.length > idx ? (
<div className={'non-card'} style={{ marginTop: '0px' }}> <div className={'non-card'} style={{ marginTop: '0px' }}>
<span>{`Expected Win Rate: ${(Number(predictionRes.prediction[idx][1]) * 100).toFixed( <span>{`${t('doudizhu.expected_win_rate')}: ${(
2, Number(predictionRes.prediction[idx][1]) * 100
)}%`}</span> ).toFixed(2)}%`}</span>
</div> </div>
) : ( ) : (
'' ''
@ -771,7 +772,7 @@ function PvEDoudizhuDemoView() {
</div> </div>
); );
} else { } else {
return <span className={'waiting'}>Waiting...</span>; return <span className={'waiting'}>{t('waiting...')}</span>;
} }
}; };
@ -861,10 +862,10 @@ function PvEDoudizhuDemoView() {
<Table aria-label="statistic table"> <Table aria-label="statistic table">
<TableHead> <TableHead>
<TableRow> <TableRow>
<TableCell>Role</TableCell> <TableCell>{t('doudizhu.role')}</TableCell>
<TableCell>Win</TableCell> <TableCell>{t('doudizhu.win')}</TableCell>
<TableCell>Total</TableCell> <TableCell>{t('doudizhu.total')}</TableCell>
<TableCell>Win Rate</TableCell> <TableCell>{t('doudizhu.win_rate')}</TableCell>
</TableRow> </TableRow>
</TableHead> </TableHead>
<TableBody> <TableBody>
@ -889,7 +890,7 @@ function PvEDoudizhuDemoView() {
setIsGameEndDialogOpen(false); setIsGameEndDialogOpen(false);
}} }}
> >
Cancel {t('cancel')}
</Button> </Button>
<Button <Button
onClick={() => handleCloseGameEndDialog()} onClick={() => handleCloseGameEndDialog()}
@ -898,7 +899,7 @@ function PvEDoudizhuDemoView() {
autoFocus autoFocus
style={{ margin: '16px' }} style={{ margin: '16px' }}
> >
Play Again {t('play_again')}
</Button> </Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>
@ -938,7 +939,7 @@ function PvEDoudizhuDemoView() {
{playerInfo.length > 0 && gameState.currentPlayer !== null ? ( {playerInfo.length > 0 && gameState.currentPlayer !== null ? (
<div style={{ padding: '16px' }}> <div style={{ padding: '16px' }}>
<span style={{ textAlign: 'center', marginBottom: '8px', display: 'block' }}> <span style={{ textAlign: 'center', marginBottom: '8px', display: 'block' }}>
Three Landlord Cards {t('doudizhu.three_landlord_cards')}
</span> </span>
<div className="playingCards" style={{ display: 'flex', justifyContent: 'center' }}> <div className="playingCards" style={{ display: 'flex', justifyContent: 'center' }}>
{sortDoudizhuCards(originalThreeLandlordCards, true).map((card) => { {sortDoudizhuCards(originalThreeLandlordCards, true).map((card) => {
@ -966,21 +967,23 @@ function PvEDoudizhuDemoView() {
justifyContent: 'center', justifyContent: 'center',
}} }}
> >
<span>Waiting...</span> <span>{t('waiting...')}</span>
</div> </div>
)} )}
<Divider /> <Divider />
<div className={'probability-player'} style={{ height: '19px', textAlign: 'center' }}> <div className={'probability-player'} style={{ height: '19px', textAlign: 'center' }}>
{playerInfo.length > 0 && gameState.currentPlayer !== null ? ( {playerInfo.length > 0 && gameState.currentPlayer !== null ? (
<span> <span>
{ {t(
['Landlord', 'Landlord Down', 'Landlord Up'][ `doudizhu.${
['landlord', 'landlord_down', 'landlord_up'][
playerInfo[gameState.currentPlayer].douzeroPlayerPosition playerInfo[gameState.currentPlayer].douzeroPlayerPosition
] ]
} }`,
)}
</span> </span>
) : ( ) : (
<span>Waiting...</span> <span>{t('waiting...')}</span>
)} )}
</div> </div>
<Divider /> <Divider />
@ -1014,7 +1017,7 @@ function PvEDoudizhuDemoView() {
span="3" span="3"
style={{ height: '51px', lineHeight: '51px', marginLeft: '-2px', marginRight: '-2px' }} style={{ height: '51px', lineHeight: '51px', marginLeft: '-2px', marginRight: '-2px' }}
> >
<div style={{ textAlign: 'center' }}>{`Turn ${gameState.turn}`}</div> <div style={{ textAlign: 'center' }}>{`${t('turn')} ${gameState.turn}`}</div>
</Layout.Col> </Layout.Col>
<Layout.Col span="1" style={{ height: '100%', width: '1px' }}> <Layout.Col span="1" style={{ height: '100%', width: '1px' }}>
<Divider orientation="vertical" /> <Divider orientation="vertical" />
@ -1025,9 +1028,9 @@ function PvEDoudizhuDemoView() {
className={'form-label-left'} className={'form-label-left'}
style={{ width: '155px', lineHeight: '28px', fontSize: '15px' }} style={{ width: '155px', lineHeight: '28px', fontSize: '15px' }}
> >
AI Thinking Time {t('doudizhu.ai_thinking_time')}
</label> </label>
<div style={{ marginLeft: '170px', marginRight: '20px' }}> <div style={{ marginLeft: '160px', marginRight: '30px' }}>
<Slider <Slider
value={gameSpeedMap.find((element) => element.delay === apiPlayDelay).value} value={gameSpeedMap.find((element) => element.delay === apiPlayDelay).value}
getAriaValueText={sliderValueText} getAriaValueText={sliderValueText}
@ -1058,7 +1061,7 @@ function PvEDoudizhuDemoView() {
paddingLeft: '10px', paddingLeft: '10px',
}} }}
> >
<TranslateIcon /> <TranslateIcon style={{ width: '1.2rem', height: '1.2rem' }} />
<Select <Select
id="language-select" id="language-select"
style={{ width: '100%', textAlign: 'center', marginLeft: '7px' }} style={{ width: '100%', textAlign: 'center', marginLeft: '7px' }}
@ -1074,6 +1077,8 @@ function PvEDoudizhuDemoView() {
</Paper> </Paper>
</div> </div>
<div className="citation"> <div className="citation">
{locale === 'en' ? (
<>
This demo is based on{' '} This demo is based on{' '}
<a href="https://github.com/datamllab/rlcard" target="_blank"> <a href="https://github.com/datamllab/rlcard" target="_blank">
RLCard RLCard
@ -1083,6 +1088,21 @@ function PvEDoudizhuDemoView() {
DouZero DouZero
</a> </a>
. If you find these projects useful, please cite: . If you find these projects useful, please cite:
</>
) : (
<>
本演示基于{' '}
<a href="https://github.com/datamllab/rlcard" target="_blank">
RLCard
</a>{' '}
{' '}
<a href="https://github.com/daochenzha/douzero" target="_blank">
DouZero
</a>{' '}
项目如果这些项目帮到您请添加引用:
</>
)}
<pre> <pre>
{`@article{zha2019rlcard, {`@article{zha2019rlcard,
title={RLCard: A Toolkit for Reinforcement Learning in Card Games}, title={RLCard: A Toolkit for Reinforcement Learning in Card Games},