first commit, pretty ok
This commit is contained in:
commit
390f600fcb
17 changed files with 8983 additions and 0 deletions
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# Nuxt dev/build outputs
|
||||||
|
.output
|
||||||
|
.data
|
||||||
|
.nuxt
|
||||||
|
.nitro
|
||||||
|
.cache
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Node dependencies
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
.DS_Store
|
||||||
|
.fleet
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Local env files
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
75
README.md
Normal file
75
README.md
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
# Nuxt Minimal Starter
|
||||||
|
|
||||||
|
Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Make sure to install dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn install
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development Server
|
||||||
|
|
||||||
|
Start the development server on `http://localhost:3000`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm dev
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn dev
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production
|
||||||
|
|
||||||
|
Build the application for production:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm build
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn build
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Locally preview production build:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run preview
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm preview
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn preview
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run preview
|
||||||
|
```
|
||||||
|
|
||||||
|
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
7
app.vue
Normal file
7
app.vue
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<NuxtLayout>
|
||||||
|
<NuxtPage />
|
||||||
|
</NuxtLayout>
|
||||||
|
</div>
|
||||||
|
</template>
|
11
drizzle.config.ts
Normal file
11
drizzle.config.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import 'dotenv/config';
|
||||||
|
import { defineConfig } from "drizzle-kit";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
dialect: "postgresql",
|
||||||
|
schema: "./src/db/schema.ts",
|
||||||
|
out: "./drizzle",
|
||||||
|
dbCredentials: {
|
||||||
|
url: process.env.DATABASE_URL!,
|
||||||
|
}
|
||||||
|
});
|
3
layouts/default.vue
Normal file
3
layouts/default.vue
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<template>
|
||||||
|
<div><slot /></div>
|
||||||
|
</template>
|
15
nuxt.config.ts
Normal file
15
nuxt.config.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
compatibilityDate: "2024-11-01",
|
||||||
|
devtools: { enabled: true },
|
||||||
|
modules: ["@nuxtjs/tailwindcss", "@nuxt/fonts"],
|
||||||
|
ssr: true,
|
||||||
|
imports: {
|
||||||
|
dirs: ["types/*.ts", "store/*.ts", "types/**/*.ts"],
|
||||||
|
},
|
||||||
|
runtimeConfig: {
|
||||||
|
public: {
|
||||||
|
cdn_url: "http://pj.netman.ovh/",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
32
package.json
Normal file
32
package.json
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"name": "nuxt-app",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"build": "nuxt build",
|
||||||
|
"dev": "nuxt dev",
|
||||||
|
"generate": "nuxt generate",
|
||||||
|
"preview": "nuxt preview",
|
||||||
|
"postinstall": "nuxt prepare"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@nuxt/fonts": "0.10.3",
|
||||||
|
"@nuxtjs/tailwindcss": "6.13.1",
|
||||||
|
"array-shuffle": "^3.0.0",
|
||||||
|
"dotenv": "^16.4.7",
|
||||||
|
"drizzle-orm": "^0.40.0",
|
||||||
|
"nuxt": "^3.15.4",
|
||||||
|
"pg": "^8.13.3",
|
||||||
|
"vue": "latest",
|
||||||
|
"vue-router": "latest"
|
||||||
|
},
|
||||||
|
"packageManager": "pnpm@10.4.1+sha512.c753b6c3ad7afa13af388fa6d808035a008e30ea9993f58c6663e2bc5ff21679aa834db094987129aa4d488b86df57f7b634981b2f827cdcacc698cc0cfb88af",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/pg": "^8.11.11",
|
||||||
|
"drizzle-kit": "^0.30.5",
|
||||||
|
"tsx": "^4.19.3"
|
||||||
|
},
|
||||||
|
"resolutions": {
|
||||||
|
"nitropack": "2.8.1"
|
||||||
|
}
|
||||||
|
}
|
37
pages/advanced.vue
Normal file
37
pages/advanced.vue
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
const {data} = await useFetch("/api/advanced");
|
||||||
|
|
||||||
|
const count = ref(0);
|
||||||
|
|
||||||
|
function next() {
|
||||||
|
if (count.value + 1 < data.value.length) {
|
||||||
|
count.value++;
|
||||||
|
} else {
|
||||||
|
console.log("Ok!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div v-if="data">
|
||||||
|
{{ data[count].nr_pytania }}: {{ data[count].pytanie }}
|
||||||
|
<!-- {{ data[count].poprawna_odp }} -->
|
||||||
|
{{ data[count].odp_a }}
|
||||||
|
{{ data[count].odp_b }}
|
||||||
|
{{ data[count].odp_c }}
|
||||||
|
<div v-if="data[count].media">
|
||||||
|
<img :src="'http://localhost:8081/'+data[count].media" alt="" v-if="data[count].media.split('.').at(-1).toLowerCase() == 'jpg'">
|
||||||
|
<video controls width="650" v-else-if="data[count].media.split('.').at(-1).toLowerCase() == 'mp4'">
|
||||||
|
<source :src="'http://localhost:8081/'+data[count].media" type="video/mp4" />
|
||||||
|
</video>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
No Media.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<button @click="next()">Next</button>
|
||||||
|
{{count}}
|
||||||
|
</div>
|
||||||
|
</template>
|
206
pages/basic.vue
Normal file
206
pages/basic.vue
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { BasicQuestion } from "@/types/basic";
|
||||||
|
|
||||||
|
useHead({
|
||||||
|
title: "Pytanie 1/20",
|
||||||
|
});
|
||||||
|
|
||||||
|
const { data, error, status, refresh } = await useFetch<BasicQuestion[]>(
|
||||||
|
"/api/basic"
|
||||||
|
);
|
||||||
|
|
||||||
|
const runtimeConfig = useRuntimeConfig();
|
||||||
|
const cdnUrl = runtimeConfig.public.cdn_url;
|
||||||
|
|
||||||
|
const count = ref(0);
|
||||||
|
|
||||||
|
const tak_nie_model = ref();
|
||||||
|
|
||||||
|
async function next() {
|
||||||
|
if (count.value + 1 < data.value?.length!) {
|
||||||
|
questionaries.value.push({
|
||||||
|
nr_pytania: question.value?.nr_pytania,
|
||||||
|
chosen_answer: tak_nie_model.value ?? "",
|
||||||
|
correct_answer: question.value?.poprawna_odp?.toLowerCase(),
|
||||||
|
chosen_is_correct:
|
||||||
|
tak_nie_model.value == question.value?.poprawna_odp?.toLowerCase(),
|
||||||
|
liczba_pkt: question.value?.liczba_pkt,
|
||||||
|
});
|
||||||
|
tak_nie_model.value = "";
|
||||||
|
count.value++;
|
||||||
|
useHead({
|
||||||
|
title: `Pytanie ${count.value + 1}/${data.value?.length}`,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// await navigateTo("/advanced");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const question = computed(() => data.value?.at(count.value));
|
||||||
|
const media = computed(() => {
|
||||||
|
const mediaSplit = question.value?.media?.split(".");
|
||||||
|
return {
|
||||||
|
fileType: mediaSplit?.pop()?.toLowerCase(),
|
||||||
|
fileName: mediaSplit?.join("."),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const questionaries: Ref<Array<any>> = ref([]);
|
||||||
|
|
||||||
|
const progres = ref();
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
const progresInterval = setInterval(() => {
|
||||||
|
progres.value.value = +progres.value.value + 1;
|
||||||
|
if (progres.value.value >= 100) {
|
||||||
|
clearInterval(progresInterval);
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div v-if="status === 'success'">
|
||||||
|
<div class="grid grid-cols-4">
|
||||||
|
<div class="col-span-3 flex flex-col gap-4 p-4">
|
||||||
|
<div class="flex flex-row gap-5">
|
||||||
|
<div>
|
||||||
|
Wartość punktowa
|
||||||
|
<div class="info-little-box">
|
||||||
|
{{ question?.liczba_pkt }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Aktualna kategoria (implement)
|
||||||
|
<div class="info-little-box">B</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Czas do końca egzaminu (implement)
|
||||||
|
<div class="info-little-box">25:00</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="select-none z-[-1] w-full flex items-center justify-center *:object-contain *:object-contain *:*:object-contain"
|
||||||
|
>
|
||||||
|
<div class="w-[650px] *:w-full">
|
||||||
|
<img
|
||||||
|
:src="cdnUrl + [media.fileName, media.fileType].join('.')"
|
||||||
|
alt=""
|
||||||
|
v-if="media.fileType == 'jpg'"
|
||||||
|
/>
|
||||||
|
<video
|
||||||
|
v-else-if="media.fileType == 'wmv'"
|
||||||
|
:key="media.fileName"
|
||||||
|
autoplay
|
||||||
|
>
|
||||||
|
<source
|
||||||
|
:src="cdnUrl + [media.fileName, 'mp4'].join('.')"
|
||||||
|
type="video/mp4"
|
||||||
|
/>
|
||||||
|
</video>
|
||||||
|
<span v-else>Brak mediów</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>{{ question?.pytanie }}</div>
|
||||||
|
<div>
|
||||||
|
<div class="flex flex-row justify-around">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="tak_nie"
|
||||||
|
id="odp_tak"
|
||||||
|
v-model="tak_nie_model"
|
||||||
|
value="tak"
|
||||||
|
class="hidden"
|
||||||
|
/>
|
||||||
|
<label for="odp_tak">
|
||||||
|
<div
|
||||||
|
:class="`btn-answer ${
|
||||||
|
tak_nie_model == 'tak' ? ' !bg-fuchsia-500' : ''
|
||||||
|
}`"
|
||||||
|
>
|
||||||
|
TAK
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="tak_nie"
|
||||||
|
id="odp_nie"
|
||||||
|
v-model="tak_nie_model"
|
||||||
|
value="nie"
|
||||||
|
class="hidden"
|
||||||
|
/>
|
||||||
|
<label for="odp_nie">
|
||||||
|
<div
|
||||||
|
:class="`btn-answer ${
|
||||||
|
tak_nie_model == 'nie' ? ' !bg-fuchsia-500' : ''
|
||||||
|
}`"
|
||||||
|
>
|
||||||
|
NIE
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<div>
|
||||||
|
<button class="btn-major">Zakończ egzamin</button>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-row">
|
||||||
|
<div>
|
||||||
|
Pytania podstawowe
|
||||||
|
<div class="progressive">
|
||||||
|
{{ count + 1 }} / {{ data?.length }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Pytania specjalistyczne
|
||||||
|
<div class="progressive">
|
||||||
|
{{ count + 1 }} / {{ data?.length }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>TimeLeft (implement)</div>
|
||||||
|
<div>
|
||||||
|
<button @click="next()" class="btn-major">Następne pytanie</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
{{ questionaries }}
|
||||||
|
</div>
|
||||||
|
<div v-else-if="status === 'error'">Error: {{ error }}</div>
|
||||||
|
<div v-else>Loading...</div>
|
||||||
|
<progress max="100" ref="progres">Aha...</progress>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.btn {
|
||||||
|
@apply box-border text-white font-bold p-3 rounded-md w-fit cursor-pointer border-[4px];
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-answer {
|
||||||
|
@apply btn bg-blue-500 text-xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-answer:hover {
|
||||||
|
@apply bg-blue-300;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-answer:active {
|
||||||
|
@apply bg-blue-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-major {
|
||||||
|
@apply btn bg-orange-400 text-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-little-box {
|
||||||
|
@apply inline-block px-[15px] py-[8px] bg-blue-500 text-white font-bold;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
.progressive {
|
||||||
|
} */
|
||||||
|
</style>
|
10
pages/index.vue
Normal file
10
pages/index.vue
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1>Test na prawo jazdy kat.B</h1>
|
||||||
|
<p>
|
||||||
|
Witaj w teście na prawo jazdy kat.B, aby rozpocząć, naciśnij poniższy
|
||||||
|
przycisk:
|
||||||
|
</p>
|
||||||
|
<NuxtLink to="/basic">START!</NuxtLink>
|
||||||
|
</div>
|
||||||
|
</template>
|
8333
pnpm-lock.yaml
generated
Normal file
8333
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load diff
73
server/api/advanced.get.ts
Normal file
73
server/api/advanced.get.ts
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
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 { AdvancedQuestion } from "~/types/basic";
|
||||||
|
|
||||||
|
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,
|
||||||
|
|
||||||
|
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)
|
||||||
|
)
|
||||||
|
// sql`lower(${dane.poprawna_odp})='a' or lower(${dane.poprawna_odp})='b' or lower(${dane.poprawna_odp})='c'`
|
||||||
|
// sql`${dane.odp_a} is not null or ${dane.odp_b} is not null or ${dane.odp_c} is not null`
|
||||||
|
);
|
||||||
|
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--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return randomizedQuestions;
|
||||||
|
});
|
70
server/api/basic.get.ts
Normal file
70
server/api/basic.get.ts
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
import "dotenv/config";
|
||||||
|
import { drizzle } from "drizzle-orm/node-postgres";
|
||||||
|
import { dane, punkty } from "@/src/db/schema";
|
||||||
|
import { sql, eq } from "drizzle-orm";
|
||||||
|
import { BasicQuestion } from "~/types/basic";
|
||||||
|
import arrayShuffle from "array-shuffle";
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
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,
|
||||||
|
})
|
||||||
|
.from(dane)
|
||||||
|
.innerJoin(punkty, eq(dane.nr_pytania, punkty.nr_pytania))
|
||||||
|
.where(
|
||||||
|
sql`(lower(${dane.poprawna_odp})='tak' or lower(${
|
||||||
|
dane.poprawna_odp
|
||||||
|
})='nie') and ${punkty.liczba_pkt}=${+points}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const query = getQuery(event);
|
||||||
|
const category = query.category;
|
||||||
|
const db = drizzle(process.env.DATABASE_URL!);
|
||||||
|
|
||||||
|
const randomizedQuestions: BasicQuestion[] = [];
|
||||||
|
|
||||||
|
for (let [key, value] of Object.entries({ 1: 4, 2: 6, 3: 10 })) {
|
||||||
|
const questionsKeyPoints: BasicQuestion[] = await getFromDb(key);
|
||||||
|
const chosenRandomQuestions: BasicQuestion[] = [];
|
||||||
|
|
||||||
|
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(",")
|
||||||
|
.filter((q) =>
|
||||||
|
q
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(
|
||||||
|
`${typeof category === "string" ? category.toLowerCase() : "b"}`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
chosenRandomQuestions.push(questionsKeyPoints[randomized]);
|
||||||
|
} else {
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chosenRandomQuestions.forEach((q) => randomizedQuestions.push(q));
|
||||||
|
}
|
||||||
|
return arrayShuffle(randomizedQuestions);
|
||||||
|
});
|
3
server/tsconfig.json
Normal file
3
server/tsconfig.json
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"extends": "../.nuxt/tsconfig.server.json"
|
||||||
|
}
|
34
src/db/schema.ts
Normal file
34
src/db/schema.ts
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import { integer, pgTable, text } from "drizzle-orm/pg-core";
|
||||||
|
|
||||||
|
export const dane = pgTable("dane", {
|
||||||
|
id: integer().primaryKey().notNull(),
|
||||||
|
nr_pytania: integer().notNull(),
|
||||||
|
pytanie: text().notNull(),
|
||||||
|
odp_a: text(),
|
||||||
|
odp_b: text(),
|
||||||
|
odp_c: text(),
|
||||||
|
poprawna_odp: text().notNull(),
|
||||||
|
media: text(),
|
||||||
|
kategorie: text().notNull(),
|
||||||
|
nazwa_media_pjm_tresc_pyt: text(),
|
||||||
|
nazwa_media_pjm_tresc_odp_a: text(),
|
||||||
|
nazwa_media_pjm_tresc_odp_b: text(),
|
||||||
|
nazwa_media_pjm_tresc_odp_c: text(),
|
||||||
|
pytanie_eng: text().notNull(),
|
||||||
|
odp_a_eng: text(),
|
||||||
|
odp_b_eng: text(),
|
||||||
|
odp_c_eng: text(),
|
||||||
|
pytanie_de: text().notNull(),
|
||||||
|
odp_a_de: text(),
|
||||||
|
odp_b_de: text(),
|
||||||
|
odp_c_de: text(),
|
||||||
|
pytanie_ua: text(),
|
||||||
|
odp_a_ua: text(),
|
||||||
|
odp_b_ua: text(),
|
||||||
|
odp_c_ua: text(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const punkty = pgTable("punkty", {
|
||||||
|
nr_pytania: integer().primaryKey().notNull(),
|
||||||
|
liczba_pkt: integer().notNull(),
|
||||||
|
});
|
4
tsconfig.json
Normal file
4
tsconfig.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
// https://nuxt.com/docs/guide/concepts/typescript
|
||||||
|
"extends": "./.nuxt/tsconfig.json"
|
||||||
|
}
|
46
types/basic.ts
Normal file
46
types/basic.ts
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
export interface BasicQuestion {
|
||||||
|
id: number;
|
||||||
|
nr_pytania: number;
|
||||||
|
pytanie: string;
|
||||||
|
// odp_a: null;
|
||||||
|
// odp_b: null;
|
||||||
|
// odp_c: null;
|
||||||
|
poprawna_odp: string;
|
||||||
|
media: string | null;
|
||||||
|
kategorie: string;
|
||||||
|
nazwa_media_pjm_tresc_pyt: string | null;
|
||||||
|
// nazwa_media_pjm_tresc_odp_a: string | null;
|
||||||
|
// nazwa_media_pjm_tresc_odp_b: string | null;
|
||||||
|
// nazwa_media_pjm_tresc_odp_c: string | null;
|
||||||
|
pytanie_eng: string;
|
||||||
|
// odp_a_eng: string | null;
|
||||||
|
// odp_b_eng: string | null;
|
||||||
|
// odp_c_eng: string | null;
|
||||||
|
pytanie_de: string;
|
||||||
|
// odp_a_de: string | null;
|
||||||
|
// odp_b_de: string | null;
|
||||||
|
// odp_c_de: string | null;
|
||||||
|
pytanie_ua: string | null;
|
||||||
|
// odp_a_ua: string | null;
|
||||||
|
// odp_b_ua: string | null;
|
||||||
|
// odp_c_ua: string | null;
|
||||||
|
liczba_pkt: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AdvancedQuestion extends BasicQuestion {
|
||||||
|
odp_a: string;
|
||||||
|
odp_b: string;
|
||||||
|
odp_c: string;
|
||||||
|
nazwa_media_pjm_tresc_odp_a: string | null;
|
||||||
|
nazwa_media_pjm_tresc_odp_b: string | null;
|
||||||
|
nazwa_media_pjm_tresc_odp_c: string | null;
|
||||||
|
odp_a_eng: string;
|
||||||
|
odp_b_eng: string;
|
||||||
|
odp_c_eng: string;
|
||||||
|
odp_a_de: string;
|
||||||
|
odp_b_de: string;
|
||||||
|
odp_c_de: string;
|
||||||
|
odp_a_ua: string | null;
|
||||||
|
odp_b_ua: string | null;
|
||||||
|
odp_c_ua: string | null;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue