From dc128a84543b3044a4ebb85804fb93cbef7a4374 Mon Sep 17 00:00:00 2001 From: Plumey Simon Date: Fri, 12 Apr 2024 13:17:09 +0200 Subject: [PATCH] Adding graph --- frontend/package-lock.json | 27 ++++++++++ frontend/package.json | 2 + frontend/src/api_client.js | 23 ++++---- frontend/src/components/AnswerForm.vue | 4 +- frontend/src/components/GraphSection.vue | 68 ++++++++++++++++++++++++ frontend/src/views/QuizView.vue | 12 ++++- 6 files changed, 125 insertions(+), 11 deletions(-) create mode 100644 frontend/src/components/GraphSection.vue diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 8e0c52d..7753a6d 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,7 +9,9 @@ "version": "0.0.0", "dependencies": { "axios": "^1.6.7", + "chart.js": "^4.4.2", "vue": "^3.4.15", + "vue-chartjs": "^5.3.1", "vue-router": "^4.2.5" }, "devDependencies": { @@ -402,6 +404,11 @@ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, + "node_modules/@kurkle/color": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.0.tgz", @@ -700,6 +707,17 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/chart.js": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.2.tgz", + "integrity": "sha512-6GD7iKwFpP5kbSD4MeRRRlTnQvxfQREy36uEtm1hzHzcOqwWx0YEHuspuoNlslu+nciLIB7fjjsHkUv/FzFcOg==", + "dependencies": { + "@kurkle/color": "^0.3.0" + }, + "engines": { + "pnpm": ">=8" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1035,6 +1053,15 @@ } } }, + "node_modules/vue-chartjs": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-5.3.1.tgz", + "integrity": "sha512-rZjqcHBxKiHrBl0CIvcOlVEBwRhpWAVf6rDU3vUfa7HuSRmGtCslc0Oc8m16oAVuk0erzc1FCtH1VCriHsrz+A==", + "peerDependencies": { + "chart.js": "^4.1.1", + "vue": "^3.0.0-0 || ^2.7.0" + } + }, "node_modules/vue-router": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.3.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 7453b7d..5f8fecf 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,7 +10,9 @@ }, "dependencies": { "axios": "^1.6.7", + "chart.js": "^4.4.2", "vue": "^3.4.15", + "vue-chartjs": "^5.3.1", "vue-router": "^4.2.5" }, "devDependencies": { diff --git a/frontend/src/api_client.js b/frontend/src/api_client.js index 03ed6c7..3b0f5be 100644 --- a/frontend/src/api_client.js +++ b/frontend/src/api_client.js @@ -60,7 +60,7 @@ export default } return btoa(binary); } - + const response = await axios.get(`/api/category/${category_id}/image/`, { responseType: 'arraybuffer' @@ -68,12 +68,20 @@ export default return 'data:image/jpeg;base64,' + arrayBufferToBase64(response.data); } + /** + * Get the current user IQ. It's the best players average IQ in all categories + * @returns {Object} {user_iq: Number} + */ + static async getUserIQ(category_id) { + const response = await axios.get(`/api/category/${category_id}/user_iq`); + return response.data; + } + /** * Get the global leaderboard. It's the best players average IQ in all categories * @returns {Array} [{user_id: Number, user_name: String, user_score: Number}] */ - static async getGlobalLeaderboard() - { + static async getGlobalLeaderboard() { const response = await axios.get(`/api/rank/global_leaderboard/`); return response.data; } @@ -81,8 +89,7 @@ export default * Get the global leaderboard specific to a category. It's the players with the best IQ in this category id * @returns {Array} [{user_id: Number, user_name: String, user_score: Number}] */ - static async getCategoryLeaderboard(category_id) - { + static async getCategoryLeaderboard(category_id) { const response = await axios.get(`/api/rank/${category_id}/leaderboard/`); return response.data; } @@ -91,8 +98,7 @@ export default * Get the global user rank based on average IQ in all categories of the connected player * @returns {Object} {user_rank: Number, user_score: Number} */ - static async getGlobalUserRank() - { + static async getGlobalUserRank() { const response = await axios.get(`/api/rank/global_user/`); return response.data; } @@ -101,8 +107,7 @@ export default * Get the user rank specific to a category. * @returns {Object} {user_rank: Number, user_score: Number} */ - static async getCategoryUserRank(category_id) - { + static async getCategoryUserRank(category_id) { const response = await axios.get(`/api/rank/${category_id}/user/`); return response.data; } diff --git a/frontend/src/components/AnswerForm.vue b/frontend/src/components/AnswerForm.vue index 8f0cd71..9722cb8 100644 --- a/frontend/src/components/AnswerForm.vue +++ b/frontend/src/components/AnswerForm.vue @@ -4,7 +4,7 @@ import { defineEmits, onMounted, ref, defineProps, watch } from 'vue'; import AnswerMessage from '@/components/AnswerMessage.vue'; // variables specific to this component -const emit = defineEmits(['newQuestion']) +const emit = defineEmits(['newQuestion', 'updateUserIq']) const answer_sent = ref(false); const show_text_form = ref(true); const answer_text = ref(""); @@ -23,11 +23,13 @@ const props = defineProps({ const submitAnswerText = async () => { response_to_answer.value = await APIClient.postAnswerText(answer_text.value); answer_sent.value = true; + emit('updateUserIq'); } const submitAnswerOption = async (id) => { response_to_answer.value = await APIClient.postAnswerOption(id); answer_sent.value = true; + emit('updateUserIq'); } const fetchOptions = async () => { diff --git a/frontend/src/components/GraphSection.vue b/frontend/src/components/GraphSection.vue new file mode 100644 index 0000000..0211902 --- /dev/null +++ b/frontend/src/components/GraphSection.vue @@ -0,0 +1,68 @@ + + + + + diff --git a/frontend/src/views/QuizView.vue b/frontend/src/views/QuizView.vue index b654b88..d12015e 100644 --- a/frontend/src/views/QuizView.vue +++ b/frontend/src/views/QuizView.vue @@ -4,6 +4,7 @@ import { onMounted, ref } from 'vue'; import AnswerForm from '@/components/AnswerForm.vue'; import LeaderBoard from '@/components/LeaderBoard.vue'; import CategorieBanner from '@/components/CategorieBanner.vue'; +import GraphSection from '@/components/GraphSection.vue'; import APIClient from '@/api_client'; // default variables @@ -20,9 +21,16 @@ const fetchNewQuestion = async () => { // wait for the question before checking if the user has asked for options hasAskedOptions.value = await APIClient.getIfOptionsAsked(); } +// Fetch user IQ and add it to the graph +const graphComponent = ref(null); +const fetchUserIQ = async () => { + const response = await APIClient.getUserIQ(); + graphComponent.value.addData(response.user_iq); +} onMounted(() => { fetchNewQuestion(); + fetchUserIQ(); }); @@ -34,10 +42,12 @@ onMounted(() => {

Question

{{ question }}

- +
+