Skip to content
Snippets Groups Projects
Commit 0876bd10 authored by Haakon Gunleiksrud's avatar Haakon Gunleiksrud
Browse files

Merge branch 'leaderboards' of...

Merge branch 'leaderboards' of https://gitlab.stud.idi.ntnu.no/tmwang/tdt4242-base into leaderboards
parents 5a2bb024 78845177
No related branches found
No related tags found
3 merge requests!5Ad ci/cs setup,!4Dev,!1Leaderboards
......@@ -28,7 +28,7 @@ urlpatterns = format_suffix_patterns(
name="exercise-instance-list",
),
path(
"api/leaderboards/",
"api/leaderboards/<int:pk>/",
views.Leaderboards.as_view(),
name="leaderboards",
),
......
......@@ -6,10 +6,11 @@ from rest_framework import permissions
from rest_framework.parsers import (
JSONParser,
)
import json
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse
from django.db.models import Q
from django.db.models import Q, Sum, F, IntegerField
from rest_framework import filters
from workouts.parsers import MultipartJsonParser
from workouts.permissions import (
......@@ -209,11 +210,6 @@ class ExerciseDetail(
permission_classes = [permissions.IsAuthenticated]
def get(self, request, *args, **kwargs):
print("heiheihei")
print(request.data)
print(request.query_params)
print(request.GET)
print(request.path)
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
......@@ -232,13 +228,41 @@ class Leaderboards(
generics.GenericAPIView,
):
permission_classes = [permissions.IsAuthenticated]
def get(self, request, *args, **kwargs):
path = request.path
exercise_id = path.split("/")[-1]
print(exercise_id)
#ExerciseInstance.objects.filter(Q(exercise__pk=1) & Q(workout__visibility='PU')).values('workout__owner__pk').annotate(amount=Sum(F("sets") * F("number"), output_field=IntegerField()))
path = self.request.path
e_id = path.split("/")[-2]
return {"hei":"Haakon"}
if self.request.user:
leaderboardNumbers = ExerciseInstance.objects.filter(Q(exercise__pk=e_id) & Q(workout__visibility='PU')).values('workout__owner__pk').annotate(amount=Sum(F("sets") * F("number"), output_field=IntegerField())).order_by('-amount')
leaderboardResult = []
# Iterates through the top 5 entries in the leaderboard and formats it correctly
for i in range(0, min(5, len(leaderboardNumbers))):
leaderboardResult.append({"name": User.objects.get(pk=leaderboardNumbers[i]['workout__owner__pk']).username, "value": leaderboardNumbers[i]['amount']})
# Applies the rank to the leaderboard entry; if two or more users have the score they get the same rank
if i > 0 and leaderboardNumbers[i-1]["amount"] == leaderboardNumbers[i]["amount"]:
leaderboardResult[i]["rank"] = leaderboardResult[i-1]["rank"]
else:
leaderboardResult[i]["rank"] = i+1
# Finds the user in the leaderboard list. If the user is not in the leaderboard list,
# the user is automatically given a score of 0 and the worst rank
currentLoggedInUser = self.request.user
for j in range(0, len(leaderboardNumbers)):
if leaderboardNumbers[j]['workout__owner__pk'] == currentLoggedInUser.pk:
leaderboardResult.append({"name": currentLoggedInUser.username, "value": leaderboardNumbers[j]["amount"], "rank": j+1})
break
else:
leaderboardResult.append({"name": currentLoggedInUser.username, "value": 0, "rank": len(leaderboardNumbers) + 1})
return Response(json.dumps(leaderboardResult))
class ExerciseInstanceList(
......
......@@ -4,196 +4,207 @@ let deleteButton;
let editButton;
let oldFormData;
function handleCancelButtonDuringEdit() {
setReadOnly(true, "#form-exercise");
okButton.className += " hide";
deleteButton.className += " hide";
cancelButton.className += " hide";
editButton.className = editButton.className.replace(" hide", "");
cancelButton.removeEventListener("click", handleCancelButtonDuringEdit);
let form = document.querySelector("#form-exercise");
if (oldFormData.has("name")) form.name.value = oldFormData.get("name");
if (oldFormData.has("description")) form.description.value = oldFormData.get("description");
if (oldFormData.has("unit")) form.unit.value = oldFormData.get("unit");
oldFormData.delete("name");
oldFormData.delete("description");
oldFormData.delete("unit");
setReadOnly(true, "#form-exercise");
okButton.className += " hide";
deleteButton.className += " hide";
cancelButton.className += " hide";
editButton.className = editButton.className.replace(" hide", "");
cancelButton.removeEventListener("click", handleCancelButtonDuringEdit);
let form = document.querySelector("#form-exercise");
if (oldFormData.has("name")) form.name.value = oldFormData.get("name");
if (oldFormData.has("description"))
form.description.value = oldFormData.get("description");
if (oldFormData.has("unit")) form.unit.value = oldFormData.get("unit");
oldFormData.delete("name");
oldFormData.delete("description");
oldFormData.delete("unit");
}
function handleCancelButtonDuringCreate() {
window.location.replace("exercises.html");
window.location.replace("exercises.html");
}
async function createExercise() {
let form = document.querySelector("#form-exercise");
let formData = new FormData(form);
let body = {"name": formData.get("name"),
"description": formData.get("description"),
"unit": formData.get("unit")};
let response = await sendRequest("POST", `${HOST}/api/exercises/`, body);
if (response.ok) {
window.location.replace("exercises.html");
} else {
let data = await response.json();
let alert = createAlert("Could not create new exercise!", data);
document.body.prepend(alert);
}
let form = document.querySelector("#form-exercise");
let formData = new FormData(form);
let body = {
name: formData.get("name"),
description: formData.get("description"),
unit: formData.get("unit"),
};
let response = await sendRequest("POST", `${HOST}/api/exercises/`, body);
if (response.ok) {
window.location.replace("exercises.html");
} else {
let data = await response.json();
let alert = createAlert("Could not create new exercise!", data);
document.body.prepend(alert);
}
}
function handleEditExerciseButtonClick() {
setReadOnly(false, "#form-exercise");
setReadOnly(false, "#form-exercise");
editButton.className += " hide";
okButton.className = okButton.className.replace(" hide", "");
cancelButton.className = cancelButton.className.replace(" hide", "");
deleteButton.className = deleteButton.className.replace(" hide", "");
editButton.className += " hide";
okButton.className = okButton.className.replace(" hide", "");
cancelButton.className = cancelButton.className.replace(" hide", "");
deleteButton.className = deleteButton.className.replace(" hide", "");
cancelButton.addEventListener("click", handleCancelButtonDuringEdit);
cancelButton.addEventListener("click", handleCancelButtonDuringEdit);
let form = document.querySelector("#form-exercise");
oldFormData = new FormData(form);
let form = document.querySelector("#form-exercise");
oldFormData = new FormData(form);
}
async function deleteExercise(id) {
let response = await sendRequest("DELETE", `${HOST}/api/exercises/${id}/`);
if (!response.ok) {
let data = await response.json();
let alert = createAlert(`Could not delete exercise ${id}`, data);
document.body.prepend(alert);
} else {
window.location.replace("exercises.html");
}
let response = await sendRequest("DELETE", `${HOST}/api/exercises/${id}/`);
if (!response.ok) {
let data = await response.json();
let alert = createAlert(`Could not delete exercise ${id}`, data);
document.body.prepend(alert);
} else {
window.location.replace("exercises.html");
}
}
async function retrieveExercise(id) {
let response = await sendRequest("GET", `${HOST}/api/exercises/${id}/`);
console.log(response.ok);
if (!response.ok) {
let data = await response.json();
let alert = createAlert("Could not retrieve exercise data!", data);
document.body.prepend(alert);
} else {
let exerciseData = await response.json();
let form = document.querySelector("#form-exercise");
let formData = new FormData(form);
for (let key of formData.keys()) {
let selector = `input[name="${key}"], textarea[name="${key}"]`;
let input = form.querySelector(selector);
let newVal = exerciseData[key];
input.value = newVal;
}
let response = await sendRequest("GET", `${HOST}/api/exercises/${id}/`);
console.log(response.ok);
if (!response.ok) {
let data = await response.json();
let alert = createAlert("Could not retrieve exercise data!", data);
document.body.prepend(alert);
} else {
let exerciseData = await response.json();
let form = document.querySelector("#form-exercise");
let formData = new FormData(form);
for (let key of formData.keys()) {
let selector = `input[name="${key}"], textarea[name="${key}"]`;
let input = form.querySelector(selector);
let newVal = exerciseData[key];
input.value = newVal;
}
}
}
async function updateExercise(id) {
let form = document.querySelector("#form-exercise");
let formData = new FormData(form);
let body = {"name": formData.get("name"),
"description": formData.get("description"),
"unit": formData.get("unit")};
let response = await sendRequest("PUT", `${HOST}/api/exercises/${id}/`, body);
if (!response.ok) {
let data = await response.json();
let alert = createAlert(`Could not update exercise ${id}`, data);
document.body.prepend(alert);
} else {
// duplicate code from handleCancelButtonDuringEdit
// you should refactor this
setReadOnly(true, "#form-exercise");
okButton.className += " hide";
deleteButton.className += " hide";
cancelButton.className += " hide";
editButton.className = editButton.className.replace(" hide", "");
cancelButton.removeEventListener("click", handleCancelButtonDuringEdit);
oldFormData.delete("name");
oldFormData.delete("description");
oldFormData.delete("unit");
}
let form = document.querySelector("#form-exercise");
let formData = new FormData(form);
let body = {
name: formData.get("name"),
description: formData.get("description"),
unit: formData.get("unit"),
};
let response = await sendRequest("PUT", `${HOST}/api/exercises/${id}/`, body);
if (!response.ok) {
let data = await response.json();
let alert = createAlert(`Could not update exercise ${id}`, data);
document.body.prepend(alert);
} else {
// duplicate code from handleCancelButtonDuringEdit
// you should refactor this
setReadOnly(true, "#form-exercise");
okButton.className += " hide";
deleteButton.className += " hide";
cancelButton.className += " hide";
editButton.className = editButton.className.replace(" hide", "");
cancelButton.removeEventListener("click", handleCancelButtonDuringEdit);
oldFormData.delete("name");
oldFormData.delete("description");
oldFormData.delete("unit");
}
}
async function fetchLeaderBoards() {
//let response = await sendRequest("GET", `${HOST}/api/leaderboards/${id}`);
//Placeholder response and status:
let response = [{"name": "Mark", "value": 301, "rank": 1},
{"name": "Anton", "value": 245, "rank": 2},
{"name": "John", "value": 112, "rank": 3},
{"name": "Joe", "value": 84, "rank": 4},
{"name": "Larry", "value": 80, "rank": 5},
{"name": "Glaum", "value": 1, "rank": 85}];
response.ok = true;
if (response.ok) {
let table = document.getElementById("leaderboardstable");
let row, cell;
//The users own score will always be placed last in the JSON response
let userIndex = response.length - 1;
for (let i = 0; i < response.length-1; i++) {
row = table.insertRow();
cell = row.insertCell();
cell.textContent = response[i].rank;
cell = row.insertCell();
cell.textContent = response[i].name;
cell = row.insertCell();
cell.textContent = response[i].value;
}
//If the user is not in top 5, the users score will also be rendered
if(response[userIndex].rank > 5){
row = table.insertRow();
cell = row.insertCell();
cell.textContent = response[userIndex].rank;
cell = row.insertCell();
cell.textContent = response[userIndex].name;
cell = row.insertCell();
cell.textContent = response[userIndex].value;
}
let response = await sendRequest("GET", `${HOST}/api/leaderboards/${id}/`);
console.log(response.ok);
//Placeholder response and status:
let response = [
{ name: "Mark", value: 301, rank: 1 },
{ name: "Anton", value: 245, rank: 2 },
{ name: "John", value: 112, rank: 3 },
{ name: "Joe", value: 84, rank: 4 },
{ name: "Larry", value: 80, rank: 5 },
{ name: "Glaum", value: 1, rank: 85 },
];
response.ok = true;
if (response.ok) {
let table = document.getElementById("leaderboardstable");
let row, cell;
//The users own score will always be placed last in the JSON response
let userIndex = response.length - 1;
for (let i = 0; i < response.length - 1; i++) {
row = table.insertRow();
cell = row.insertCell();
cell.textContent = response[i].rank;
cell = row.insertCell();
cell.textContent = response[i].name;
cell = row.insertCell();
cell.textContent = response[i].value;
}
//If the user is not in top 5, the users score will also be rendered
if (response[userIndex].rank > 5) {
row = table.insertRow();
cell = row.insertCell();
cell.textContent = response[userIndex].rank;
cell = row.insertCell();
cell.textContent = response[userIndex].name;
cell = row.insertCell();
cell.textContent = response[userIndex].value;
}
}
return response;
return response;
}
window.addEventListener("DOMContentLoaded", async () => {
cancelButton = document.querySelector("#btn-cancel-exercise");
okButton = document.querySelector("#btn-ok-exercise");
deleteButton = document.querySelector("#btn-delete-exercise");
editButton = document.querySelector("#btn-edit-exercise");
oldFormData = null;
const urlParams = new URLSearchParams(window.location.search);
// view/edit
if (urlParams.has('id')) {
const exerciseId = urlParams.get('id');
await retrieveExercise(exerciseId);
editButton.addEventListener("click", handleEditExerciseButtonClick);
deleteButton.addEventListener("click", (async (id) => await deleteExercise(id)).bind(undefined, exerciseId));
okButton.addEventListener("click", (async (id) => await updateExercise(id)).bind(undefined, exerciseId));
}
//create
else {
setReadOnly(false, "#form-exercise");
editButton.className += " hide";
okButton.className = okButton.className.replace(" hide", "");
cancelButton.className = cancelButton.className.replace(" hide", "");
okButton.addEventListener("click", async () => await createExercise());
cancelButton.addEventListener("click", handleCancelButtonDuringCreate);
}
cancelButton = document.querySelector("#btn-cancel-exercise");
okButton = document.querySelector("#btn-ok-exercise");
deleteButton = document.querySelector("#btn-delete-exercise");
editButton = document.querySelector("#btn-edit-exercise");
oldFormData = null;
const urlParams = new URLSearchParams(window.location.search);
// view/edit
if (urlParams.has("id")) {
const exerciseId = urlParams.get("id");
await retrieveExercise(exerciseId);
editButton.addEventListener("click", handleEditExerciseButtonClick);
deleteButton.addEventListener(
"click",
(async (id) => await deleteExercise(id)).bind(undefined, exerciseId)
);
okButton.addEventListener(
"click",
(async (id) => await updateExercise(id)).bind(undefined, exerciseId)
);
}
//create
else {
setReadOnly(false, "#form-exercise");
editButton.className += " hide";
okButton.className = okButton.className.replace(" hide", "");
cancelButton.className = cancelButton.className.replace(" hide", "");
okButton.addEventListener("click", async () => await createExercise());
cancelButton.addEventListener("click", handleCancelButtonDuringCreate);
}
await fetchLeaderBoards();
});
\ No newline at end of file
await fetchLeaderBoards();
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment