From 8c8847cdd8f1eaee12a9c074d4cfca6c9f0d80c6 Mon Sep 17 00:00:00 2001 From: AdrienLSH Date: Mon, 22 Apr 2024 18:05:09 +0200 Subject: [PATCH 1/2] profiles: friend and block through profile page :)) --- frontend/static/js/api/MyProfile.js | 50 ++++- frontend/static/js/api/Profile.js | 13 +- frontend/static/js/api/Profiles.js | 34 --- frontend/static/js/views/ProfilePageView.js | 217 ++++++++++---------- profiles/views/friends.py | 8 +- 5 files changed, 175 insertions(+), 147 deletions(-) diff --git a/frontend/static/js/api/MyProfile.js b/frontend/static/js/api/MyProfile.js index 549f116..ef2e694 100644 --- a/frontend/static/js/api/MyProfile.js +++ b/frontend/static/js/api/MyProfile.js @@ -18,7 +18,7 @@ class MyProfile extends Profile /** * @type {[Profile]} */ - this.friends = []; + this.friendList = []; /** * @type {[Profile]} */ @@ -46,7 +46,7 @@ class MyProfile extends Profile async getFriends() { const response = await this.client._get('/api/profiles/friends'); const data = await response.json(); - data.forEach(profileData => this.friends.push(new Profile(this.client, profileData.username, profileData.user_id, profileData.avatar))); + data.forEach(profileData => this.friendList.push(new Profile(this.client, profileData.username, profileData.user_id, profileData.avatar))); } async getIncomingFriendRequests() { const response = await this.client._get('/api/profiles/incoming_friend_requests'); @@ -62,6 +62,52 @@ class MyProfile extends Profile new Profile(this.client, profileData.username, profileData.user_id, profileData.avatar) )); } + + /** + * @param {Profile} profile + * @returns {Boolean} + */ + _isFriend(profile) { + for (const user of this.friendList) { + if (user.id === profile.id) + return true; + } + return false; + } + /** + * @param {Profile} profile + * @returns {Boolean} + */ + _isBlocked(profile) { + for (const user of this.blockedUsers) { + if (user.id === profile.id) + return true; + } + return false; + } + /** + * @param {Profile} profile + * @returns {Boolean} + */ + _hasIncomingRequestFrom(profile) { + for (const user of this.incomingFriendRequests) { + if (user.id === profile.id) + return true; + } + return false; + } + /** + * @param {Profile} profile + * @returns {Boolean} + */ + _hasOutgoingRequestTo(profile) { + for (const user of this.outgoingFriendRequests) { + if (user.id === profile.id) + return true; + } + return false; + } + /** * * @param {File} selectedFile diff --git a/frontend/static/js/api/Profile.js b/frontend/static/js/api/Profile.js index bd38d9f..feb9570 100644 --- a/frontend/static/js/api/Profile.js +++ b/frontend/static/js/api/Profile.js @@ -33,8 +33,10 @@ export class Profile extends AExchangeable /** * @type {Boolean} */ - this.isBlocked = false; - this.isFriend = false; + this.isFriend; + this.isBlocked; + this.hasIncomingRequest; + this.hasOutgoingRequest; } /** @@ -57,6 +59,13 @@ export class Profile extends AExchangeable this.username = response_data.username; this.avatar = response_data.avatar; + if (!this.client.me || this.client.me.id === this.id) + return; + + this.isFriend = this.client.me._isFriend(this); + this.isBlocked = this.client.me._isBlocked(this); + this.hasIncomingRequest = this.client.me._hasIncomingRequestFrom(this); + this.hasOutgoingRequest = this.client.me._hasOutgoingRequestTo(this); } /** diff --git a/frontend/static/js/api/Profiles.js b/frontend/static/js/api/Profiles.js index 7c0de7e..796abc7 100644 --- a/frontend/static/js/api/Profiles.js +++ b/frontend/static/js/api/Profiles.js @@ -54,40 +54,6 @@ class Profiles return null; return profile; } - - /** - * Block a user - * @param {Number} user_id - * @returns {Promise} - */ - async block(user_id) { - - // blocker & blocked - let response = await this.client._post("/api/profiles/block", { - users_id:[this.client.me.id, user_id], - }); - - let data = await response.json(); - return data; - - } - - /** - * Unblock a user - * @param {Number} user_id - * @returns {Promise} - */ - async deblock(user_id) { - - // blocker & blocked - let response = await this.client._delete("/api/profiles/block", { - users_id:[this.client.me.id, user_id], - }); - - let data = await response.json(); - return data; - - } } export {Profiles}; diff --git a/frontend/static/js/views/ProfilePageView.js b/frontend/static/js/views/ProfilePageView.js index 930e206..8b27e81 100644 --- a/frontend/static/js/views/ProfilePageView.js +++ b/frontend/static/js/views/ProfilePageView.js @@ -8,7 +8,7 @@ export default class extends AbstractView { } setTitle() { - document.title = `${this.username} - Profile`; + document.title = this.titleKey; } async postInit() @@ -16,100 +16,32 @@ export default class extends AbstractView { if (!this.profile) return 404; - this.userId = this.profile.id; + const addFriendButton = document.getElementById('addFriendButton'), + removeFriendButton = document.getElementById('removeFriendButton'), + blockButton = document.getElementById('blockButton'), + unblockButton = document.getElementById('unblockButton'); - await this.blockButton(); - await this.friendButton(); + if (this.profile.hasIncomingRequest) { + addFriendButton.classList.remove('d-none'); + addFriendButton.innerHTML = 'Accept Request'; + } else if (this.profile.hasOutgoingRequest) { + removeFriendButton.classList.remove('d-none'); + removeFriendButton.classList.replace('btn-danger', 'btn-secondary'); + removeFriendButton.innerHTML = 'Cancel Request' + } else if (this.profile.isFriend) + removeFriendButton.classList.remove('d-none'); + else + addFriendButton.classList.remove('d-none'); - client.notice.rewrite_profile = async () => { - await this.profile.getFriend(); - await this.profile.getBlock(); - await this.friendButton(); - }; - } + if (this.profile.isBlocked) + unblockButton.classList.remove('d-none'); + else + blockButton.classList.remove('d-none'); - async blockButton() { - // Block option - if (await client.isAuthenticated() === false) - return; - - if (client.me.id != this.userId) { - let block = document.getElementById("block"); - if (block == undefined) { - block = document.createElement("p"); - // this.info.appendChild(block); - } - - block.id = "block"; - block.onclick = async () => { - if (!this.profile.isBlocked) - await client.profiles.block(this.userId); - else - await client.profiles.deblock(this.userId); - this.profile = await client.profiles.getProfile(this.username); - - this.blockButton(); - }; - if (this.profile.isBlocked) - block.textContent = lang.get('profileUnblock', 'Unblock'); - else - block.textContent = lang.get('profileBlock', 'Block'); - } - } - - async friendButton() { - if (await client.isAuthenticated() === false) - return; - - if (client.me.id != this.userId) { - let yes = document.getElementById("yes") || document.createElement("p"); - let no = document.getElementById("no") || document.createElement("p"); - let friend = document.getElementById("friend") || document.createElement("p"); - - if (client.notice.data.asker.includes(this.userId)) { - - if (friend) - friend.remove(); - - yes.id = "yes"; - yes.textContent = lang.get('profileAcceptRequest', 'Accept Friend'); - yes.onclick = async () => { - client.notice.accept_friend(this.userId); - }; - - no.id = "no"; - no.textContent = lang.get('profileDenyRequest', 'Decline Friend'); - no.onclick = async () => { - client.notice.refuse_friend(this.userId); - }; - - // this.info.appendChild(yes); - // this.info.appendChild(document.createTextNode(" ")); - // this.info.appendChild(no); - - } - else { - - if (yes && no) - yes.remove(); no.remove(); - - friend.id = "friend"; - friend.onclick = async () => { - if (this.profile.isFriend) - await client.notice.remove_friend(this.userId); - else - await client.notice.ask_friend(this.userId); - await client.profiles.getProfile(this.username); - this.friendButton(); - }; - if (this.profile.isFriend) - friend.textContent = lang.get('profileRemoveFriend', 'Remove Friend'); - else { - friend.textContent = lang.get('profileAddFriend', 'Ask Friend'); - } - // this.info.appendChild(friend); - } - } + addFriendButton.onclick = _ => this.addFriend(); + removeFriendButton.onclick = _ => this.removeFriend(); + unblockButton.onclick = _ => this.unblockUser(); + blockButton.onclick = _ => this.blockUser(); } async getHtml() { @@ -118,19 +50,94 @@ export default class extends AbstractView { if (!this.profile) return ''; - const logged = await client.isAuthenticated(); - return ` -
-

${this.username}

- - - -
-
- - -
- `; +
+
+

${this.username}

+ + + +
+
+ + + + +
+
+ `; + } + + async addFriend() { + const removeFriendButton = document.getElementById('removeFriendButton'); + + const response = await client._post(`/api/profiles/friends/${this.profile.id}`); + const body = await response.json(); + console.log(body); + + if (response.ok) { + removeFriendButton.classList.remove('d-none'); + document.getElementById('addFriendButton').classList.add('d-none'); + } + if (response.status === 200) { + removeFriendButton.innerHTML = 'Cancel Request'; + removeFriendButton.classList.replace('btn-danger', 'btn-secondary'); + client.me.outgoingFriendRequests.push(this.profile); + this.profile.hasOutgoingRequest = true; + } else if (response.status === 201) { + removeFriendButton.innerHTML = 'Remove Friend'; + removeFriendButton.classList.replace('btn-secondary', 'btn-danger'); + this.profile.friend = true; + this.profile.hasIncomingRequest = false; + client.me.incomingFriendRequests = client.me.incomingFriendRequests.filter(profile => profile.id !== this.profile.id); + client.me.friendList.push(this.profile); + } + } + + async removeFriend() { + const addFriendButton = document.getElementById('addFriendButton'); + + const response = await client._delete(`/api/profiles/friends/${this.profile.id}`); + const body = await response.json(); + console.log(body); + + if (response.ok) { + addFriendButton.innerHTML = 'Add Friend'; + addFriendButton.classList.remove('d-none'); + document.getElementById('removeFriendButton').classList.add('d-none'); + } + if (response.status === 200) { + this.profile.hasOutgoingRequest = false; + client.me.outgoingFriendRequests = client.me.outgoingFriendRequests.filter(profile => profile.id !== this.profile.id); + } else if (response.status === 201) { + this.profile.isFriend = false; + client.me.friendList = client.me.friendList.client.me.incomingFriendRequests = filter(friend => friend.id !== this.profile.id); + } + } + + async blockUser() { + const response = await client._post(`/api/profiles/block/${this.profile.id}`); + const body = await response.json(); + console.log(body); + + if (response.ok) { + document.getElementById('blockButton').classList.add('d-none'); + document.getElementById('unblockButton').classList.remove('d-none'); + client.me.blockedUsers.push(this.profile); + this.profile.isBlocked = true; + } + } + + async unblockUser() { + const response = await client._delete(`/api/profiles/block/${this.profile.id}`); + const body = await response.json(); + console.log(body); + + if (response.ok) { + document.getElementById('unblockButton').classList.add('d-none'); + document.getElementById('blockButton').classList.remove('d-none'); + client.me.blockedUsers = client.me.blockedUsers.filter(profile => profile.id !== this.profile.id); + this.profile.isBlocked = false; + } } } diff --git a/profiles/views/friends.py b/profiles/views/friends.py index 00d76b3..125b061 100644 --- a/profiles/views/friends.py +++ b/profiles/views/friends.py @@ -50,16 +50,16 @@ class EditFriendView(APIView): user_profile = self.get_object() friend_profile = get_object_or_404(ProfileModel, pk=pk) - if not user_profile.is_friend(friend_profile): - return Response(_('You are not friend with this user.'), status.HTTP_400_BAD_REQUEST) - outgoing_request = user_profile.get_outgoing_friend_request_to(friend_profile) if outgoing_request: outgoing_request.delete() return Response(_('Friend request cancelled.')) + if not user_profile.is_friend(friend_profile): + return Response(_('You are not friend with this user.'), status.HTTP_400_BAD_REQUEST) + user_profile.delete_friend(friend_profile) - return Response(_('Friendship succssfully deleted.')) + return Response(_('Friendship succssfully deleted.'), status.HTTP_201_CREATED) class GetIncomingFriendRequestView(APIView): From 91cdc969721225355875861858c40c99f78d497a Mon Sep 17 00:00:00 2001 From: Namonay Date: Mon, 22 Apr 2024 19:13:08 +0200 Subject: [PATCH 2/2] morpion: add: Frontend checks, QOL changes and winning conditions --- .../js/api/game/tictactoe/TicTacToeGame.js | 105 +++++++++--------- .../static/js/sound/tictactoe/play-move.mp3 | Bin 0 -> 5224 bytes .../static/js/views/TicTacToeOnlineView.js | 1 - games/consumers.py | 9 +- games/objects/tictactoe/TicTacToeGame.py | 19 ++-- 5 files changed, 75 insertions(+), 59 deletions(-) create mode 100644 frontend/static/js/sound/tictactoe/play-move.mp3 diff --git a/frontend/static/js/api/game/tictactoe/TicTacToeGame.js b/frontend/static/js/api/game/tictactoe/TicTacToeGame.js index 73b5a56..49d6d18 100644 --- a/frontend/static/js/api/game/tictactoe/TicTacToeGame.js +++ b/frontend/static/js/api/game/tictactoe/TicTacToeGame.js @@ -18,12 +18,12 @@ class TicTacToe this.canvas = canvas this.context = this.canvas.getContext("2d"); this.sign; + this.currentMorpion = 4; this.turn; } async init() { - console.log(this.game_id); await this.game.join(); this.canvas.addEventListener("mousedown", (event, morpion = this) => this.onClick(event, morpion)); } @@ -37,22 +37,46 @@ class TicTacToe async onReceive(messageData) { console.log(messageData) - if (messageData.detail == "x" || messageData.detail == "o") + switch (messageData.detail) { - this.sign = messageData.detail; - this.turn = messageData.detail == "x"; - } - else if (messageData.detail == "game_start") - this.game.started = true; - else if (messageData.targetMorpion && messageData.targetCase) - { - this.map[messageData.targetMorpion][messageData.targetCase] = (this.sign == "x") ? 1 : 0; - this.printSign(messageData.targetMorpion, messageData.targetCase, (this.sign == "x") ? "o" : "x"); - if (this.checkWin() != -1) - printWin(); + case 'x': + case 'o': + this.sign = messageData.detail; + this.turn = messageData.detail == "x"; + if (this.turn) + this.setOutline(4, false); + break; + + case 'game_start': + this.game.started = true; + this.game.finished = false; + break; + + case 'game_move': + this.map[messageData.targetMorpion][messageData.targetCase] = (this.sign == "x") ? 1 : 0; + this.printSign(messageData.targetMorpion, messageData.targetCase, (this.sign == "x") ? "o" : "x"); + this.setOutline(this.currentMorpion, false); + break; + + case 'game_end': + this.game.finished = true; + this.canvas.removeEventListener("mousedown", (event, morpion = this) => this.onClick(event, morpion)); + this.printWin(messageData.winning_sign); + break; } } + printWin(winning_sign) + { + this.context.beginPath(); + this.context.fillStyle = "white"; + this.context.fillRect(this.width / 2 - 200, this.height - this.gap + 10, 400, 80); + this.context.closePath(); + this.context.beginPath(); + this.context.fillStyle = (winning_sign == "o") ? "red" : "green"; + this.context.fillText((winning_sign == "o") ? "Winner is : O" : "Winner is : X", this.width / 2 - 30, this.height - this.gap / 2, 140); + this.context.closePath(); + } checkWin() { for (let i = 0; i < 9; i++) @@ -85,6 +109,10 @@ class TicTacToe let y = event.offsetY; let targetMorpion, targetCase; + if (this.game.finished) + { + return; + } targetMorpion = morpion.findPlace(x, this) + morpion.findPlace(y, this) * 3; if (morpion.findPlace(x, this) < 0 || morpion.findPlace(y, this) < 0) return -1; @@ -92,8 +120,8 @@ class TicTacToe if (morpion.checkCase(targetMorpion, targetCase)) { + morpion.setOutline(this.currentMorpion, true); morpion.sendCase(targetMorpion, targetCase); - morpion.setOutline(); } else morpion.incorrectCase(); @@ -101,19 +129,20 @@ class TicTacToe checkCase(targetMorpion, targetCase) { - return (this.map[targetMorpion][targetCase] == -1 && this.turn == true); + return (this.map[targetMorpion][targetCase] == -1 && this.turn == true && targetMorpion == this.currentMorpion); } incorrectCase() { - console.log("bozo"); + } sendCase(targetMorpion, targetCase) { this.map[targetMorpion][targetCase] = (this.sign == "x") ? 0 : 1; + this.currentMorpion = targetCase; this.printSign(targetMorpion, targetCase, this.sign); - console.log(this.game.send, targetMorpion, targetCase) + console.log(targetMorpion, targetCase) this.game.send(JSON.stringify({"targetMorpion" : targetMorpion, "targetCase" : targetCase, "sign" : this.sign})); console.log(this.turn); this.turn = !this.turn; @@ -172,21 +201,25 @@ class TicTacToe return -1; } - setOutline() + setOutline(targetMorpion, clear) { - if (this.turn) + let targetX = (this.gap + targetMorpion % 3 * this.rectsize * 3); + let targetY = (this.gap + Math.floor(targetMorpion / 3) * this.rectsize * 3); + if (this.game.finished) + return; + if (!clear) { this.context.beginPath(); this.context.strokeStyle = (this.sign == "x") ? "green" : "red"; - this.context.roundRect(0, 0, this.canvas.width, this.canvas.height, 25); + this.context.rect(targetX, targetY, this.rectsize * 3, this.rectsize * 3) this.context.stroke(); this.context.closePath(); } else { this.context.beginPath(); - this.context.strokeStyle = "#1a1a1d"; - this.context.roundRect(0, 0, this.canvas.width, this.canvas.height, 25); + this.context.strokeStyle = `rgb(230 230 230)`; + this.context.rect(targetX, targetY, this.rectsize * 3, this.rectsize * 3) this.context.stroke(); this.context.closePath(); } @@ -244,34 +277,6 @@ class TicTacToe } this.context.closePath(); } - - selectCase(x, y) - { - case_morpion = Math.floor(x / this.rectsize) + Math.floor((y / this.rectsize)) * 3 - case_square = Math.floor(x / Math.floor(this.rectsize / 3)) % this.rectsize + Math.floor(y / this.rectsize) % this.rectsize - // ask server if case_morpion == playing_case && case_square == empty - - } - - setOutline() - { - if (this.turn) - { - this.context.beginPath(); - this.context.strokeStyle = (this.sign == "x") ? "green" : "red"; - this.context.roundRect(0, 0, this.canvas.width, this.canvas.height, 25); - this.context.stroke(); - this.context.closePath(); - } - else - { - this.context.beginPath(); - this.context.strokeStyle = "#1a1a1d"; - this.context.roundRect(0, 0, this.canvas.width, this.canvas.height, 25); - this.context.stroke(); - this.context.closePath(); - } - } } export { TicTacToe }; \ No newline at end of file diff --git a/frontend/static/js/sound/tictactoe/play-move.mp3 b/frontend/static/js/sound/tictactoe/play-move.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..1713db075b05221ed24cdd14b0024b31633016d8 GIT binary patch literal 5224 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 literal 0 HcmV?d00001 diff --git a/frontend/static/js/views/TicTacToeOnlineView.js b/frontend/static/js/views/TicTacToeOnlineView.js index 129e6a5..2379cd8 100644 --- a/frontend/static/js/views/TicTacToeOnlineView.js +++ b/frontend/static/js/views/TicTacToeOnlineView.js @@ -19,7 +19,6 @@ export class TicTacToeOnlineView extends AbstractView this.Morpion = new TicTacToe(this.height, this.width, 60, 60, document.getElementById("Morpion"), this.game_id); this.Morpion.DrawSuperMorpion(); await this.Morpion.init(); - this.Morpion.setOutline(); } async leavePage() diff --git a/games/consumers.py b/games/consumers.py index 4fd1094..825ffe5 100644 --- a/games/consumers.py +++ b/games/consumers.py @@ -45,6 +45,8 @@ class TicTacToeWebSocket(WebsocketConsumer): self.member.send(self.member.sign) if (self.game._everbody_is_here() and self.game.model.started == False): + if (self.game.time != -1): + self.game.broadcast("opponent_joined") self.game.broadcast("game_start") self.game.model.start() @@ -54,7 +56,12 @@ class TicTacToeWebSocket(WebsocketConsumer): if (data.get("targetMorpion") is not None and data.get("targetCase") is not None): if (self.game.add(data, self.member) == False): return - self.game.broadcast("", data, [self.member]) + if (data.get("catchup") is not None and self.game.model.finished == False and self.game.model.finished == True): + self.member.send("catchup", {"Morpion": self.game._map, "turn": self.game.turn}) + if (self.game.checkWin() != False): + print(self.game.checkWin()) + self.game.broadcast("game_end", {"winning_sign": self.member.sign}) + self.game.broadcast("game_move", data, [self.member]) pass def disconnect(self, event): diff --git a/games/objects/tictactoe/TicTacToeGame.py b/games/objects/tictactoe/TicTacToeGame.py index fe123e5..7befea5 100644 --- a/games/objects/tictactoe/TicTacToeGame.py +++ b/games/objects/tictactoe/TicTacToeGame.py @@ -18,6 +18,10 @@ class TicTacToeGame(AGame): self.players: list[TicTacToePlayer] = [TicTacToePlayer(player, None, self, ["x", "o"][i]) for i, player in enumerate(players)] + self.time = -1 + + self.turn = 'x' + self._map = [[-1 for _ in range(9)] for _ in range(9)] def _everbody_is_here(self): @@ -44,14 +48,15 @@ class TicTacToeGame(AGame): if (self.checkMove(newmove, player)): self._map[newmove.get("targetMorpion")][newmove.get("targetCase")] = newmove.get("sign") - player.currentMorpion = int(newmove.get("targetMorpion")) + player.currentMorpion = int(newmove.get("targetCase")) + self.turn = newmove.get("sign") return True return False def checkMove(self, newmove, player): print(int(newmove.get("targetMorpion")), player.currentMorpion) - if (int(newmove.get("targetMorpion")) != player.currentMorpion): + if (int(newmove.get("targetMorpion")) != player.currentMorpion or newmove.get("sign") != self.turn): return False if (self._map[newmove.get("targetMorpion")][newmove.get("targetCase")] != -1): @@ -62,16 +67,16 @@ class TicTacToeGame(AGame): def checkWin(self): for tab in self._map: for i in range(3): - if tab[i] == tab[i + 3] == tab[i + 6]: + if tab[i] != -1 and tab[i] == tab[i + 3] and tab[i + 3] == tab[i + 6]: return tab[i] for i in range(0, 9, 3): - if tab[i] == tab[i + 1] == tab[i + 2]: + if tab[i] != -1 and tab[i] == tab[i + 1] and tab[i + 1] == tab[i + 2]: return tab[i] - if tab[0] == tab[4] == tab[8]: + if tab[0] != -1 and tab[0] == tab[4] and tab[4] == tab[8]: return tab[0] - if tab[6] == tab[4] == tab[2]: + if tab[6] != -1 and tab[6] == tab[4] and tab[4] == tab[2]: return tab[6] - return None + return False def _spectator_join(self, user_id: int, socket: WebsocketConsumer):