Skip to content

Commit

Permalink
Merge pull request #215 from ShotaTanemura/202-game-stats-in-profile
Browse files Browse the repository at this point in the history
プロフィールに試合の勝敗結果を表示。
  • Loading branch information
libknt authored Oct 20, 2024
2 parents b247aa3 + 8ecd7f8 commit 6766b08
Show file tree
Hide file tree
Showing 6 changed files with 219 additions and 37 deletions.
12 changes: 6 additions & 6 deletions pong/pong/static/pong/components/GameStats.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ export class GameStats extends Component {
this.element.parentElement.prepend(this.headerComponent.element);
this.headerComponent.afterPageLoaded();
this.createPongGameMatchResultTable(
await this.getMatchResultsData("/ponggame/api/v1/match-result/"),
await GameStats.getMatchResultsData("/ponggame/api/v1/match-result/"),
);
this.createTypingGameMatchResultTable(
await this.getMatchResultsData("/typinggame/api/v1/match-result/"),
await GameStats.getMatchResultsData("/typinggame/api/v1/match-result/"),
);
this.createReactionGameMatchResultTable(
await this.getMatchResultsData("/reactiongame/api/v1/match-result/"),
await GameStats.getMatchResultsData("/reactiongame/api/v1/match-result/"),
);
};

Expand All @@ -35,7 +35,7 @@ export class GameStats extends Component {
this.goNextPage("/");
};

getUserName = async () => {
static getUserName = async () => {
try {
const userUuid = await getUuid();
if (!userUuid) {
Expand All @@ -53,8 +53,8 @@ export class GameStats extends Component {
}
};

getMatchResultsData = async (apiEndpoint) => {
const userName = await this.getUserName();
static getMatchResultsData = async (apiEndpoint, user_name = null) => {
const userName = user_name || (await GameStats.getUserName());
if (!userName) {
return;
}
Expand Down
130 changes: 111 additions & 19 deletions pong/pong/static/pong/components/Profile.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { Component } from "../core/component.js";
import { Header } from "./Header.js";
import { getUuid, getUserFromUuid } from "../api/api.js";
import { GameStats } from "./GameStats.js";

export class Profile extends Component {
constructor(router, params, state) {
super(router, params, state);
this.loadUserProfile();
this.loadUserGameResults();
this.findElement("button.edit-profile-button").onclick = this.goEditProfile;
this.findElement("button.edit-2fa-button").onclick = this.goEdit2FA;
this.TYPINGGAME = "TypingGame";
this.PONGGAME = "PongGame";
this.REACTIONGAME = "ReactionGame"; // New constant for ReactionGame
}

afterPageLoaded() {
Expand All @@ -26,23 +31,98 @@ export class Profile extends Component {
if (!uuid) {
throw new Error("UUID not found");
}
const user = await getUserFromUuid(uuid);
if (!user) {
this.user = await getUserFromUuid(uuid);
if (!this.user) {
throw new Error("User not found");
}
this.updateProfileUI(user);
this.updateProfileUI();
} catch (error) {
console.error("Failed to load user profile:", error);
window.alert("Failed to load user profile");
this.router.goNextPage("/");
}
}

updateProfileUI(user) {
this.findElement("#username").textContent = user.name;
this.findElement("#email").textContent = user.email;
this.findElement("#user-icon").src = user.icon;
console.log(user.icon);
async loadUserGameResults() {
const pongGameResults = await GameStats.getMatchResultsData(
"/ponggame/api/v1/match-result/",
);
const typingGameResults = await GameStats.getMatchResultsData(
"/typinggame/api/v1/match-result/",
);
const reactionGameResults = await GameStats.getMatchResultsData(
"/reactiongame/api/v1/match-result/",
);

this.createGameMatchResultTable(pongGameResults, this.PONGGAME);
this.createGameMatchResultTable(typingGameResults, this.TYPINGGAME);
this.createGameMatchResultTable(reactionGameResults, this.REACTIONGAME);
}

createGameMatchResultTable = (matchResultData, gameType) => {
if (!matchResultData) {
return;
}

const tableElement = Object.assign(document.createElement("table"), {
className: "table",
});
const theadElement = document.createElement("thead");
const tbodyElement = document.createElement("tbody");

theadElement.innerHTML = `<tr>
<th scope="col">Win or Lose</th>
<th scope="col">Opponent</th>
</tr>`;

matchResultData.forEach((matchResult) => {
const trElement = document.createElement("tr");
let winOrLose;
let opponent;

if (gameType === this.PONGGAME) {
const winner =
matchResult.contents.player1_score >
matchResult.contents.player2_score
? matchResult.contents.player1
: matchResult.contents.player2;
winOrLose = winner === this.user.name ? "Win" : "Lose";
} else if (
gameType === this.TYPINGGAME ||
gameType === this.REACTIONGAME
) {
winOrLose =
matchResult.contents.winner === this.user.name ? "Win" : "Lose";
}
opponent =
matchResult.contents.player1 === this.user.name
? matchResult.contents.player2
: matchResult.contents.player1;

trElement.innerHTML = `
<td>${winOrLose}</td>
<td>${opponent}</td>
`;
tbodyElement.appendChild(trElement);
});

tableElement.appendChild(theadElement);
tableElement.appendChild(tbodyElement);

const tableContainer =
gameType === "PongGame"
? this.findElement("div.ponggame-result-table")
: gameType === "TypingGame"
? this.findElement("div.typinggame-result-table")
: this.findElement("div.reactiongame-result-table"); // Add ReactionGame results

tableContainer.appendChild(tableElement);
};

updateProfileUI() {
this.findElement("#username").textContent = this.user.name;
this.findElement("#email").textContent = this.user.email;
this.findElement("#user-icon").src = this.user.icon;
}

goEditProfile = () => {
Expand All @@ -55,17 +135,29 @@ export class Profile extends Component {

get html() {
return `
<div class="profile-card">
<h1>プロフィールページ</h1>
<img id="user-icon" height="256" width="256">
<br>
<br>
<p><strong>Username:</strong> <span id="username"></span></p>
<p><strong>E-mail:</strong> <span id="email"></span></p>
<br>
<button class="edit-profile-button">プロフィールを変更する</button>
<button class="edit-2fa-button">二要素認証の設定を変更する</button>
<div class="profile-card">
<h1>プロフィールページ</h1>
<img id="user-icon" height="256" width="256">
<br>
<br>
<p>Username: <span id="username"></span></p>
<p>E-mail: <span id="email"></span></p>
<br>
<h3>Last 10 Game Match Results</h3>
<div class="ponggame-result-table">
<strong>PongGame</strong>
</div>
<div class="typinggame-result-table">
<strong>TypingGame</strong>
</div>
<div class="reactiongame-result-table">
<strong>ReactionGame</strong>
</div>
`;
<button class="edit-profile-button">プロフィールを変更する</button>
<br>
<br>
<button class="edit-2fa-button">二要素認証の設定を変更する</button>
</div>
`;
}
}
110 changes: 101 additions & 9 deletions pong/pong/static/pong/components/UserProfile.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { Component } from "../core/component.js";
import { Header } from "./Header.js";
import { getUsersDataFromName } from "../api/api.js";
import { GameStats } from "./GameStats.js";

export class UserProfile extends Component {
constructor(router, params, state) {
super(router, params, state);
this.parameters = params;
if (this.parameters.user_name) {
this.loadUserProfile(this.parameters.user_name);
this.loadUserGameResults(this.parameters.user_name);
}
}

Expand All @@ -28,9 +30,9 @@ export class UserProfile extends Component {
this.element.parentElement.removeChild(this.headerComponent.element);
}

async loadUserProfile(user_name) {
async loadUserProfile(userName) {
try {
const users = await getUsersDataFromName(user_name);
const users = await getUsersDataFromName(userName);
if (!users) {
throw new Error("User not found");
}
Expand All @@ -44,20 +46,110 @@ export class UserProfile extends Component {
}
}

async loadUserGameResults(userName) {
const pongGameResults = await GameStats.getMatchResultsData(
`/ponggame/api/v1/match-result/`,
userName,
);
const typingGameResults = await GameStats.getMatchResultsData(
`/typinggame/api/v1/match-result/`,
userName,
);
const reactionGameResults = await GameStats.getMatchResultsData(
`/reactiongame/api/v1/match-result/`,
userName,
);

this.createGameMatchResultTable(pongGameResults, "PongGame", userName);
this.createGameMatchResultTable(typingGameResults, "TypingGame", userName);
this.createGameMatchResultTable(
reactionGameResults,
"ReactionGame",
userName,
);
}

createGameMatchResultTable = (matchResultData, gameType, userName) => {
if (!matchResultData) {
return;
}

const tableElement = Object.assign(document.createElement("table"), {
className: "table",
});
const theadElement = document.createElement("thead");
const tbodyElement = document.createElement("tbody");

theadElement.innerHTML = `<tr>
<th scope="col">Win or Lose</th>
<th scope="col">Opponent</th>
</tr>`;

matchResultData.forEach((matchResult) => {
const trElement = document.createElement("tr");
let winOrLose;
let opponent;

if (gameType === "PongGame") {
const winner =
matchResult.contents.player1_score >
matchResult.contents.player2_score
? matchResult.contents.player1
: matchResult.contents.player2;
winOrLose = winner === userName ? "Win" : "Lose";
} else if (gameType === "TypingGame" || gameType === "ReactionGame") {
winOrLose = matchResult.contents.winner === userName ? "Win" : "Lose";
}
opponent =
matchResult.contents.player1 === userName
? matchResult.contents.player2
: matchResult.contents.player1;

trElement.innerHTML = `
<td>${winOrLose}</td>
<td>${opponent}</td>
`;
tbodyElement.appendChild(trElement);
});

tableElement.appendChild(theadElement);
tableElement.appendChild(tbodyElement);

const tableContainer =
gameType === "PongGame"
? this.findElement("div.ponggame-result-table")
: gameType === "TypingGame"
? this.findElement("div.typinggame-result-table")
: this.findElement("div.reactiongame-result-table");

tableContainer.appendChild(tableElement);
};

updateProfileUI(user) {
this.findElement("#username").textContent = user.name;
this.findElement("#user-icon").src = user.icon;
}

get html() {
return `
<div class="profile-card">
<h1>プロフィールページ</h1>
<img id="user-icon">
<p><strong>Username:</strong> <span id="username"></span></p>
<br>
<button id="back-button">元のページに戻る</button>
<div class="profile-card">
<h1>プロフィールページ</h1>
<img id="user-icon">
<p>Username: <span id="username"></span></p>
<br>
<h3>Last 10 Game Match Results</h3>
<div class="ponggame-result-table">
<strong>PongGame</strong>
</div>
<div class="typinggame-result-table">
<strong>TypingGame</strong>
</div>
<div class="reactiongame-result-table">
<strong>ReactionGame</strong>
</div>
`;
<br>
<button id="back-button">元のページに戻る</button>
</div>
`;
}
}
1 change: 0 additions & 1 deletion pong/pong/static/pong/styles/home.styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ main.home .home-container {
min-width: 100%;
margin: auto;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
overflow: hidden;
border: solid 0.1px #ccc;
}

Expand Down
2 changes: 1 addition & 1 deletion pong/reaction_game/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ class GameRecord(models.Model):
timestamp = models.DateTimeField(auto_now_add=True)

def __str__(self):
return f"{self.user.username} vs {self.opponent.username} - Winner: {self.winner.username} at {self.timestamp}"
return f"{self.user.name} vs {self.opponent.name} - Winner: {self.winner.name} at {self.timestamp}"
1 change: 0 additions & 1 deletion pong/reaction_game/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ def get_user_match_result(request, name):
"-timestamp"
)[:10]

logger.info(user_last_10_match_results)
user_match_results = []

for index, user_match_result in enumerate(user_last_10_match_results):
Expand Down

0 comments on commit 6766b08

Please sign in to comment.