fix and improve results, fix api advanced
This commit is contained in:
parent
d79369eabe
commit
2d3854a4fe
12 changed files with 470 additions and 93 deletions
7
app.vue
7
app.vue
|
@ -5,3 +5,10 @@
|
|||
</NuxtLayout>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.set-translate {
|
||||
@apply absolute top-[50%] left-[50%];
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
</style>
|
||||
|
|
55
components/ResultModal.vue
Normal file
55
components/ResultModal.vue
Normal file
|
@ -0,0 +1,55 @@
|
|||
<script setup lang="ts">
|
||||
import { VueFinalModal } from "vue-final-modal";
|
||||
|
||||
defineProps<{
|
||||
title?: string;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "homepage"): void;
|
||||
(e: "newExam"): void;
|
||||
(e: "close"): void;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VueFinalModal
|
||||
class="flex justify-center items-center backdrop-blur-sm"
|
||||
content-class="flex flex-col p-3 bg-white rounded-md gap-3"
|
||||
overlay-transition="vfm-fade"
|
||||
content-transition="vfm-fade"
|
||||
:click-to-close="false"
|
||||
:esc-to-close="false"
|
||||
>
|
||||
<h1 class="text-[1.5rem]">{{ title }}</h1>
|
||||
<div class="*:inline">Punkty: <slot name="points" /> / 74</div>
|
||||
<div class="*:inline">Wynik: pozytywny/negatywny</div>
|
||||
<div
|
||||
class="flex flex-row gap-2 *:py-1 *:px-3 *:border *:border-1 *:border-slate-300 *:rounded-md *:bg-slate-100"
|
||||
>
|
||||
<button class="text-slate-600" @click="emit('homepage')">
|
||||
Wróć na stronę główną
|
||||
</button>
|
||||
<button class="border-slate-200 bg-slate-50" @click="emit('newExam')">
|
||||
Rozpocznij jeszcze raz
|
||||
</button>
|
||||
<button
|
||||
class="!border-slate-500 !bg-slate-700 text-white"
|
||||
@click="emit('close')"
|
||||
>
|
||||
Przejrzyj odpowiedzi
|
||||
</button>
|
||||
</div>
|
||||
</VueFinalModal>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.confirm-modal-content button {
|
||||
padding: 0 8px;
|
||||
border: 1px solid;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
.dark .confirm-modal-content {
|
||||
background: #000;
|
||||
}
|
||||
</style>
|
|
@ -112,11 +112,6 @@ const isAdvanced = computed(() => props.now == "advanced");
|
|||
</template>
|
||||
|
||||
<style>
|
||||
.set-translate {
|
||||
@apply absolute top-[50%] left-[50%];
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.progressive {
|
||||
animation: progressZapoznanie 20s linear;
|
||||
}
|
57
components/RightBarResult.vue
Normal file
57
components/RightBarResult.vue
Normal file
|
@ -0,0 +1,57 @@
|
|||
<script setup lang="ts">
|
||||
import * as _ from "lodash";
|
||||
|
||||
const props = defineProps<{
|
||||
// result: ResultEndType;
|
||||
countBasic: number;
|
||||
countAdvanced: number;
|
||||
question: BasicQuestion | AdvancedQuestion | undefined;
|
||||
questionBasic: BasicQuestion | undefined;
|
||||
questionAdvanced: AdvancedQuestion | undefined;
|
||||
now: string | null | undefined;
|
||||
}>();
|
||||
|
||||
const isBasic = computed(() => props.now == "basic");
|
||||
const isAdvanced = computed(() => props.now == "advanced");
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="flex flex-col items-center p-4 gap-10 border-l border-slate-300 bg-slate-100"
|
||||
>
|
||||
<div>
|
||||
<button @click="$emit('end-exam')" class="btn-major">
|
||||
Wróć na stronę główną
|
||||
</button>
|
||||
<button @click="$emit('end-exam')" class="btn-major">
|
||||
Rozpocznij jeszcze raz
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex flex-row gap-6 *:flex-1 w-full">
|
||||
<button class="text-md text-white bg-blue-400">Pytania podstawowe</button>
|
||||
<button class="text-md text-white bg-blue-400">
|
||||
Pytania specjalistyczne
|
||||
</button>
|
||||
</div>
|
||||
<div class="w-full flex justify-center items-center">
|
||||
<div class="flex flex-row flex-wrap gap-2 items-stretch !w-max">
|
||||
<div
|
||||
v-for="num in _.range(1, 21)"
|
||||
class="p-1 bg-blue-500 text-white w-8 aspect-square text-center"
|
||||
>
|
||||
{{ num }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-row gap-6 *:flex-1 w-full">
|
||||
<button class="text-md text-white bg-blue-400">
|
||||
Odtwórz film ponownie
|
||||
</button>
|
||||
<button class="text-md text-white bg-blue-400">
|
||||
Pokaż poprawną odpowiedź
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- <style></style> -->
|
|
@ -2,7 +2,7 @@
|
|||
defineProps<{
|
||||
points: number | undefined;
|
||||
category: string | undefined;
|
||||
timeRemaining: string | undefined;
|
||||
timeRemaining?: string | undefined;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
|
@ -20,7 +20,7 @@ defineProps<{
|
|||
<span class="block">Aktualna kategoria (implement)</span>
|
||||
<div class="info-little-box">{{ category }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div v-if="typeof timeRemaining === 'string'">
|
||||
<span class="block">Czas do końca egzaminu (implement)</span>
|
||||
<div class="info-little-box">{{ timeRemaining }}</div>
|
||||
</div>
|
||||
|
|
|
@ -4,6 +4,7 @@ export default defineNuxtConfig({
|
|||
devtools: { enabled: true },
|
||||
modules: ["@nuxtjs/tailwindcss", "@nuxt/fonts", "@pinia/nuxt"],
|
||||
ssr: true,
|
||||
css: ["vue-final-modal/style.css"],
|
||||
imports: {
|
||||
dirs: ["types/*.ts", "store/*.ts", "types/**/*.ts"],
|
||||
},
|
||||
|
@ -12,4 +13,4 @@ export default defineNuxtConfig({
|
|||
cdn_url: "http://pj.netman.ovh/",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
|
@ -18,14 +18,17 @@
|
|||
"date-fns": "^4.1.0",
|
||||
"dotenv": "^16.4.7",
|
||||
"drizzle-orm": "^0.40.0",
|
||||
"lodash": "^4.17.21",
|
||||
"nuxt": "^3.15.4",
|
||||
"pg": "^8.13.3",
|
||||
"pinia": "^3.0.1",
|
||||
"vue": "latest",
|
||||
"vue-final-modal": "^4.5.5",
|
||||
"vue-router": "latest"
|
||||
},
|
||||
"packageManager": "pnpm@10.4.1+sha512.c753b6c3ad7afa13af388fa6d808035a008e30ea9993f58c6663e2bc5ff21679aa834db094987129aa4d488b86df57f7b634981b2f827cdcacc698cc0cfb88af",
|
||||
"devDependencies": {
|
||||
"@types/lodash": "^4.17.16",
|
||||
"@types/pg": "^8.11.11",
|
||||
"drizzle-kit": "^0.30.5",
|
||||
"tsx": "^4.19.3"
|
||||
|
|
|
@ -42,8 +42,8 @@ async function next() {
|
|||
question: questionBasic.value,
|
||||
chosen_answer: tak_nie_model.value ?? "",
|
||||
chosen_is_correct:
|
||||
tak_nie_model.value == question.value?.poprawna_odp?.toLowerCase(),
|
||||
liczba_pkt: question.value?.liczba_pkt,
|
||||
tak_nie_model.value == questionBasic.value?.poprawna_odp?.toLowerCase(),
|
||||
liczba_pkt: questionBasic.value?.liczba_pkt,
|
||||
});
|
||||
tak_nie_model.value = "";
|
||||
countBasic.value++;
|
||||
|
@ -56,28 +56,41 @@ async function next() {
|
|||
question: questionAdvanced.value,
|
||||
chosen_answer: abc_model.value ?? "",
|
||||
chosen_is_correct:
|
||||
abc_model.value == question.value?.poprawna_odp?.toLowerCase(),
|
||||
liczba_pkt: question.value?.liczba_pkt,
|
||||
abc_model.value ==
|
||||
questionAdvanced.value?.poprawna_odp?.toLowerCase(),
|
||||
liczba_pkt: questionAdvanced.value?.liczba_pkt,
|
||||
});
|
||||
} else {
|
||||
now.value = "advanced";
|
||||
|
||||
result.value.basic.push({
|
||||
question: questionBasic.value,
|
||||
chosen_answer: tak_nie_model.value ?? "",
|
||||
chosen_is_correct:
|
||||
tak_nie_model.value ==
|
||||
questionBasic.value?.poprawna_odp?.toLowerCase(),
|
||||
liczba_pkt: questionBasic.value?.liczba_pkt,
|
||||
});
|
||||
tak_nie_model.value = "";
|
||||
}
|
||||
if (countAdvanced.value + 1 < dataAdvanced.value?.length!) {
|
||||
countAdvanced.value++;
|
||||
} else {
|
||||
}
|
||||
if (countAdvanced.value == dataAdvanced.value?.length! - 1) {
|
||||
ending.value = true;
|
||||
}
|
||||
abc_model.value = "";
|
||||
}
|
||||
}
|
||||
|
||||
async function endExam() {
|
||||
function endExam() {
|
||||
while (!ending.value) {
|
||||
next();
|
||||
}
|
||||
next();
|
||||
examStore.result = result.value;
|
||||
examStore.end = true;
|
||||
await navigateTo("/result");
|
||||
return navigateTo("/result");
|
||||
}
|
||||
|
||||
const questionBasic = computed<BasicQuestion | undefined>(() =>
|
||||
|
@ -135,7 +148,7 @@ const result: Ref<ResultEndType> = ref({
|
|||
/>
|
||||
</div>
|
||||
|
||||
<RightBar
|
||||
<RightBarExam
|
||||
:result="result"
|
||||
:data-basic="dataBasic"
|
||||
:data-advanced="dataAdvanced"
|
||||
|
|
122
pages/result.vue
122
pages/result.vue
|
@ -1,4 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import { ModalsContainer, useModal } from "vue-final-modal";
|
||||
import ResultModal from "~/components/ResultModal.vue";
|
||||
|
||||
definePageMeta({
|
||||
layout: "exam",
|
||||
});
|
||||
|
@ -9,32 +12,121 @@ const points = ref<number>();
|
|||
|
||||
if (!examStore.end) {
|
||||
examStore.resetExam();
|
||||
setTimeout(() => {
|
||||
return navigateTo("/");
|
||||
}, 5000);
|
||||
await navigateTo("/");
|
||||
} else {
|
||||
let sum = 0;
|
||||
examStore.result.basic.forEach((a) => {
|
||||
if (a.chosen_is_correct) {
|
||||
sum += a.liczba_pkt ?? 0;
|
||||
examStore.result.basic.forEach((answer) => {
|
||||
if (answer.chosen_is_correct) {
|
||||
sum += answer.question?.liczba_pkt ?? 0;
|
||||
}
|
||||
});
|
||||
examStore.result.advanced.forEach((a) => {
|
||||
if (a.chosen_is_correct) {
|
||||
sum += a.liczba_pkt ?? 0;
|
||||
examStore.result.advanced.forEach((answer) => {
|
||||
if (answer.chosen_is_correct) {
|
||||
sum += answer.question?.liczba_pkt ?? 0;
|
||||
}
|
||||
});
|
||||
points.value = sum;
|
||||
}
|
||||
|
||||
const countBasic = ref(0);
|
||||
const countAdvanced = ref(0);
|
||||
|
||||
const resultQuestionBasic = computed<ResultType<BasicQuestion> | undefined>(
|
||||
() => examStore.result.basic.at(countBasic.value)
|
||||
);
|
||||
const resultQuestionAdvanced = computed<
|
||||
ResultType<AdvancedQuestion> | undefined
|
||||
>(() => examStore.result.advanced.at(countAdvanced.value));
|
||||
|
||||
const questionBasic = computed<BasicQuestion | undefined>(
|
||||
() => resultQuestionBasic.value?.question
|
||||
);
|
||||
const questionAdvanced = computed<AdvancedQuestion | undefined>(
|
||||
() => resultQuestionAdvanced.value?.question
|
||||
);
|
||||
|
||||
const now = ref("basic");
|
||||
|
||||
const question = computed(() => {
|
||||
if (now.value == "basic") {
|
||||
return questionBasic.value;
|
||||
} else if (now.value == "advanced") {
|
||||
return questionAdvanced.value;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
const tak_nie_model = computed(() =>
|
||||
resultQuestionBasic.value?.chosen_answer.toLowerCase()
|
||||
);
|
||||
const abc_model = computed(() =>
|
||||
resultQuestionAdvanced.value?.chosen_answer.toLowerCase()
|
||||
);
|
||||
|
||||
const media = computed(() => {
|
||||
const mediaSplit = question.value?.media?.split(".");
|
||||
return {
|
||||
fileType: mediaSplit?.pop()?.toLowerCase(),
|
||||
fileName: mediaSplit?.join("."),
|
||||
ogName: question.value?.media,
|
||||
};
|
||||
});
|
||||
|
||||
const { open, close } = useModal({
|
||||
component: ResultModal,
|
||||
attrs: {
|
||||
title: "Egzamin teorytyczny",
|
||||
onClose() {
|
||||
close();
|
||||
},
|
||||
onHomepage() {
|
||||
return navigateTo("/");
|
||||
},
|
||||
onNewExam() {
|
||||
return navigateTo("/exam");
|
||||
},
|
||||
},
|
||||
slots: {
|
||||
points: `${points.value}`,
|
||||
},
|
||||
});
|
||||
open();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="text-4xl">
|
||||
<div v-if="!examStore.end">Exam not finished, redirecting...</div>
|
||||
<div v-else>
|
||||
Result: {{ points }} / 74
|
||||
<br />
|
||||
{{ examStore.result }}
|
||||
<div>
|
||||
<ModalsContainer />
|
||||
<div>
|
||||
<div class="grid grid-cols-4 min-h-dvh">
|
||||
<div class="col-span-3 flex flex-col gap-4">
|
||||
<TopBar :points="question?.liczba_pkt" :category="`B`" />
|
||||
<Media :media="media" />
|
||||
<BasicQuestionBlock
|
||||
v-if="now == 'basic'"
|
||||
:question="questionBasic"
|
||||
v-model="tak_nie_model"
|
||||
class="select-none z-[-1]"
|
||||
/>
|
||||
<AdvancedQuestionBlock
|
||||
v-else-if="now == 'advanced'"
|
||||
:question="questionAdvanced"
|
||||
v-model="abc_model"
|
||||
class="select-none z-[-1]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<RightBarResult
|
||||
:question="question"
|
||||
:question-basic="questionBasic"
|
||||
:question-advanced="questionAdvanced"
|
||||
:count-basic="countBasic"
|
||||
:count-advanced="countAdvanced"
|
||||
:now="now"
|
||||
/>
|
||||
<!-- :result="result" -->
|
||||
<!-- @next-question="next()" -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
7
plugins/vue-final-modal.ts
Normal file
7
plugins/vue-final-modal.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { createVfm } from "vue-final-modal";
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
const vfm = createVfm() as any;
|
||||
|
||||
nuxtApp.vueApp.use(vfm);
|
||||
});
|
124
pnpm-lock.yaml
generated
124
pnpm-lock.yaml
generated
|
@ -35,6 +35,9 @@ importers:
|
|||
drizzle-orm:
|
||||
specifier: ^0.40.0
|
||||
version: 0.40.0(@types/pg@8.11.11)(gel@2.0.0)(pg@8.13.3)
|
||||
lodash:
|
||||
specifier: ^4.17.21
|
||||
version: 4.17.21
|
||||
nuxt:
|
||||
specifier: ^3.15.4
|
||||
version: 3.15.4(@parcel/watcher@2.5.1)(@types/node@22.13.4)(db0@0.2.4(drizzle-orm@0.40.0(@types/pg@8.11.11)(gel@2.0.0)(pg@8.13.3)))(ioredis@5.5.0)(magicast@0.3.5)(rollup@4.34.8)(terser@5.39.0)(tsx@4.19.3)(typescript@5.7.3)(vite@6.1.1(@types/node@22.13.4)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(yaml@2.7.0)
|
||||
|
@ -47,10 +50,16 @@ importers:
|
|||
vue:
|
||||
specifier: latest
|
||||
version: 3.5.13(typescript@5.7.3)
|
||||
vue-final-modal:
|
||||
specifier: ^4.5.5
|
||||
version: 4.5.5(@vueuse/core@12.7.0(typescript@5.7.3))(@vueuse/integrations@12.7.0(focus-trap@7.6.4)(fuse.js@7.1.0)(typescript@5.7.3))(focus-trap@7.6.4)(vue@3.5.13(typescript@5.7.3))
|
||||
vue-router:
|
||||
specifier: latest
|
||||
version: 4.5.0(vue@3.5.13(typescript@5.7.3))
|
||||
devDependencies:
|
||||
'@types/lodash':
|
||||
specifier: ^4.17.16
|
||||
version: 4.17.16
|
||||
'@types/pg':
|
||||
specifier: ^8.11.11
|
||||
version: 8.11.11
|
||||
|
@ -1247,6 +1256,9 @@ packages:
|
|||
'@types/http-proxy@1.17.16':
|
||||
resolution: {integrity: sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w==}
|
||||
|
||||
'@types/lodash@4.17.16':
|
||||
resolution: {integrity: sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==}
|
||||
|
||||
'@types/node@22.13.4':
|
||||
resolution: {integrity: sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==}
|
||||
|
||||
|
@ -1259,6 +1271,9 @@ packages:
|
|||
'@types/resolve@1.20.2':
|
||||
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
|
||||
|
||||
'@types/web-bluetooth@0.0.20':
|
||||
resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==}
|
||||
|
||||
'@unhead/dom@1.11.19':
|
||||
resolution: {integrity: sha512-udkgITdIblEWH3hsoFQMKW+6QXNO2qFZlZ2FI37bVAplQSnK/PytTPt/5oA1GWkoVwT0DsQNGHbU6kOg/3SlNg==}
|
||||
|
||||
|
@ -1369,6 +1384,56 @@ packages:
|
|||
'@vue/shared@3.5.13':
|
||||
resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==}
|
||||
|
||||
'@vueuse/core@12.7.0':
|
||||
resolution: {integrity: sha512-jtK5B7YjZXmkGNHjviyGO4s3ZtEhbzSgrbX+s5o+Lr8i2nYqNyHuPVOeTdM1/hZ5Tkxg/KktAuAVDDiHMraMVA==}
|
||||
|
||||
'@vueuse/integrations@12.7.0':
|
||||
resolution: {integrity: sha512-IEq7K4bCl7mn3uKJaWtNXnd1CAPaHLUMuyj5K1/k/pVcItt0VONZW8xiGxdIovJcQjkzOHjImhX5t6gija+0/g==}
|
||||
peerDependencies:
|
||||
async-validator: ^4
|
||||
axios: ^1
|
||||
change-case: ^5
|
||||
drauu: ^0.4
|
||||
focus-trap: ^7
|
||||
fuse.js: ^7
|
||||
idb-keyval: ^6
|
||||
jwt-decode: ^4
|
||||
nprogress: ^0.2
|
||||
qrcode: ^1.5
|
||||
sortablejs: ^1
|
||||
universal-cookie: ^7
|
||||
peerDependenciesMeta:
|
||||
async-validator:
|
||||
optional: true
|
||||
axios:
|
||||
optional: true
|
||||
change-case:
|
||||
optional: true
|
||||
drauu:
|
||||
optional: true
|
||||
focus-trap:
|
||||
optional: true
|
||||
fuse.js:
|
||||
optional: true
|
||||
idb-keyval:
|
||||
optional: true
|
||||
jwt-decode:
|
||||
optional: true
|
||||
nprogress:
|
||||
optional: true
|
||||
qrcode:
|
||||
optional: true
|
||||
sortablejs:
|
||||
optional: true
|
||||
universal-cookie:
|
||||
optional: true
|
||||
|
||||
'@vueuse/metadata@12.7.0':
|
||||
resolution: {integrity: sha512-4VvTH9mrjXqFN5LYa5YfqHVRI6j7R00Vy4995Rw7PQxyCL3z0Lli86iN4UemWqixxEvYfRjG+hF9wL8oLOn+3g==}
|
||||
|
||||
'@vueuse/shared@12.7.0':
|
||||
resolution: {integrity: sha512-coLlUw2HHKsm7rPN6WqHJQr18WymN4wkA/3ThFaJ4v4gWGWAQQGK+MJxLuJTBs4mojQiazlVWAKNJNpUWGRkNw==}
|
||||
|
||||
abbrev@1.1.1:
|
||||
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
|
||||
|
||||
|
@ -2162,6 +2227,9 @@ packages:
|
|||
flatted@3.3.3:
|
||||
resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==}
|
||||
|
||||
focus-trap@7.6.4:
|
||||
resolution: {integrity: sha512-xx560wGBk7seZ6y933idtjJQc1l+ck+pI3sKvhKozdBV1dRZoKhkW5xoCaFv9tQiX5RH1xfSxjuNu6g+lmN/gw==}
|
||||
|
||||
fontaine@0.5.0:
|
||||
resolution: {integrity: sha512-vPDSWKhVAfTx4hRKT777+N6Szh2pAosAuzLpbppZ6O3UdD/1m6OlHjNcC3vIbgkRTIcLjzySLHXzPeLO2rE8cA==}
|
||||
|
||||
|
@ -3615,6 +3683,9 @@ packages:
|
|||
resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
tabbable@6.2.0:
|
||||
resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==}
|
||||
|
||||
tailwind-config-viewer@2.0.4:
|
||||
resolution: {integrity: sha512-icvcmdMmt9dphvas8wL40qttrHwAnW3QEN4ExJ2zICjwRsPj7gowd1cOceaWG3IfTuM/cTNGQcx+bsjMtmV+cw==}
|
||||
engines: {node: '>=13'}
|
||||
|
@ -4008,6 +4079,14 @@ packages:
|
|||
vue-devtools-stub@0.1.0:
|
||||
resolution: {integrity: sha512-RutnB7X8c5hjq39NceArgXg28WZtZpGc3+J16ljMiYnFhKvd8hITxSWQSQ5bvldxMDU6gG5mkxl1MTQLXckVSQ==}
|
||||
|
||||
vue-final-modal@4.5.5:
|
||||
resolution: {integrity: sha512-A6xgsXqE6eLw9e6Tq/W6pxDBmimPuSuvq20WL9TOZpZy7itPdGeNn8e1P15PCGqP2yHM3q2gJIchPY9ZJd8YsA==}
|
||||
peerDependencies:
|
||||
'@vueuse/core': '>=10.0.0'
|
||||
'@vueuse/integrations': '>=10.0.0'
|
||||
focus-trap: '>=7.2.0'
|
||||
vue: '>=3.2.0'
|
||||
|
||||
vue-router@4.5.0:
|
||||
resolution: {integrity: sha512-HDuk+PuH5monfNuY+ct49mNmkCRK4xJAV9Ts4z9UFc4rzdDnxQLyCMGGc8pKhZhHTVzfanpNwB/lwqevcBwI4w==}
|
||||
peerDependencies:
|
||||
|
@ -5233,6 +5312,8 @@ snapshots:
|
|||
dependencies:
|
||||
'@types/node': 22.13.4
|
||||
|
||||
'@types/lodash@4.17.16': {}
|
||||
|
||||
'@types/node@22.13.4':
|
||||
dependencies:
|
||||
undici-types: 6.20.0
|
||||
|
@ -5247,6 +5328,8 @@ snapshots:
|
|||
|
||||
'@types/resolve@1.20.2': {}
|
||||
|
||||
'@types/web-bluetooth@0.0.20': {}
|
||||
|
||||
'@unhead/dom@1.11.19':
|
||||
dependencies:
|
||||
'@unhead/schema': 1.11.19
|
||||
|
@ -5444,6 +5527,34 @@ snapshots:
|
|||
|
||||
'@vue/shared@3.5.13': {}
|
||||
|
||||
'@vueuse/core@12.7.0(typescript@5.7.3)':
|
||||
dependencies:
|
||||
'@types/web-bluetooth': 0.0.20
|
||||
'@vueuse/metadata': 12.7.0
|
||||
'@vueuse/shared': 12.7.0(typescript@5.7.3)
|
||||
vue: 3.5.13(typescript@5.7.3)
|
||||
transitivePeerDependencies:
|
||||
- typescript
|
||||
|
||||
'@vueuse/integrations@12.7.0(focus-trap@7.6.4)(fuse.js@7.1.0)(typescript@5.7.3)':
|
||||
dependencies:
|
||||
'@vueuse/core': 12.7.0(typescript@5.7.3)
|
||||
'@vueuse/shared': 12.7.0(typescript@5.7.3)
|
||||
vue: 3.5.13(typescript@5.7.3)
|
||||
optionalDependencies:
|
||||
focus-trap: 7.6.4
|
||||
fuse.js: 7.1.0
|
||||
transitivePeerDependencies:
|
||||
- typescript
|
||||
|
||||
'@vueuse/metadata@12.7.0': {}
|
||||
|
||||
'@vueuse/shared@12.7.0(typescript@5.7.3)':
|
||||
dependencies:
|
||||
vue: 3.5.13(typescript@5.7.3)
|
||||
transitivePeerDependencies:
|
||||
- typescript
|
||||
|
||||
abbrev@1.1.1: {}
|
||||
|
||||
accepts@1.3.8:
|
||||
|
@ -6210,6 +6321,10 @@ snapshots:
|
|||
|
||||
flatted@3.3.3: {}
|
||||
|
||||
focus-trap@7.6.4:
|
||||
dependencies:
|
||||
tabbable: 6.2.0
|
||||
|
||||
fontaine@0.5.0:
|
||||
dependencies:
|
||||
'@capsizecss/metrics': 2.2.0
|
||||
|
@ -7887,6 +8002,8 @@ snapshots:
|
|||
|
||||
system-architecture@0.1.0: {}
|
||||
|
||||
tabbable@6.2.0: {}
|
||||
|
||||
tailwind-config-viewer@2.0.4(tailwindcss@3.4.17):
|
||||
dependencies:
|
||||
'@koa/router': 12.0.2
|
||||
|
@ -8315,6 +8432,13 @@ snapshots:
|
|||
|
||||
vue-devtools-stub@0.1.0: {}
|
||||
|
||||
vue-final-modal@4.5.5(@vueuse/core@12.7.0(typescript@5.7.3))(@vueuse/integrations@12.7.0(focus-trap@7.6.4)(fuse.js@7.1.0)(typescript@5.7.3))(focus-trap@7.6.4)(vue@3.5.13(typescript@5.7.3)):
|
||||
dependencies:
|
||||
'@vueuse/core': 12.7.0(typescript@5.7.3)
|
||||
'@vueuse/integrations': 12.7.0(focus-trap@7.6.4)(fuse.js@7.1.0)(typescript@5.7.3)
|
||||
focus-trap: 7.6.4
|
||||
vue: 3.5.13(typescript@5.7.3)
|
||||
|
||||
vue-router@4.5.0(vue@3.5.13(typescript@5.7.3)):
|
||||
dependencies:
|
||||
'@vue/devtools-api': 6.6.4
|
||||
|
|
|
@ -1,71 +1,94 @@
|
|||
import "dotenv/config";
|
||||
import { drizzle } from "drizzle-orm/node-postgres";
|
||||
import { dane, punkty } from "@/src/db/schema";
|
||||
import { sql, eq, isNotNull, and } from "drizzle-orm";
|
||||
import { sql, eq, and, or, isNotNull } from "drizzle-orm";
|
||||
import { AdvancedQuestion } from "~/types";
|
||||
import arrayShuffle from "array-shuffle";
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const query = getQuery(event);
|
||||
const amount = query?.amount;
|
||||
const db = drizzle(process.env.DATABASE_URL!);
|
||||
const questions: AdvancedQuestion[] = await db
|
||||
.select({
|
||||
id: dane.id,
|
||||
nr_pytania: dane.nr_pytania,
|
||||
pytanie: dane.pytanie,
|
||||
poprawna_odp: dane.poprawna_odp,
|
||||
media: dane.media,
|
||||
kategorie: dane.kategorie,
|
||||
nazwa_media_pjm_tresc_pyt: dane.nazwa_media_pjm_tresc_pyt,
|
||||
pytanie_eng: dane.pytanie_eng,
|
||||
pytanie_de: dane.pytanie_de,
|
||||
pytanie_ua: dane.pytanie_ua,
|
||||
liczba_pkt: punkty.liczba_pkt,
|
||||
async function getFromDb(points: number | string) {
|
||||
return await db
|
||||
.select({
|
||||
id: dane.id,
|
||||
nr_pytania: dane.nr_pytania,
|
||||
pytanie: dane.pytanie,
|
||||
poprawna_odp: dane.poprawna_odp,
|
||||
media: dane.media,
|
||||
kategorie: dane.kategorie,
|
||||
nazwa_media_pjm_tresc_pyt: dane.nazwa_media_pjm_tresc_pyt,
|
||||
pytanie_eng: dane.pytanie_eng,
|
||||
pytanie_de: dane.pytanie_de,
|
||||
pytanie_ua: dane.pytanie_ua,
|
||||
liczba_pkt: punkty.liczba_pkt,
|
||||
|
||||
odp_a: dane.odp_a,
|
||||
odp_b: dane.odp_b,
|
||||
odp_c: dane.odp_c,
|
||||
nazwa_media_pjm_tresc_odp_a: dane.nazwa_media_pjm_tresc_odp_a,
|
||||
nazwa_media_pjm_tresc_odp_b: dane.nazwa_media_pjm_tresc_odp_b,
|
||||
nazwa_media_pjm_tresc_odp_c: dane.nazwa_media_pjm_tresc_odp_c,
|
||||
odp_a_eng: dane.odp_a_eng,
|
||||
odp_b_eng: dane.odp_b_eng,
|
||||
odp_c_eng: dane.odp_c_eng,
|
||||
odp_a_de: dane.odp_a_de,
|
||||
odp_b_de: dane.odp_b_de,
|
||||
odp_c_de: dane.odp_c_de,
|
||||
odp_a_ua: dane.odp_a_ua,
|
||||
odp_b_ua: dane.odp_b_ua,
|
||||
odp_c_ua: dane.odp_c_ua,
|
||||
})
|
||||
.from(dane)
|
||||
.innerJoin(punkty, eq(dane.nr_pytania, punkty.nr_pytania))
|
||||
.where(
|
||||
and(
|
||||
isNotNull(dane.odp_a),
|
||||
isNotNull(dane.odp_b),
|
||||
isNotNull(dane.odp_c),
|
||||
isNotNull(dane.odp_a_eng),
|
||||
isNotNull(dane.odp_b_eng),
|
||||
isNotNull(dane.odp_c_eng),
|
||||
isNotNull(dane.odp_a_de),
|
||||
isNotNull(dane.odp_b_de),
|
||||
isNotNull(dane.odp_c_de)
|
||||
)
|
||||
);
|
||||
const randoms: Array<number> = [];
|
||||
const randomizedQuestions = [];
|
||||
for (let i = 0; i < +(amount ?? 12); i++) {
|
||||
let randomized = Math.floor(Math.random() * (questions.length - 1 + 1)) + 0;
|
||||
while (randoms.includes(randomized)) {
|
||||
randomized = Math.floor(Math.random() * (questions.length - 1 + 1)) + 0;
|
||||
}
|
||||
randoms.push(randomized);
|
||||
if (questions[randomized].kategorie?.split(",").includes("B")) {
|
||||
randomizedQuestions.push(questions[randomized]);
|
||||
} else {
|
||||
i--;
|
||||
}
|
||||
odp_a: dane.odp_a,
|
||||
odp_b: dane.odp_b,
|
||||
odp_c: dane.odp_c,
|
||||
nazwa_media_pjm_tresc_odp_a: dane.nazwa_media_pjm_tresc_odp_a,
|
||||
nazwa_media_pjm_tresc_odp_b: dane.nazwa_media_pjm_tresc_odp_b,
|
||||
nazwa_media_pjm_tresc_odp_c: dane.nazwa_media_pjm_tresc_odp_c,
|
||||
odp_a_eng: dane.odp_a_eng,
|
||||
odp_b_eng: dane.odp_b_eng,
|
||||
odp_c_eng: dane.odp_c_eng,
|
||||
odp_a_de: dane.odp_a_de,
|
||||
odp_b_de: dane.odp_b_de,
|
||||
odp_c_de: dane.odp_c_de,
|
||||
odp_a_ua: dane.odp_a_ua,
|
||||
odp_b_ua: dane.odp_b_ua,
|
||||
odp_c_ua: dane.odp_c_ua,
|
||||
})
|
||||
.from(dane)
|
||||
.innerJoin(punkty, eq(dane.nr_pytania, punkty.nr_pytania))
|
||||
.where(
|
||||
and(
|
||||
isNotNull(dane.odp_a),
|
||||
isNotNull(dane.odp_b),
|
||||
isNotNull(dane.odp_c),
|
||||
isNotNull(dane.odp_a_eng),
|
||||
isNotNull(dane.odp_b_eng),
|
||||
isNotNull(dane.odp_c_eng),
|
||||
isNotNull(dane.odp_a_de),
|
||||
isNotNull(dane.odp_b_de),
|
||||
isNotNull(dane.odp_c_de),
|
||||
eq(punkty.liczba_pkt, +points)
|
||||
)
|
||||
);
|
||||
}
|
||||
return randomizedQuestions;
|
||||
const query = getQuery(event);
|
||||
const category = query.category;
|
||||
if (typeof category != "undefined" && typeof category != "string") {
|
||||
throw new Error(
|
||||
"category argument has to be string (or not to be defined at all)"
|
||||
);
|
||||
}
|
||||
const db = drizzle(process.env.DATABASE_URL!);
|
||||
|
||||
const randomizedQuestions: AdvancedQuestion[] = [];
|
||||
|
||||
for (let [key, value] of Object.entries({ 1: 2, 2: 4, 3: 6 })) {
|
||||
const questionsKeyPoints: AdvancedQuestion[] = await getFromDb(key);
|
||||
const chosenRandomQuestions: AdvancedQuestion[] = [];
|
||||
|
||||
const randoms: Array<number> = [];
|
||||
for (let j = 0; j < value; j++) {
|
||||
let randomized =
|
||||
Math.floor(Math.random() * (questionsKeyPoints.length - 1 + 1)) + 0;
|
||||
while (randoms.includes(randomized)) {
|
||||
randomized =
|
||||
Math.floor(Math.random() * (questionsKeyPoints.length - 1 + 1)) + 0;
|
||||
}
|
||||
randoms.push(randomized);
|
||||
if (
|
||||
questionsKeyPoints[randomized].kategorie
|
||||
.split(",")
|
||||
.includes(category ?? "B")
|
||||
) {
|
||||
chosenRandomQuestions.push(questionsKeyPoints[randomized]);
|
||||
} else {
|
||||
j--;
|
||||
}
|
||||
}
|
||||
chosenRandomQuestions.forEach((q) => randomizedQuestions.push(q));
|
||||
}
|
||||
return arrayShuffle(randomizedQuestions);
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue