make leaderboard table show agent ranking info; add total row info in query api
This commit is contained in:
parent
0cc89a3b55
commit
b7b722761e
|
@ -48,11 +48,12 @@ PAGE_FIELDS = ['elements_every_page', 'page_index']
|
|||
def _get_page(result, elements_every_page, page_index):
|
||||
elements_every_page = int(elements_every_page)
|
||||
page_index = int(page_index)
|
||||
total_row = len(result)
|
||||
total_page = math.ceil(len(result) / float(elements_every_page))
|
||||
begin = page_index * elements_every_page
|
||||
end = min((page_index+1) * elements_every_page, len(result))
|
||||
result = result[begin:end]
|
||||
return result, total_page
|
||||
return result, total_page, total_row
|
||||
|
||||
def replay(request):
|
||||
if request.method == 'GET':
|
||||
|
@ -70,9 +71,9 @@ def query_game(request):
|
|||
return HttpResponse(json.dumps({'value': -1, 'info': 'elements_every_page and page_index should be given'}))
|
||||
filter_dict = {key: request.GET.get(key) for key in dict(request.GET).keys() if key not in PAGE_FIELDS}
|
||||
result = Game.objects.filter(**filter_dict).order_by('index')
|
||||
result, total_page = _get_page(result, request.GET['elements_every_page'], request.GET['page_index'])
|
||||
result, total_page, total_row = _get_page(result, request.GET['elements_every_page'], request.GET['page_index'])
|
||||
result = serializers.serialize('json', result, fields=('name', 'index', 'agent0', 'agent1', 'win', 'payoff'))
|
||||
return HttpResponse(json.dumps({'value': 0, 'data': json.loads(result), 'total_page': total_page}))
|
||||
return HttpResponse(json.dumps({'value': 0, 'data': json.loads(result), 'total_page': total_page, 'total_row': total_row}))
|
||||
|
||||
def query_payoff(request):
|
||||
if request.method == 'GET':
|
||||
|
@ -82,15 +83,15 @@ def query_payoff(request):
|
|||
return HttpResponse(result)
|
||||
|
||||
def query_agent_payoff(request):
|
||||
if request.method == 'GET':
|
||||
if request.method == 'GET':
|
||||
if not PAGE_FIELDS[0] in request.GET or not PAGE_FIELDS[1] in request.GET:
|
||||
return HttpResponse(json.dumps({'value': -1, 'info': 'elements_every_page and page_index should be given'}))
|
||||
if not 'name' in request.GET:
|
||||
return HttpResponse(json.dumps({'value': -2, 'info': 'name should be given'}))
|
||||
result = list(Payoff.objects.filter(name=request.GET['name']).values('agent0').annotate(payoff = Avg('payoff')).order_by('-payoff'))
|
||||
print(result)
|
||||
result, total_page = _get_page(result, request.GET['elements_every_page'], request.GET['page_index'])
|
||||
return HttpResponse(json.dumps({'value': 0, 'data': result, 'total_page': total_page}))
|
||||
result, total_page, total_row = _get_page(result, request.GET['elements_every_page'], request.GET['page_index'])
|
||||
return HttpResponse(json.dumps({'value': 0, 'data': result, 'total_page': total_page, 'total_row': total_row}))
|
||||
|
||||
@transaction.atomic
|
||||
def launch(request):
|
||||
|
|
|
@ -15,7 +15,7 @@ import LinearProgress from '@material-ui/core/LinearProgress';
|
|||
import PlayArrowRoundedIcon from '@material-ui/icons/PlayArrowRounded';
|
||||
import PauseCircleOutlineRoundedIcon from '@material-ui/icons/PauseCircleOutlineRounded';
|
||||
import ReplayRoundedIcon from '@material-ui/icons/ReplayRounded';
|
||||
import NotInterestedIcon from '@material-ui/icons/NotInterested';
|
||||
// import NotInterestedIcon from '@material-ui/icons/NotInterested';
|
||||
import SkipNextIcon from '@material-ui/icons/SkipNext';
|
||||
import SkipPreviousIcon from '@material-ui/icons/SkipPrevious';
|
||||
import DialogTitle from "@material-ui/core/DialogTitle";
|
||||
|
@ -281,30 +281,30 @@ class DoudizhuGameView extends React.Component {
|
|||
|
||||
computeProbabilityItem(idx){
|
||||
return <span className={"waiting"}>Currently Unavailable...</span>
|
||||
if(this.state.gameInfo.gameStatus !== "ready" && this.state.gameInfo.turn < this.moveHistory.length){
|
||||
let style = {};
|
||||
style["backgroundColor"] = this.moveHistory[this.state.gameInfo.turn].probabilities.length > idx ? `rgba(63, 81, 181, ${this.moveHistory[this.state.gameInfo.turn].probabilities[idx].probability})` : "#bdbdbd";
|
||||
return (
|
||||
<div className={"playing"} style={style}>
|
||||
<div className="probability-move">
|
||||
{this.moveHistory[this.state.gameInfo.turn].probabilities.length > idx ?
|
||||
this.computeSingleLineHand(this.cardStr2Arr(this.moveHistory[this.state.gameInfo.turn].probabilities[idx].move))
|
||||
:
|
||||
<NotInterestedIcon fontSize="large" />
|
||||
}
|
||||
</div>
|
||||
{this.moveHistory[this.state.gameInfo.turn].probabilities.length > idx ?
|
||||
<div className={"non-card"}>
|
||||
<span>{this.moveHistory[this.state.gameInfo.turn].probabilities.length > idx ? `Probability ${(this.moveHistory[this.state.gameInfo.turn].probabilities[idx].probability * 100).toFixed(2)}%` : ""}</span>
|
||||
</div>
|
||||
:
|
||||
""
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}else {
|
||||
return <span className={"waiting"}>Waiting...</span>
|
||||
}
|
||||
// if(this.state.gameInfo.gameStatus !== "ready" && this.state.gameInfo.turn < this.moveHistory.length){
|
||||
// let style = {};
|
||||
// style["backgroundColor"] = this.moveHistory[this.state.gameInfo.turn].probabilities.length > idx ? `rgba(63, 81, 181, ${this.moveHistory[this.state.gameInfo.turn].probabilities[idx].probability})` : "#bdbdbd";
|
||||
// return (
|
||||
// <div className={"playing"} style={style}>
|
||||
// <div className="probability-move">
|
||||
// {this.moveHistory[this.state.gameInfo.turn].probabilities.length > idx ?
|
||||
// this.computeSingleLineHand(this.cardStr2Arr(this.moveHistory[this.state.gameInfo.turn].probabilities[idx].move))
|
||||
// :
|
||||
// <NotInterestedIcon fontSize="large" />
|
||||
// }
|
||||
// </div>
|
||||
// {this.moveHistory[this.state.gameInfo.turn].probabilities.length > idx ?
|
||||
// <div className={"non-card"}>
|
||||
// <span>{this.moveHistory[this.state.gameInfo.turn].probabilities.length > idx ? `Probability ${(this.moveHistory[this.state.gameInfo.turn].probabilities[idx].probability * 100).toFixed(2)}%` : ""}</span>
|
||||
// </div>
|
||||
// :
|
||||
// ""
|
||||
// }
|
||||
// </div>
|
||||
// )
|
||||
// }else {
|
||||
// return <span className={"waiting"}>Waiting...</span>
|
||||
// }
|
||||
}
|
||||
|
||||
go2PrevGameState() {
|
||||
|
|
|
@ -34,32 +34,55 @@ const modelList = [
|
|||
];
|
||||
|
||||
function LeaderBoard () {
|
||||
const initRowsPerPage = 10;
|
||||
const [rowsPerPage, setRowsPerPage] = React.useState(initRowsPerPage);
|
||||
const [page, setPage] = React.useState(0);
|
||||
const [rowsTotal, setRowsTotal] = React.useState(0);
|
||||
const [rows, setRows] = React.useState([]);
|
||||
|
||||
const { type, name } = qs.parse(window.location.search);
|
||||
let requestUrl = `${apiUrl}/tournament/`;
|
||||
if (type === 'game') {
|
||||
requestUrl += `query_game?name=${name}`
|
||||
requestUrl += `query_agent_payoff?name=${name}&elements_every_page=${rowsPerPage}&page_index=${page}`
|
||||
} else if (type === 'agent') {
|
||||
requestUrl += `query_game?agent0=${name}`
|
||||
requestUrl += `query_game?agent0=${name}&elements_every_page=${rowsPerPage}&page_index=${page}`
|
||||
}
|
||||
console.log(requestUrl);
|
||||
|
||||
// todo: detect type change then reset page and page size
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchData() {
|
||||
const res = await axios.get(requestUrl);
|
||||
console.log('wdnmd', res);
|
||||
setRows(res.data.map((resRow) => {return createData(resRow);}));
|
||||
console.log(res);
|
||||
if (type === 'game') {
|
||||
setRows(res.data.data.map((resRow, index) => {
|
||||
const rank = rowsPerPage * page + index + 1;
|
||||
return createLeaderBoardData(resRow, rank);
|
||||
}));
|
||||
} else if (type === 'agent') {
|
||||
setRows(res.data.data.map((resRow) => {return createData(resRow);}));
|
||||
}
|
||||
setRowsTotal(res.data.total_row)
|
||||
}
|
||||
fetchData();
|
||||
}, [requestUrl])
|
||||
}, [requestUrl, page, rowsPerPage, type])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<MenuBar gameList={gameList} modelList={modelList} />
|
||||
<div style={{marginLeft: '250px'}}>
|
||||
<div style={{padding: 20}}>
|
||||
<EnhancedTable tableRows={rows} routeInfo={{type, name}}/>
|
||||
<EnhancedTable
|
||||
tableRows={rows}
|
||||
routeInfo={{type, name}}
|
||||
page={page}
|
||||
setPage={(q) => {setPage(q)}}
|
||||
rowsPerPage={rowsPerPage}
|
||||
setRowsPerPage={(q) => {setRowsPerPage(q)}}
|
||||
rowsTotal={rowsTotal}
|
||||
type={type}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -78,7 +101,15 @@ function createData(resData) {
|
|||
};
|
||||
}
|
||||
|
||||
const headCells = [
|
||||
function createLeaderBoardData(resData, rank) {
|
||||
return {
|
||||
rank: rank,
|
||||
agent: resData.agent0,
|
||||
payoff: resData.payoff
|
||||
}
|
||||
}
|
||||
|
||||
const agentHeadCells = [
|
||||
{ id: 'id', numeric: false, disablePadding: false, label: 'ID' },
|
||||
{ id: 'game', numeric: false, disablePadding: false, label: 'Game' },
|
||||
{ id: 'agent0', numeric: false, disablePadding: false, label: 'Agent 0' },
|
||||
|
@ -88,6 +119,12 @@ const headCells = [
|
|||
{ id: 'replay', numeric: false, disablePadding: false, label: 'Replay' }
|
||||
];
|
||||
|
||||
const leaderBoardHeadCells = [
|
||||
{ id: 'rank', numeric: false, disablePadding: false, label: 'Rank' },
|
||||
{ id: 'agent', numeric: false, disablePadding: false, label: 'Agent' },
|
||||
{ id: 'payoff', numeric: false, disablePadding: false, label: 'Payoff' }
|
||||
];
|
||||
|
||||
const StyledTableCell = withStyles((theme) => ({
|
||||
head: {
|
||||
backgroundColor: '#373538',
|
||||
|
@ -97,7 +134,8 @@ const StyledTableCell = withStyles((theme) => ({
|
|||
}
|
||||
}))(TableCell);
|
||||
|
||||
function EnhancedTableHead() {
|
||||
function EnhancedTableHead(props) {
|
||||
const {headCells} = props;
|
||||
return (
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
|
@ -115,11 +153,6 @@ function EnhancedTableHead() {
|
|||
);
|
||||
}
|
||||
|
||||
EnhancedTableHead.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
rowCount: PropTypes.number.isRequired,
|
||||
};
|
||||
|
||||
const useToolbarStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
paddingLeft: theme.spacing(2),
|
||||
|
@ -206,17 +239,98 @@ const useStyles = makeStyles((theme) => ({
|
|||
},
|
||||
}));
|
||||
|
||||
const EnhancedTable = (props) => {
|
||||
const initRowsPerPage = 10;
|
||||
const { tableRows, routeInfo } = props;
|
||||
const LeaderBoardTableContent = (props) => {
|
||||
const { tableRows, rowsPerPage, page, rowsTotal, headCells } = props;
|
||||
const classes = useStyles();
|
||||
const [rowsPerPage, setRowsPerPage] = React.useState(initRowsPerPage);
|
||||
const [page, setPage] = React.useState(0);
|
||||
const emptyRows = rowsPerPage - Math.min(rowsPerPage, rowsTotal - page * rowsPerPage);
|
||||
return (
|
||||
<TableContainer>
|
||||
<Table
|
||||
className={classes.table}
|
||||
aria-labelledby="tableTitle"
|
||||
size={'medium'}
|
||||
aria-label="enhanced table"
|
||||
>
|
||||
<EnhancedTableHead headCells={headCells}/>
|
||||
<TableBody>
|
||||
{tableRows.map((row, index) => {
|
||||
const labelId = `enhanced-table-checkbox-${index}`;
|
||||
return (
|
||||
<TableRow
|
||||
hover
|
||||
role="checkbox"
|
||||
tabIndex={-1}
|
||||
key={row.rank}
|
||||
>
|
||||
<TableCell component="th" id={labelId} scope="row">
|
||||
{row.rank}
|
||||
</TableCell>
|
||||
<TableCell>{row.agent}</TableCell>
|
||||
<TableCell>{row.payoff}</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
{emptyRows > 0 && (
|
||||
<TableRow style={{ height: 53 * emptyRows }}>
|
||||
<TableCell colSpan={3} />
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setRowsPerPage(initRowsPerPage);
|
||||
setPage(0);
|
||||
}, [tableRows]);
|
||||
const AgentTableContent = (props) => {
|
||||
const { tableRows, rowsPerPage, page, rowsTotal, headCells } = props;
|
||||
const classes = useStyles();
|
||||
const emptyRows = rowsPerPage - Math.min(rowsPerPage, rowsTotal - page * rowsPerPage);
|
||||
return (
|
||||
<TableContainer>
|
||||
<Table
|
||||
className={classes.table}
|
||||
aria-labelledby="tableTitle"
|
||||
size={'medium'}
|
||||
aria-label="enhanced table"
|
||||
>
|
||||
<EnhancedTableHead headCells={headCells}/>
|
||||
<TableBody>
|
||||
{tableRows.map((row, index) => {
|
||||
const labelId = `enhanced-table-checkbox-${index}`;
|
||||
return (
|
||||
<TableRow
|
||||
hover
|
||||
role="checkbox"
|
||||
tabIndex={-1}
|
||||
key={row.id}
|
||||
>
|
||||
<TableCell component="th" id={labelId} scope="row">
|
||||
{row.id}
|
||||
</TableCell>
|
||||
<TableCell>{row.game}</TableCell>
|
||||
<TableCell>{row.agent0}</TableCell>
|
||||
<TableCell>{row.agent1}</TableCell>
|
||||
<TableCell>{row.win}</TableCell>
|
||||
<TableCell>{row.payoff}</TableCell>
|
||||
<TableCell><a style={{display: "table-cell"}} href={row.replayUrl} rel="noopener noreferrer" target="_blank"><PlayCircleOutlineIcon style={{verticalAlign: "middle"}}/></a></TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
{emptyRows > 0 && (
|
||||
<TableRow style={{ height: 53 * emptyRows }}>
|
||||
<TableCell colSpan={7} />
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
)
|
||||
}
|
||||
|
||||
const EnhancedTable = (props) => {
|
||||
|
||||
const { tableRows, routeInfo, rowsPerPage, page, setPage, setRowsPerPage, rowsTotal, type } = props;
|
||||
const classes = useStyles();
|
||||
|
||||
const handleChangePage = (event, newPage) => {
|
||||
setPage(newPage);
|
||||
|
@ -227,59 +341,23 @@ const EnhancedTable = (props) => {
|
|||
setPage(0);
|
||||
};
|
||||
|
||||
const emptyRows = rowsPerPage - Math.min(rowsPerPage, tableRows.length - page * rowsPerPage);
|
||||
let tableContent = '';
|
||||
if (type === 'game') {
|
||||
tableContent = <LeaderBoardTableContent headCells={leaderBoardHeadCells} tableRows={tableRows} rowsPerPage={rowsPerPage} page={page} rowsTotal={rowsTotal}/>;
|
||||
} else if (type === 'agent') {
|
||||
tableContent = <AgentTableContent headCells={agentHeadCells} tableRows={tableRows} rowsPerPage={rowsPerPage} page={page} rowsTotal={rowsTotal}/>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<Paper className={classes.paper}>
|
||||
<EnhancedTableToolbar routeInfo={routeInfo}/>
|
||||
<TableContainer>
|
||||
<Table
|
||||
className={classes.table}
|
||||
aria-labelledby="tableTitle"
|
||||
size={'medium'}
|
||||
aria-label="enhanced table"
|
||||
>
|
||||
<EnhancedTableHead
|
||||
classes={classes}
|
||||
rowCount={tableRows.length}
|
||||
/>
|
||||
<TableBody>
|
||||
{tableRows
|
||||
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
|
||||
.map((row, index) => {
|
||||
const labelId = `enhanced-table-checkbox-${index}`;
|
||||
return (
|
||||
<TableRow
|
||||
hover
|
||||
role="checkbox"
|
||||
tabIndex={-1}
|
||||
key={row.id}
|
||||
>
|
||||
<TableCell component="th" id={labelId} scope="row">
|
||||
{row.id}
|
||||
</TableCell>
|
||||
<TableCell>{row.game}</TableCell>
|
||||
<TableCell>{row.agent0}</TableCell>
|
||||
<TableCell>{row.agent1}</TableCell>
|
||||
<TableCell>{row.win}</TableCell>
|
||||
<TableCell>{row.payoff}</TableCell>
|
||||
<TableCell><a style={{display: "table-cell"}} href={row.replayUrl} target="_blank"><PlayCircleOutlineIcon style={{verticalAlign: "middle"}}/></a></TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
{emptyRows > 0 && (
|
||||
<TableRow style={{ height: 53 * emptyRows }}>
|
||||
<TableCell colSpan={6} />
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
{tableContent}
|
||||
<TablePagination
|
||||
rowsPerPageOptions={[10, 50, 100]}
|
||||
// todo: remove testing page size option
|
||||
rowsPerPageOptions={[2, 10, 50, 100]}
|
||||
component="div"
|
||||
count={tableRows.length}
|
||||
count={rowsTotal}
|
||||
rowsPerPage={rowsPerPage}
|
||||
page={page}
|
||||
onChangePage={handleChangePage}
|
||||
|
|
Loading…
Reference in New Issue