Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

プロフィールに試合の勝敗結果を表示。 #215

Merged
merged 26 commits into from
Oct 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b79f1ad
feat: そのユーザーの試合の勝敗を表示
subarunrun0812 Oct 19, 2024
e3dbc3a
init
libknt Oct 19, 2024
d9a3232
feat: 4人対戦のURLを生成可能に
libknt Oct 19, 2024
247c037
feat: chatからのponggame招待を2~4人で設定可能に
libknt Oct 19, 2024
f27cdda
add: 2人 or 4人でmessageの変更
libknt Oct 19, 2024
189becd
Merge remote-tracking branch 'origin/develop' into 202-game-stats-in-…
subarunrun0812 Oct 19, 2024
220165f
fix: refs #212 return when websocket is undefined.
massahito Oct 19, 2024
d1fdbe0
fix: refs #212 remove friend page console error.
massahito Oct 19, 2024
f7a1d6c
init
libknt Oct 19, 2024
3c0f27d
fix: sidebarのsttingの削除
libknt Oct 19, 2024
cbf0411
init
libknt Oct 19, 2024
b79e62a
fix: changePage
libknt Oct 19, 2024
5b1cae5
fix: changePageでpathが"/"の際に無視するように設定
libknt Oct 19, 2024
006329e
feat: 他のuserのprofileにGameStatsを表示
subarunrun0812 Oct 20, 2024
dbcd697
format
subarunrun0812 Oct 20, 2024
66a8300
Merge remote-tracking branch 'origin/develop' into 202-game-stats-in-…
subarunrun0812 Oct 20, 2024
da856fd
refactor 不要なコメントを削除
subarunrun0812 Oct 20, 2024
fd9bab8
Merge branch 'develop' into 202-game-stats-in-profile
subarunrun0812 Oct 20, 2024
b76d759
ADD: ProfileにReactionGame
subarunrun0812 Oct 20, 2024
af24ad6
format
subarunrun0812 Oct 20, 2024
19eb555
Merge branch 'develop' into 202-game-stats-in-profile
subarunrun0812 Oct 20, 2024
822c768
fix; loss->lose
subarunrun0812 Oct 20, 2024
ebb7860
fix; scrollできない
subarunrun0812 Oct 20, 2024
e3f9229
init
libknt Oct 20, 2024
d545805
fix
libknt Oct 20, 2024
8ecd7f8
Merge pull request #227 from ShotaTanemura/fix/reaction-game
libknt Oct 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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