Format
This commit is contained in:
parent
52eb07a993
commit
0fde080ab8
8 changed files with 555 additions and 376 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="hu">
|
<html lang="hu">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
|
|
|
||||||
156
backend/server.test.js
Normal file
156
backend/server.test.js
Normal file
|
|
@ -0,0 +1,156 @@
|
||||||
|
const { test, before, after, beforeEach } = require("node:test");
|
||||||
|
const assert = require("node:assert");
|
||||||
|
const fs = require("node:fs");
|
||||||
|
const os = require("node:os");
|
||||||
|
const path = require("node:path");
|
||||||
|
|
||||||
|
// Point the server at a throwaway data dir before importing it, so tests never
|
||||||
|
// touch real question data.
|
||||||
|
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "fizika-test-"));
|
||||||
|
const dataPath = path.join(tmpDir, "fizika.json");
|
||||||
|
const picsPath = path.join(tmpDir, "pics");
|
||||||
|
fs.mkdirSync(picsPath, { recursive: true });
|
||||||
|
|
||||||
|
process.env.DATA_PATH = dataPath;
|
||||||
|
process.env.PICS_PATH = picsPath;
|
||||||
|
|
||||||
|
const { app, isUnsafeFilename } = require("./server");
|
||||||
|
|
||||||
|
const seedQuestions = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
source: "2016/m1/1",
|
||||||
|
description: "q1",
|
||||||
|
a: "a",
|
||||||
|
b: "b",
|
||||||
|
c: "c",
|
||||||
|
d: "d",
|
||||||
|
correct: 1,
|
||||||
|
type: "mk",
|
||||||
|
image: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
source: "2016/m1/2",
|
||||||
|
description: "q2",
|
||||||
|
a: "a",
|
||||||
|
b: "b",
|
||||||
|
c: "c",
|
||||||
|
d: "d",
|
||||||
|
correct: 2,
|
||||||
|
type: "md",
|
||||||
|
image: null,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let server;
|
||||||
|
let baseUrl;
|
||||||
|
|
||||||
|
const api = (route, options) => fetch(`${baseUrl}${route}`, options);
|
||||||
|
const sendJson = (route, method, body) =>
|
||||||
|
api(route, {
|
||||||
|
method,
|
||||||
|
headers: { "content-type": "application/json" },
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
server = app.listen(0);
|
||||||
|
await new Promise((resolve) => server.once("listening", resolve));
|
||||||
|
baseUrl = `http://127.0.0.1:${server.address().port}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
after(() => {
|
||||||
|
server.close();
|
||||||
|
fs.rmSync(tmpDir, { recursive: true, force: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fs.writeFileSync(dataPath, JSON.stringify(seedQuestions, null, 2));
|
||||||
|
});
|
||||||
|
|
||||||
|
test("GET /api/fizika returns every question", async () => {
|
||||||
|
const res = await api("/api/fizika");
|
||||||
|
assert.equal(res.status, 200);
|
||||||
|
const body = await res.json();
|
||||||
|
assert.equal(body.length, 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("POST creates a question with an incremented id", async () => {
|
||||||
|
const res = await sendJson("/api/admin/questions", "POST", {
|
||||||
|
source: "2020/1/1",
|
||||||
|
description: "new",
|
||||||
|
a: "a",
|
||||||
|
b: "b",
|
||||||
|
c: "c",
|
||||||
|
d: "d",
|
||||||
|
correct: 3,
|
||||||
|
type: "h",
|
||||||
|
image: null,
|
||||||
|
});
|
||||||
|
assert.equal(res.status, 201);
|
||||||
|
const created = await res.json();
|
||||||
|
assert.equal(created.id, 3);
|
||||||
|
|
||||||
|
const all = await (await api("/api/fizika")).json();
|
||||||
|
assert.equal(all.length, 3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("PUT updates an existing question", async () => {
|
||||||
|
const res = await sendJson("/api/admin/questions/1", "PUT", {
|
||||||
|
description: "updated",
|
||||||
|
});
|
||||||
|
assert.equal(res.status, 200);
|
||||||
|
const updated = await res.json();
|
||||||
|
assert.equal(updated.description, "updated");
|
||||||
|
// unchanged fields are preserved
|
||||||
|
assert.equal(updated.source, "2016/m1/1");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("PUT returns 404 for a missing question", async () => {
|
||||||
|
const res = await sendJson("/api/admin/questions/999", "PUT", { a: "x" });
|
||||||
|
assert.equal(res.status, 404);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("DELETE removes a question", async () => {
|
||||||
|
const res = await api("/api/admin/questions/1", { method: "DELETE" });
|
||||||
|
assert.equal(res.status, 200);
|
||||||
|
const all = await (await api("/api/fizika")).json();
|
||||||
|
assert.equal(all.length, 1);
|
||||||
|
assert.equal(all[0].id, 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("DELETE returns 404 for a missing question", async () => {
|
||||||
|
const res = await api("/api/admin/questions/999", { method: "DELETE" });
|
||||||
|
assert.equal(res.status, 404);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("DELETE image rejects an unsafe filename", async () => {
|
||||||
|
// Percent-encoded so the path survives client-side URL normalization and
|
||||||
|
// reaches the route with a separator the guard must reject.
|
||||||
|
const res = await api(`/api/admin/images/${encodeURIComponent("a\\b")}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
});
|
||||||
|
assert.equal(res.status, 400);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("DELETE image returns 404 for a missing but valid filename", async () => {
|
||||||
|
const res = await api("/api/admin/images/nope.png", { method: "DELETE" });
|
||||||
|
assert.equal(res.status, 404);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("unknown routes return 404 JSON", async () => {
|
||||||
|
const res = await api("/api/does-not-exist");
|
||||||
|
assert.equal(res.status, 404);
|
||||||
|
const body = await res.json();
|
||||||
|
assert.equal(body.error, "Not found");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("isUnsafeFilename blocks traversal but allows plain names", () => {
|
||||||
|
for (const bad of ["../etc", "a/b", "a\\b", "..", ".", "/abs.png", ""]) {
|
||||||
|
assert.equal(isUnsafeFilename(bad), true, `${bad} should be unsafe`);
|
||||||
|
}
|
||||||
|
for (const ok of ["pic.png", "image_1.jpg", "2016-m1-1.png"]) {
|
||||||
|
assert.equal(isUnsafeFilename(ok), false, `${ok} should be safe`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -1,31 +1,32 @@
|
||||||
.button {
|
.button {
|
||||||
font-family: "Roboto", serif;
|
font-family: "Roboto", serif;
|
||||||
color: #003366;
|
color: #003366;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
padding: 0.75em;
|
padding: 0.75em;
|
||||||
margin: 1em;
|
margin: 1em;
|
||||||
width: auto;
|
width: auto;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: rgba(0,0,0,0);
|
background-color: rgba(0, 0, 0, 0);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-width: 3px;
|
border-width: 3px;
|
||||||
border-color: #003366;
|
border-color: #003366;
|
||||||
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.15), 0 6px 20px 0 rgba(0,0,0,0.15);
|
box-shadow:
|
||||||
-webkit-user-select: none;
|
0 8px 16px 0 rgba(0, 0, 0, 0.15),
|
||||||
-moz-user-select: none;
|
0 6px 20px 0 rgba(0, 0, 0, 0.15);
|
||||||
-ms-user-select: none;
|
-webkit-user-select: none;
|
||||||
user-select: none;
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
.button:hover {
|
.button:hover {
|
||||||
box-shadow:none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
@media only screen and (max-width: 1000px){
|
@media only screen and (max-width: 1000px) {
|
||||||
.button {
|
.button {
|
||||||
font-size: 1.45em;
|
font-size: 1.45em;
|
||||||
padding: 0.3em;
|
padding: 0.3em;
|
||||||
margin: 0.15em;
|
margin: 0.15em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,45 +1,47 @@
|
||||||
.card {
|
.card {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
padding: 2em;
|
padding: 2em;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
margin: 2em 0em 2em 0em;
|
margin: 2em 0em 2em 0em;
|
||||||
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.5), 0 6px 20px 0 rgba(0,0,0,0.09);
|
box-shadow:
|
||||||
height: auto;
|
0 8px 16px 0 rgba(0, 0, 0, 0.5),
|
||||||
width: auto;
|
0 6px 20px 0 rgba(0, 0, 0, 0.09);
|
||||||
overflow: auto;
|
height: auto;
|
||||||
|
width: auto;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
h2 {
|
h2 {
|
||||||
font-family: "Roboto", sans-serif;
|
font-family: "Roboto", sans-serif;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #0A0F14;
|
color: #0a0f14;
|
||||||
}
|
}
|
||||||
pre {
|
pre {
|
||||||
text-align: justify;
|
text-align: justify;
|
||||||
font-family: "Open sans", sans-serif;
|
font-family: "Open sans", sans-serif;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
img {
|
img {
|
||||||
display: block;
|
display: block;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
float: right;
|
float: right;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
-ms-user-select: none;
|
-ms-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
margin: 1px;
|
margin: 1px;
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
}
|
}
|
||||||
@media only screen and (max-width: 1000px){
|
@media only screen and (max-width: 1000px) {
|
||||||
h2 {
|
h2 {
|
||||||
font-size: 1.6em;
|
font-size: 1.6em;
|
||||||
}
|
}
|
||||||
pre {
|
pre {
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,268 +1,276 @@
|
||||||
body {
|
body {
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #003366;
|
color: #003366;
|
||||||
background-image: url("../auxIMG/bg.jpg");
|
background-image: url("../auxIMG/bg.jpg");
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
background-repeat: repeat;
|
background-repeat: repeat;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
::-moz-selection {
|
::-moz-selection {
|
||||||
background: #003366;
|
background: #003366;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-shadow: none;
|
text-shadow: none;
|
||||||
}
|
}
|
||||||
::selection {
|
::selection {
|
||||||
background: #003366;
|
background: #003366;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-shadow: none;
|
text-shadow: none;
|
||||||
}
|
}
|
||||||
h1:hover {
|
h1:hover {
|
||||||
text-shadow: 0.3px 0.3px #002D5B,
|
text-shadow:
|
||||||
0.6px 0.6px #002851,
|
0.3px 0.3px #002d5b,
|
||||||
1px 1px #002347,
|
0.6px 0.6px #002851,
|
||||||
1.3px 1.3px #001E3D,
|
1px 1px #002347,
|
||||||
1.6px 1.6px #001933,
|
1.3px 1.3px #001e3d,
|
||||||
2px 2px #001326,
|
1.6px 1.6px #001933,
|
||||||
2.3px 2.3px #000E1C,
|
2px 2px #001326,
|
||||||
2.6px 2.6px #000A14,
|
2.3px 2.3px #000e1c,
|
||||||
3px 3px #00070F,
|
2.6px 2.6px #000a14,
|
||||||
3.3px 3.3px #00050A,
|
3px 3px #00070f,
|
||||||
3.6px 3.6px #000205,
|
3.3px 3.3px #00050a,
|
||||||
4px 4px #000000;
|
3.6px 3.6px #000205,
|
||||||
|
4px 4px #000000;
|
||||||
}
|
}
|
||||||
h1 {
|
h1 {
|
||||||
font-family: "Poiret One", "Montserrat", serif;
|
font-family: "Poiret One", "Montserrat", serif;
|
||||||
font-size: 5em;
|
font-size: 5em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 0.2em 0 0.3em 0;
|
margin: 0.2em 0 0.3em 0;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
-ms-user-select: none;
|
-ms-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
display: inline;
|
display: inline;
|
||||||
transition: all 0.6s ease-out;
|
transition: all 0.6s ease-out;
|
||||||
}
|
}
|
||||||
#titlebox {
|
#titlebox {
|
||||||
padding-bottom: 0.5em;
|
padding-bottom: 0.5em;
|
||||||
}
|
}
|
||||||
hr {
|
hr {
|
||||||
border-bottom: 2px solid #003366;
|
border-bottom: 2px solid #003366;
|
||||||
width: 35%;
|
width: 35%;
|
||||||
}
|
}
|
||||||
.menu {
|
.menu {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
-ms-user-select: none;
|
-ms-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
ul {
|
ul {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
li {
|
li {
|
||||||
font-family: "Roboto", serif;
|
font-family: "Roboto", serif;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0.5em 1em;
|
padding: 0.5em 1em;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
}
|
}
|
||||||
li:hover {
|
li:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-shadow: 1px 1px 1px #0A0F14;
|
text-shadow: 1px 1px 1px #0a0f14;
|
||||||
}
|
}
|
||||||
#wrapper {
|
#wrapper {
|
||||||
width: 75%;
|
width: 75%;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
padding-top: 0.5em;
|
padding-top: 0.5em;
|
||||||
}
|
}
|
||||||
#bfooldal {
|
#bfooldal {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
.szoveg, #buttonwrapper {
|
.szoveg,
|
||||||
width: 80%;
|
#buttonwrapper {
|
||||||
margin: auto;
|
width: 80%;
|
||||||
|
margin: auto;
|
||||||
}
|
}
|
||||||
p:first-of-type {
|
p:first-of-type {
|
||||||
padding-top: 2em;
|
padding-top: 2em;
|
||||||
}
|
}
|
||||||
p {
|
p {
|
||||||
font-family: "Open sans", sans-serif;
|
font-family: "Open sans", sans-serif;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
font-size: 1.3em;
|
font-size: 1.3em;
|
||||||
color: #0A0F14;
|
color: #0a0f14;
|
||||||
text-align: justify;
|
text-align: justify;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
padding: 0.5em 0;
|
padding: 0.5em 0;
|
||||||
}
|
}
|
||||||
p:last-of-type {
|
p:last-of-type {
|
||||||
padding-bottom: 2em;
|
padding-bottom: 2em;
|
||||||
}
|
}
|
||||||
.buttonwrapper {
|
.buttonwrapper {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
#teszt, #eredmenyek, #kereses, #temakor {
|
#teszt,
|
||||||
display: none;
|
#eredmenyek,
|
||||||
|
#kereses,
|
||||||
|
#temakor {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
#temak {
|
#temak {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
.fele {
|
.fele {
|
||||||
width: 40%;
|
width: 40%;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
#bal {
|
#bal {
|
||||||
float: left;
|
float: left;
|
||||||
margin-left: 20%;
|
margin-left: 20%;
|
||||||
}
|
}
|
||||||
#jobb {
|
#jobb {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
.negyzet {
|
.negyzet {
|
||||||
margin-left: 1.5em;
|
margin-left: 1.5em;
|
||||||
font-family: "Open sans", sans-serif;
|
font-family: "Open sans", sans-serif;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
.main {
|
.main {
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
font-family: "Roboto", serif;
|
font-family: "Roboto", serif;
|
||||||
}
|
}
|
||||||
#numberof {
|
#numberof {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border: 2px solid #ccc;
|
border: 2px solid #ccc;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
width: 63%;
|
width: 63%;
|
||||||
}
|
}
|
||||||
.f2006, .f2016 {
|
.f2006,
|
||||||
display: none;
|
.f2016 {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
#load, #loadingGif {
|
#load,
|
||||||
display: none;
|
#loadingGif {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
#loading {
|
#loading {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
#loadingGif {
|
#loadingGif {
|
||||||
float: none;
|
float: none;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
padding-bottom: 2em;
|
padding-bottom: 2em;
|
||||||
}
|
}
|
||||||
#megoldas {
|
#megoldas {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
#percentage {
|
#percentage {
|
||||||
font-family: "Poiret One", "Montserrat", serif;
|
font-family: "Poiret One", "Montserrat", serif;
|
||||||
font-size: 3em;
|
font-size: 3em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
#state, #state2 {
|
#state,
|
||||||
font-weight: 300;
|
#state2 {
|
||||||
font-size: 2em;
|
font-weight: 300;
|
||||||
text-align: center;
|
font-size: 2em;
|
||||||
padding: 0.6em;
|
text-align: center;
|
||||||
|
padding: 0.6em;
|
||||||
}
|
}
|
||||||
#content {
|
#content {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border: 2px solid #ccc;
|
border: 2px solid #ccc;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-size: 1.25em;
|
font-size: 1.25em;
|
||||||
color: #0A0F14;
|
color: #0a0f14;
|
||||||
width: 26%;
|
width: 26%;
|
||||||
padding: 12px 20px 12px 40px;
|
padding: 12px 20px 12px 40px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
margin : auto;
|
margin: auto;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
|
||||||
th, td {
|
|
||||||
text-align: left;
|
|
||||||
padding: 0.5em;
|
|
||||||
}
|
}
|
||||||
tr:nth-child(even){
|
th,
|
||||||
background-color: #f2f2f2;
|
td {
|
||||||
|
text-align: left;
|
||||||
|
padding: 0.5em;
|
||||||
}
|
}
|
||||||
th {
|
tr:nth-child(even) {
|
||||||
background-color: #003366;
|
background-color: #f2f2f2;
|
||||||
color: white;
|
}
|
||||||
|
th {
|
||||||
|
background-color: #003366;
|
||||||
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
font-size: 0.75em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 1000px) {
|
||||||
|
body {
|
||||||
|
font-size: 1.75em;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 7em;
|
||||||
|
}
|
||||||
|
h1:hover {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
#wrapper {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
.szoveg {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
#numberof {
|
||||||
|
font-size: 0.6em;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
max-width: 400px;
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
font-size: 0.8em;
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
hr {
|
||||||
|
border-bottom-width: 4px;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
font-size: 1.75em;
|
||||||
|
padding: 0.25em;
|
||||||
|
}
|
||||||
|
p {
|
||||||
font-size: 0.75em;
|
font-size: 0.75em;
|
||||||
}
|
}
|
||||||
|
p:first-of-type {
|
||||||
|
padding-top: 0.5em;
|
||||||
|
}
|
||||||
|
p:last-of-type {
|
||||||
|
padding-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 1000px){
|
#tablazat {
|
||||||
body {
|
font-size: 0.8em;
|
||||||
font-size: 1.75em;
|
}
|
||||||
}
|
.mbcheck {
|
||||||
h1 {
|
font-size: 0.75em;
|
||||||
font-size: 7em;
|
}
|
||||||
}
|
#bal {
|
||||||
h1:hover {
|
margin-left: 0;
|
||||||
text-shadow: none;
|
}
|
||||||
}
|
|
||||||
#wrapper {
|
|
||||||
width: 90%;
|
|
||||||
}
|
|
||||||
.szoveg {
|
|
||||||
width: 90%;
|
|
||||||
}
|
|
||||||
#numberof {
|
|
||||||
font-size: 0.6em;
|
|
||||||
}
|
|
||||||
img {
|
|
||||||
max-width: 400px;
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
font-size: 0.8em;
|
|
||||||
width: 30%;
|
|
||||||
}
|
|
||||||
hr {
|
|
||||||
border-bottom-width: 4px;
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
li {
|
|
||||||
font-size: 1.75em;
|
|
||||||
padding: 0.25em;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
font-size: 0.75em;
|
|
||||||
}
|
|
||||||
p:first-of-type {
|
|
||||||
padding-top: 0.5em;
|
|
||||||
}
|
|
||||||
p:last-of-type {
|
|
||||||
padding-bottom: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tablazat {
|
|
||||||
font-size: 0.8em;
|
|
||||||
}
|
|
||||||
.mbcheck {
|
|
||||||
font-size: 0.75em;
|
|
||||||
}
|
|
||||||
#bal {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,44 +1,44 @@
|
||||||
#preload {
|
#preload {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=radio] {
|
input[type="radio"] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
input[type=radio] {
|
input[type="radio"] {
|
||||||
width: 28px;
|
width: 28px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
input[type=radio] + label {
|
input[type="radio"] + label {
|
||||||
display: inline;
|
display: inline;
|
||||||
font-family: "Open Sans", sans-serif;
|
font-family: "Open Sans", sans-serif;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
font-size: 1.3em;
|
font-size: 1.3em;
|
||||||
margin-left: -28px;
|
margin-left: -28px;
|
||||||
padding-left: 28px;
|
padding-left: 28px;
|
||||||
background: url('../auxIMG/unchecked.svg') no-repeat 0 50%;
|
background: url("../auxIMG/unchecked.svg") no-repeat 0 50%;
|
||||||
line-height: 35px;
|
line-height: 35px;
|
||||||
background-size: 28px 28px;
|
background-size: 28px 28px;
|
||||||
margin-bottom: 6.25em;
|
margin-bottom: 6.25em;
|
||||||
}
|
}
|
||||||
input[type=radio]:checked + label {
|
input[type="radio"]:checked + label {
|
||||||
background: url('../auxIMG/checked.svg') no-repeat 0 50%;
|
background: url("../auxIMG/checked.svg") no-repeat 0 50%;
|
||||||
background-size: 28px 28px;
|
background-size: 28px 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 1000px){
|
@media only screen and (max-width: 1000px) {
|
||||||
input[type=radio] {
|
input[type="radio"] {
|
||||||
width: 60px;
|
width: 60px;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
}
|
}
|
||||||
input[type=radio] + label {
|
input[type="radio"] + label {
|
||||||
margin-left: -60px;
|
margin-left: -60px;
|
||||||
padding-left: 60px;
|
padding-left: 60px;
|
||||||
background-size: 60px 60px;
|
background-size: 60px 60px;
|
||||||
}
|
}
|
||||||
input[type=radio]:checked + label {
|
input[type="radio"]:checked + label {
|
||||||
background-size: 60px 60px;
|
background-size: 60px 60px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="hu-HU">
|
<html lang="hu-HU">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
|
|
@ -92,10 +92,14 @@
|
||||||
<p>
|
<p>
|
||||||
A Tesztek fülre kattintva juthatsz el a gyakorló feladatlapokig,
|
A Tesztek fülre kattintva juthatsz el a gyakorló feladatlapokig,
|
||||||
amiket <b>a te beállításaid alapján</b> állít össze az alkalmazás. Ezt
|
amiket <b>a te beállításaid alapján</b> állít össze az alkalmazás. Ezt
|
||||||
egy <b>659 kérdést tartalmazó adatbázisból</b> viszi véghez, melyet az
|
egy
|
||||||
előző <b>több mint 10 év</b> érettségijeinek feladatai alkotnak. Ebben
|
<b
|
||||||
a menüpontban nem csak témakör, hanem év alapján is
|
><span id="questionCount">682</span> kérdést tartalmazó
|
||||||
<b>rákereshetsz a feladatokra</b>.
|
adatbázisból</b
|
||||||
|
>
|
||||||
|
viszi véghez, melyet az előző <b>több mint 10 év</b> érettségijeinek
|
||||||
|
feladatai alkotnak. Ebben a menüpontban nem csak témakör, hanem év
|
||||||
|
alapján is <b>rákereshetsz a feladatokra</b>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
A teszteken elért pontjaidat, és azokkal kapcsolatos egyéb infókat, az
|
A teszteken elért pontjaidat, és azokkal kapcsolatos egyéb infókat, az
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,13 @@ async function ajaxLoad(type) {
|
||||||
try {
|
try {
|
||||||
if (type == 1) {
|
if (type == 1) {
|
||||||
var source =
|
var source =
|
||||||
"^" + $("#evszam").val() + $("#honap").val() + $("#feladat").val() + "$";
|
"^" +
|
||||||
|
$("#evszam").val() +
|
||||||
|
$("#honap").val() +
|
||||||
|
$("#feladat").val() +
|
||||||
|
"$";
|
||||||
for (var i = 0; i <= 3; i++) {
|
for (var i = 0; i <= 3; i++) {
|
||||||
source = source.replace("all", ".*");
|
source = source.replace("all", ".*");
|
||||||
console.log(source);
|
|
||||||
}
|
}
|
||||||
result = await loadQuestions(true, undefined, source, 1000000);
|
result = await loadQuestions(true, undefined, source, 1000000);
|
||||||
} else if (type == 2) {
|
} else if (type == 2) {
|
||||||
|
|
@ -56,7 +59,7 @@ async function ajaxLoad(type) {
|
||||||
"v",
|
"v",
|
||||||
],
|
],
|
||||||
undefined,
|
undefined,
|
||||||
15
|
15,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
var NOQ = $("#numberof").val() ? $("#numberof").val() : 15;
|
var NOQ = $("#numberof").val() ? $("#numberof").val() : 15;
|
||||||
|
|
@ -109,7 +112,7 @@ async function ajaxLoad(type) {
|
||||||
</div>
|
</div>
|
||||||
`);
|
`);
|
||||||
$("#state").html("Hiba a feladatok betöltésekor");
|
$("#state").html("Hiba a feladatok betöltésekor");
|
||||||
console.error('Quiz loading error:', error);
|
console.error("Quiz loading error:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,15 +120,15 @@ function showCorrect(id, correctAns) {
|
||||||
teszt(id, correctAns);
|
teszt(id, correctAns);
|
||||||
eval(
|
eval(
|
||||||
"$('" +
|
"$('" +
|
||||||
"#label" +
|
"#label" +
|
||||||
id +
|
id +
|
||||||
".rad" +
|
".rad" +
|
||||||
correctAns +
|
correctAns +
|
||||||
"').css('background-color', '#C6FF8C');"
|
"').css('background-color', '#C6FF8C');",
|
||||||
);
|
);
|
||||||
$("#state").html("Helyes válaszok bejelölve!");
|
$("#state").html("Helyes válaszok bejelölve!");
|
||||||
$("#state2").html(
|
$("#state2").html(
|
||||||
"(Ellenőrző mód, az itteni eredményeid nem kerülnek elmentésre, a módból való kilépéshez tölts be egy új tesztsort!)"
|
"(Ellenőrző mód, az itteni eredményeid nem kerülnek elmentésre, a módból való kilépéshez tölts be egy új tesztsort!)",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -140,7 +143,6 @@ function teszt(id, correctAns) {
|
||||||
} else {
|
} else {
|
||||||
$(div).animate({ backgroundColor: "#FF808C" }, 1100);
|
$(div).animate({ backgroundColor: "#FF808C" }, 1100);
|
||||||
}
|
}
|
||||||
console.log(currentPoints, totalPoints, correctAnswersGiven);
|
|
||||||
if (currentPoints >= totalPoints) {
|
if (currentPoints >= totalPoints) {
|
||||||
var percentage = (correctAnswersGiven / totalPoints) * 100;
|
var percentage = (correctAnswersGiven / totalPoints) * 100;
|
||||||
percentage = Math.round(percentage * 100) / 100;
|
percentage = Math.round(percentage * 100) / 100;
|
||||||
|
|
@ -151,30 +153,34 @@ function teszt(id, correctAns) {
|
||||||
var datum = new Date();
|
var datum = new Date();
|
||||||
var ido = Math.round(timer / 60);
|
var ido = Math.round(timer / 60);
|
||||||
eval(
|
eval(
|
||||||
"localStorage.teszt" + numberOfPreviousTests + " = '" + percentage + "'"
|
"localStorage.teszt" +
|
||||||
|
numberOfPreviousTests +
|
||||||
|
" = '" +
|
||||||
|
percentage +
|
||||||
|
"'",
|
||||||
);
|
);
|
||||||
eval(
|
eval(
|
||||||
"localStorage.teszt" +
|
"localStorage.teszt" +
|
||||||
numberOfPreviousTests +
|
numberOfPreviousTests +
|
||||||
"date = '" +
|
"date = '" +
|
||||||
datum.toLocaleDateString() +
|
datum.toLocaleDateString() +
|
||||||
"'"
|
"'",
|
||||||
);
|
);
|
||||||
eval(
|
eval(
|
||||||
"localStorage.teszt" + numberOfPreviousTests + "time = '" + ido + "'"
|
"localStorage.teszt" + numberOfPreviousTests + "time = '" + ido + "'",
|
||||||
);
|
);
|
||||||
eval(
|
eval(
|
||||||
"localStorage.teszt" +
|
"localStorage.teszt" +
|
||||||
numberOfPreviousTests +
|
numberOfPreviousTests +
|
||||||
"total = '" +
|
"total = '" +
|
||||||
totalPoints +
|
totalPoints +
|
||||||
"'"
|
"'",
|
||||||
);
|
);
|
||||||
startTimer = 0;
|
startTimer = 0;
|
||||||
timer = 0;
|
timer = 0;
|
||||||
$("#state2").show();
|
$("#state2").show();
|
||||||
$("#state2").html(
|
$("#state2").html(
|
||||||
"Eredményed mentésre került! Ellenőrző módba belépve az eredményeid nem kerülnek tárolásra. A módból való kilépéshez tölts be egy új tesztsort!"
|
"Eredményed mentésre került! Ellenőrző módba belépve az eredményeid nem kerülnek tárolásra. A módból való kilépéshez tölts be egy új tesztsort!",
|
||||||
);
|
);
|
||||||
eredmeny();
|
eredmeny();
|
||||||
reviewMode = 1;
|
reviewMode = 1;
|
||||||
|
|
@ -189,7 +195,7 @@ function scrollTo(where) {
|
||||||
{
|
{
|
||||||
scrollTop: $(where).offset().top - 100,
|
scrollTop: $(where).offset().top - 100,
|
||||||
},
|
},
|
||||||
1000
|
1000,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -208,7 +214,7 @@ function eredmeny() {
|
||||||
if (isLocal) {
|
if (isLocal) {
|
||||||
if (typeof localStorage.teszt1 !== "undefined") {
|
if (typeof localStorage.teszt1 !== "undefined") {
|
||||||
$("#tablazat").html(
|
$("#tablazat").html(
|
||||||
'<table id="ered"><tr><th></th><th>Dátum</th><th>Időtartam</th><th>Eredmény</th><th>Pontszám</th></tr></table>'
|
'<table id="ered"><tr><th></th><th>Dátum</th><th>Időtartam</th><th>Eredmény</th><th>Pontszám</th></tr></table>',
|
||||||
);
|
);
|
||||||
for (var i = 1; i < numberOfPreviousTests; i++) {
|
for (var i = 1; i < numberOfPreviousTests; i++) {
|
||||||
var localString = "localStorage.teszt" + i;
|
var localString = "localStorage.teszt" + i;
|
||||||
|
|
@ -218,21 +224,21 @@ function eredmeny() {
|
||||||
var isGood = eval(localString);
|
var isGood = eval(localString);
|
||||||
$("#ered tr:last").after(
|
$("#ered tr:last").after(
|
||||||
"<tr><td>" +
|
"<tr><td>" +
|
||||||
i +
|
i +
|
||||||
".</td><td>" +
|
".</td><td>" +
|
||||||
eval(datumString) +
|
eval(datumString) +
|
||||||
"</td><td>" +
|
"</td><td>" +
|
||||||
eval(timeString) +
|
eval(timeString) +
|
||||||
" perc</td>" +
|
" perc</td>" +
|
||||||
"<td style='color: hsl(" +
|
"<td style='color: hsl(" +
|
||||||
isGood +
|
isGood +
|
||||||
",100%,50%);''> <b>" +
|
",100%,50%);''> <b>" +
|
||||||
eval(localString) +
|
eval(localString) +
|
||||||
"%</b></td><td>" +
|
"%</b></td><td>" +
|
||||||
Math.round((eval(localString) * eval(totalString)) / 100) +
|
Math.round((eval(localString) * eval(totalString)) / 100) +
|
||||||
"/" +
|
"/" +
|
||||||
eval(totalString) +
|
eval(totalString) +
|
||||||
" pont</td></tr>"
|
" pont</td></tr>",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -240,7 +246,7 @@ function eredmeny() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$("#tablazat").html(
|
$("#tablazat").html(
|
||||||
"<h2>Sajnos a böngésződ nem támogatja ezt a funkciót, tölts le egy modernebbet vagy jelentkezz be!</h2>"
|
"<h2>Sajnos a böngésződ nem támogatja ezt a funkciót, tölts le egy modernebbet vagy jelentkezz be!</h2>",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -259,17 +265,17 @@ setInterval(function () {
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
eredmeny();
|
eredmeny();
|
||||||
|
|
||||||
// Initialize year dropdown with dynamic years from question data
|
// Initialize year dropdown with dynamic years from question data
|
||||||
if (typeof initializeYearDropdown === 'function') {
|
if (typeof initializeYearDropdown === "function") {
|
||||||
initializeYearDropdown().then(() => {
|
initializeYearDropdown().then(() => {
|
||||||
// Initialize month dropdown for default "all" year selection
|
// Initialize month dropdown for default "all" year selection
|
||||||
if (typeof initializeMonthDropdown === 'function') {
|
if (typeof initializeMonthDropdown === "function") {
|
||||||
initializeMonthDropdown('all/');
|
initializeMonthDropdown("all/");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$(window).on("mousewheel", function () {
|
$(window).on("mousewheel", function () {
|
||||||
$("body").stop();
|
$("body").stop();
|
||||||
});
|
});
|
||||||
|
|
@ -328,9 +334,9 @@ $(document).ready(function () {
|
||||||
});
|
});
|
||||||
$("#evszam").change(function () {
|
$("#evszam").change(function () {
|
||||||
const selectedYear = $("#evszam").val();
|
const selectedYear = $("#evszam").val();
|
||||||
|
|
||||||
// Initialize month dropdown dynamically based on selected year
|
// Initialize month dropdown dynamically based on selected year
|
||||||
if (typeof initializeMonthDropdown === 'function') {
|
if (typeof initializeMonthDropdown === "function") {
|
||||||
initializeMonthDropdown(selectedYear);
|
initializeMonthDropdown(selectedYear);
|
||||||
} else {
|
} else {
|
||||||
// Fallback to original logic if dynamic function not available
|
// Fallback to original logic if dynamic function not available
|
||||||
|
|
@ -356,7 +362,7 @@ $(document).ready(function () {
|
||||||
$(".fnem17").show();
|
$(".fnem17").show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#honap").val("all");
|
$("#honap").val("all");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -390,7 +396,7 @@ $(document).ready(function () {
|
||||||
{
|
{
|
||||||
scrollTop: $("#teszt").offset().top,
|
scrollTop: $("#teszt").offset().top,
|
||||||
},
|
},
|
||||||
3000
|
3000,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -419,28 +425,28 @@ $(document).ready(function () {
|
||||||
Math.max(
|
Math.max(
|
||||||
Math.min(
|
Math.min(
|
||||||
parseInt(g.pos * (g.end[0] - g.start[0]) + g.start[0]),
|
parseInt(g.pos * (g.end[0] - g.start[0]) + g.start[0]),
|
||||||
255
|
255,
|
||||||
),
|
),
|
||||||
0
|
0,
|
||||||
),
|
),
|
||||||
Math.max(
|
Math.max(
|
||||||
Math.min(
|
Math.min(
|
||||||
parseInt(g.pos * (g.end[1] - g.start[1]) + g.start[1]),
|
parseInt(g.pos * (g.end[1] - g.start[1]) + g.start[1]),
|
||||||
255
|
255,
|
||||||
),
|
),
|
||||||
0
|
0,
|
||||||
),
|
),
|
||||||
Math.max(
|
Math.max(
|
||||||
Math.min(
|
Math.min(
|
||||||
parseInt(g.pos * (g.end[2] - g.start[2]) + g.start[2]),
|
parseInt(g.pos * (g.end[2] - g.start[2]) + g.start[2]),
|
||||||
255
|
255,
|
||||||
),
|
),
|
||||||
0
|
0,
|
||||||
),
|
),
|
||||||
].join(",") +
|
].join(",") +
|
||||||
")";
|
")";
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
function b(f) {
|
function b(f) {
|
||||||
var e;
|
var e;
|
||||||
|
|
@ -448,16 +454,18 @@ $(document).ready(function () {
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
(e = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(
|
(e =
|
||||||
f
|
/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(
|
||||||
))
|
f,
|
||||||
|
))
|
||||||
) {
|
) {
|
||||||
return [parseInt(e[1]), parseInt(e[2]), parseInt(e[3])];
|
return [parseInt(e[1]), parseInt(e[2]), parseInt(e[3])];
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
(e = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(
|
(e =
|
||||||
f
|
/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(
|
||||||
))
|
f,
|
||||||
|
))
|
||||||
) {
|
) {
|
||||||
return [
|
return [
|
||||||
parseFloat(e[1]) * 2.55,
|
parseFloat(e[1]) * 2.55,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue