Skip to content

Commit

Permalink
fix: admin past games view fixes
Browse files Browse the repository at this point in the history
- don't display highscores and winners for defeated games
- show contact info for players without a full name given
- add types for the game data

resolves virtualcommons/planning#54
  • Loading branch information
sgfost committed Nov 17, 2023
1 parent 39be266 commit 79219bd
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 51 deletions.
74 changes: 30 additions & 44 deletions client/src/views/admin/Games.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<div class="p-3 h-100">
<b-row class="h-100 m-0">
<!-- games -->
<b-col :cols="showPlayers ? '7' : '12'" class="mh-100 p-2">
<b-col :cols="inspectedGame ? '7' : '12'" class="mh-100 p-2">
<div>
<h4 class="header-nowrap">Games</h4>
<div id="filter-options" class="p-2">
Expand Down Expand Up @@ -105,11 +105,8 @@
variant="light"
size="sm"
class="float-right"
:disabled="isInspectedGame(data.item.id)"
@click="
players = data.item.players;
inspectedHighScore = data.item.highScore;
"
:disabled="data.item.id === inspectedGame?.id"
@click="inspectedGame = data.item"
>Scoreboard
<b-icon-box-arrow-right class="float-right ml-2"></b-icon-box-arrow-right>
</b-button>
Expand All @@ -118,8 +115,8 @@
</div>
</b-col>
<!-- players -->
<b-col v-if="showPlayers" cols="5" class="mh-100 p-2">
<h4 class="header-nowrap">Game #{{ players[0].gameId }} Scoreboard</h4>
<b-col v-if="inspectedGame" cols="5" class="mh-100 p-2">
<h4 class="header-nowrap">Game #{{ inspectedGame.players[0].gameId }} Scoreboard</h4>
<div class="h-100-header w-100 content-container">
<b-table
dark
Expand All @@ -128,7 +125,7 @@
style="max-height: none"
:tbody-tr-attr="playerRowStyle"
:fields="playerFields"
:items="players"
:items="inspectedGame.players"
sort-by="points"
:sort-desc="true"
>
Expand All @@ -143,8 +140,8 @@
variant="success"
v-if="
isEligibleForPrize(data.item.user) &&
inspectedHighScore &&
data.item.points === inspectedHighScore
inspectedGame.highScore &&
data.item.points === inspectedGame.highScore
"
>winner</b-badge
>
Expand Down Expand Up @@ -177,12 +174,13 @@
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import { AdminAPI } from "@port-of-mars/client/api/admin/request";
import { AdminGameData, ClientSafeUser } from "@port-of-mars/shared/types";
@Component({})
export default class Games extends Vue {
api!: AdminAPI;
games: any = [];
games: AdminGameData[] = [];
gameFields = [
{ key: "id", label: "Game ID" },
{ key: "tournamentRound", label: "Tournament" },
Expand All @@ -192,7 +190,6 @@ export default class Games extends Vue {
{ key: "highScore", label: "High Score" },
{ key: "inspect", label: "" },
];
players: any = [];
playerFields = [
{ key: "username", label: "Username" },
{ key: "role", label: "Role" },
Expand All @@ -201,7 +198,7 @@ export default class Games extends Vue {
];
highestScore = 0;
inspectedHighScore = 0;
inspectedGame: AdminGameData | null = null;
datePickerFormat = { year: "2-digit", month: "2-digit", day: "2-digit" };
// default to last 14 days
startDate = new Date(new Date().setDate(new Date().getDate() - 14));
Expand All @@ -225,23 +222,12 @@ export default class Games extends Vue {
};
}
get showPlayers() {
return this.players.length > 0;
}
isInspectedGame(id: number) {
if (this.players.length === 0) {
return false;
}
return id === this.players[0].gameId;
getBotCount(players: AdminGameData["players"]) {
return players.filter(p => p.user.isSystemBot).length;
}
getBotCount(players: any) {
return players.filter((p: any) => p.user.isSystemBot).length;
}
getHumanCount(players: any) {
return players.filter((p: any) => !p.user.isSystemBot).length;
getHumanCount(players: AdminGameData["players"]) {
return players.filter(p => !p.user.isSystemBot).length;
}
playerRowStyle(item: any, type: any) {
Expand Down Expand Up @@ -277,26 +263,26 @@ export default class Games extends Vue {
}
findHighScores() {
// find the highest eligible (player is human, has email and name) score for each game
// find the highest eligible (player is human, has email) score for each game
this.highestScore = 0;
this.games.forEach((game: any) => {
game.highScore = 0;
game.players.forEach((player: any) => {
if (this.isEligibleForPrize(player.user)) {
console.log("elligble");
if (player.points > game.highScore) {
game.highScore = player.points;
this.games
.filter((game: AdminGameData) => game.status === "victory")
.forEach((game: AdminGameData) => {
game.players.forEach((player: any) => {
if (this.isEligibleForPrize(player.user)) {
if (player.points > (game.highScore ?? 0)) {
game.highScore = player.points;
}
}
if ((game.highScore ?? 0) > this.highestScore) {
this.highestScore = game.highScore ?? 0;
}
}
if (game.highScore > this.highestScore) {
this.highestScore = game.highScore;
}
});
});
});
}
isEligibleForPrize(user: any) {
return !user.isSystemBot && user.email && user.name;
isEligibleForPrize(user: ClientSafeUser) {
return !user.isSystemBot && user.email;
}
}
</script>
Expand Down
4 changes: 2 additions & 2 deletions server/src/entity/Game.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GameType } from "@port-of-mars/shared/types";
import { GameStatus, GameType } from "@port-of-mars/shared/types";
import {
Column,
CreateDateColumn,
Expand Down Expand Up @@ -48,7 +48,7 @@ export class Game {
players!: Array<Player>;

@Column({ default: "incomplete" })
status: "incomplete" | "defeat" | "victory" | "failure" = "incomplete";
status: GameStatus = "incomplete";

@OneToOne(type => Player, { nullable: true })
@JoinColumn()
Expand Down
10 changes: 8 additions & 2 deletions server/src/services/game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ export class GameService extends BaseService {
}

async getTotalCompletedGames(
status: GameStatus | Array<GameStatus> = [{ status: "victory" }, { status: "defeat" }]
status: { status: GameStatus } | Array<{ status: GameStatus }> = [
{ status: "victory" },
{ status: "defeat" },
]
): Promise<number> {
return await this.em.getRepository(Game).count({
where: status,
Expand Down Expand Up @@ -56,7 +59,10 @@ export class GameService extends BaseService {
}

async getTotalGamesWithBots(
status: GameStatus | Array<GameStatus> = [{ status: "victory" }, { status: "defeat" }]
status: { status: GameStatus } | Array<{ status: GameStatus }> = [
{ status: "victory" },
{ status: "defeat" },
]
): Promise<number> {
return this.em
.getRepository(Game)
Expand Down
29 changes: 26 additions & 3 deletions shared/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@ export const MODERATION_ACTION_TYPES = [MUTE, BAN, NONE];

export interface ClientSafeUser {
id: number;
email?: string;
name?: string;
username: string;
isAdmin: boolean;
isMuted: boolean;
isBanned: boolean;
passedQuiz?: boolean;
isVerified?: boolean;
isSystemBot?: boolean;
dateConsented?: Date;
participantId?: string;
}
Expand Down Expand Up @@ -120,6 +123,28 @@ export interface ModerationActionClientData {
dateMuteExpires?: Date;
}

export interface AdminGameData {
id: string;
status: GameStatus;
type: GameType;
roomId: string;
buildId: string;
dateCreated: string;
dateFinalized: string;
tournamentRoundId: number;
treatmentId?: number;
highScore?: number;
players: Array<{
id: number;
role: Role;
userId: number;
playerIp: string;
gameId: number;
points: number;
user: ClientSafeUser;
}>;
}

export interface MarsLogData {
category: string;
message: string;
Expand Down Expand Up @@ -417,9 +442,7 @@ export interface SoloPlayerStatItem {
maxRound: number;
}

export interface GameStatus {
status: "incomplete" | "defeat" | "victory" | "failure" | "incomplete";
}
export type GameStatus = "incomplete" | "defeat" | "victory" | "failure" | "incomplete";

export interface InspectData {
players: Array<{ username: string; role: string; isBot: boolean; points: number }>;
Expand Down

0 comments on commit 79219bd

Please sign in to comment.