mirror of
https://github.com/jakobkordez/s5_practice.git
synced 2025-05-30 07:30:29 +00:00
Progress
This commit is contained in:
parent
d668df566c
commit
c887c724af
@ -1,3 +1,6 @@
|
||||
{
|
||||
"extends": ["next/core-web-vitals", "prettier"]
|
||||
"extends": ["next/core-web-vitals", "prettier"],
|
||||
"rules": {
|
||||
"no-unused-vars": "warn"
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ export default function IzpitQuiz() {
|
||||
|
||||
function inProgress() {
|
||||
return (
|
||||
<div className="mx-auto my-10 flex max-w-xl flex-col gap-12">
|
||||
<div className="container my-10 flex max-w-xl flex-col gap-12">
|
||||
{questions?.map((question, qi) => (
|
||||
<QuestionCard
|
||||
key={qi}
|
||||
@ -133,7 +133,7 @@ export default function IzpitQuiz() {
|
||||
<div className="my-10">
|
||||
<h1 className="my-10 text-center text-2xl">Napačni odgovori</h1>
|
||||
|
||||
<div className="mx-auto flex max-w-xl flex-col gap-12">
|
||||
<div className="container flex max-w-xl flex-col gap-12">
|
||||
{questions?.map(
|
||||
(question, qi) =>
|
||||
question.correct !== answers![qi][0] && (
|
||||
|
114
src/app/klicni-znak/callsign-tool.tsx
Normal file
114
src/app/klicni-znak/callsign-tool.tsx
Normal file
@ -0,0 +1,114 @@
|
||||
'use client';
|
||||
|
||||
import { robotoMono } from '@/fonts/fonts';
|
||||
import {
|
||||
faCheckCircle,
|
||||
faXmarkCircle,
|
||||
} from '@fortawesome/free-regular-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { useState } from 'react';
|
||||
|
||||
export default function CallsignTool() {
|
||||
const [clas, setClas] = useState(1);
|
||||
const [callsign, setCallsign] = useState('S50HQ');
|
||||
|
||||
return (
|
||||
<div className="container my-10 flex flex-col gap-6">
|
||||
<div className="flex flex-col gap-1">
|
||||
<label className="text-sm font-semibold">Izberi razred</label>
|
||||
<div className="flex flex-row gap-4">
|
||||
<button
|
||||
onClick={() => setClas(0)}
|
||||
className={`flex-1 rounded-lg border-4 bg-light py-2 font-semibold text-dark shadow ${
|
||||
!clas ? 'border-dark' : 'border-transparent'
|
||||
}`}
|
||||
>
|
||||
N razred
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setClas(1)}
|
||||
className={`flex-1 rounded-lg border-4 bg-light py-2 font-semibold text-dark shadow ${
|
||||
clas ? 'border-dark' : 'border-transparent'
|
||||
}`}
|
||||
>
|
||||
A razred
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1">
|
||||
<label className="text-sm font-semibold">Vnesi klicni znak</label>
|
||||
<input
|
||||
type="text"
|
||||
className={`rounded-lg border border-light py-3 text-center text-3xl uppercase shadow-lg ${robotoMono.className}`}
|
||||
value={callsign}
|
||||
onChange={(e) => setCallsign(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col overflow-clip rounded-lg">
|
||||
{tests
|
||||
.filter((test) =>
|
||||
test.preTest ? test.preTest(clas, callsign) : true
|
||||
)
|
||||
.map((test, i) => {
|
||||
const result = test.test(callsign);
|
||||
|
||||
return (
|
||||
<div
|
||||
key={i}
|
||||
className={`flex flex-row items-center gap-4 px-5 py-3 text-lg ${
|
||||
result ? 'bg-green-100' : 'bg-red-100'
|
||||
}`}
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={result ? faCheckCircle : faXmarkCircle}
|
||||
className={`w-5 ${
|
||||
result ? 'text-green-600' : 'text-red-600'
|
||||
}`}
|
||||
/>
|
||||
<span>{test.name}</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const tests = [
|
||||
{
|
||||
name: 'Se začne s S5',
|
||||
test: (callsign: string) => /^S5/i.test(callsign),
|
||||
},
|
||||
{
|
||||
name: 'Vsebuje eno številko',
|
||||
preTest: (clas: number, callsign: string) => /^S5/i.test(callsign),
|
||||
test: (callsign: string) => /^S5\d/i.test(callsign),
|
||||
},
|
||||
{
|
||||
name: 'Vsebuje eno do tri črke',
|
||||
preTest: (clas: number, callsign: string) =>
|
||||
clas === 1 && /^S5\d/i.test(callsign),
|
||||
test: (callsign: string) => /^S5\d[A-Z]{1,3}$/i.test(callsign),
|
||||
},
|
||||
{
|
||||
name: 'Vsebuje tri črke',
|
||||
preTest: (clas: number, callsign: string) =>
|
||||
clas === 0 && /^S5\d/i.test(callsign),
|
||||
test: (callsign: string) => /^S5\d[A-Z]{3}$/i.test(callsign),
|
||||
},
|
||||
{
|
||||
name: 'Ustreza razredu A',
|
||||
preTest: (clas: number, callsign: string) =>
|
||||
clas === 1 && /^S5\d[A-Z]{1,3}$/i.test(callsign),
|
||||
test: (callsign: string) =>
|
||||
/^S5(\d[A-Z]{1,2}|([0457][A-X]|[4678]Z)[A-Z]{2})$/i.test(callsign),
|
||||
},
|
||||
{
|
||||
name: 'Ustreza razredu N',
|
||||
preTest: (clas: number, callsign: string) =>
|
||||
clas === 0 && /^S5\d[A-Z]{3}$/i.test(callsign),
|
||||
test: (callsign: string) => /^S5(2[A-XZ]|8[A-X])[A-Z]{2}$/i.test(callsign),
|
||||
},
|
||||
];
|
27
src/app/klicni-znak/page.tsx
Normal file
27
src/app/klicni-znak/page.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import { SubHeader } from '@/components/sub_header';
|
||||
import { Metadata } from 'next';
|
||||
import CallsignTool from './callsign-tool';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Izbira klicnega znaka',
|
||||
description: 'Pomoč pri izbiri klicnega znaka',
|
||||
};
|
||||
|
||||
export default function Callsign() {
|
||||
return (
|
||||
<>
|
||||
<SubHeader title="Pomoč pri izbiri klicnega znaka">
|
||||
<p className="text-lg">
|
||||
Spodaj vpiši želen klicni znak in preveri, če je ta že zaseden in če
|
||||
je za pravi razred.
|
||||
</p>
|
||||
<p className="text-lg">
|
||||
Če v znaku uporabiš * (zvezdico), ti bodo prikazani vsi klicni znaki,
|
||||
ki ustrezajo vnesenemu vzorcu.
|
||||
</p>
|
||||
</SubHeader>
|
||||
|
||||
<CallsignTool />
|
||||
</>
|
||||
);
|
||||
}
|
@ -2,6 +2,7 @@ import { AnalyticsWrapper } from '@/components/analytics';
|
||||
import Header from '@/components/header';
|
||||
import { Metadata } from 'next';
|
||||
import '@/styles/globals.scss';
|
||||
import { morse } from '@/fonts/fonts';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
@ -42,7 +43,7 @@ export default function RootLayout({
|
||||
return (
|
||||
<html lang="sl">
|
||||
<head />
|
||||
<body>
|
||||
<body className={morse.variable}>
|
||||
<Header />
|
||||
|
||||
<main>{children}</main>
|
||||
|
@ -73,7 +73,7 @@ export default function License() {
|
||||
<p>
|
||||
Klicni znak si lahko izbereš glede na razred izpita, ki si ga opravil.
|
||||
</p>
|
||||
<div className="flex flex-col gap-6 md:flex-row">
|
||||
<div className="my-6 flex flex-col gap-6 md:flex-row">
|
||||
<div className="flex flex-1 flex-col gap-4 rounded-lg bg-light p-6 shadow-md">
|
||||
<h4 className="text-center">N razred</h4>
|
||||
|
||||
@ -96,6 +96,10 @@ export default function License() {
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<LinkButton href="/klicni-znak" className="w-full">
|
||||
Pomagaj izbrati klicni znak
|
||||
</LinkButton>
|
||||
</div>
|
||||
|
||||
<div className="flex bg-light">
|
||||
@ -106,7 +110,23 @@ export default function License() {
|
||||
digitalnim potrdilom), ali pa z izpolnjenim obrazcem poslanega po
|
||||
pošti.
|
||||
</p>
|
||||
<div className="flex flex-col gap-4 text-center md:flex-row">
|
||||
<p>
|
||||
Priporočljivo je, da na vlogi izpolniš vse tri klicne znake, ki jih
|
||||
želiš imeti v primeru, da je prvi klicni znak že zaseden ali pa ga
|
||||
zavrnejo.
|
||||
</p>
|
||||
<p>
|
||||
Od začetka leta 2023 se za izdajo in podaljšanje radioamaterskega
|
||||
dovoljenja <strong>plača uporabo dela radijskega spektra</strong>{' '}
|
||||
(frekvenčnino) v višini 60 točk. Točka je vredna 0,50 €.
|
||||
</p>
|
||||
<p>
|
||||
Radioamatersko dovoljenje velja 15 let, po tem času pa ga je
|
||||
potrebno podaljšati. Po poteku veljavnosti velja še 10 letni
|
||||
moratorij za klicni znak.
|
||||
</p>
|
||||
|
||||
<div className="mt-6 flex flex-col gap-4 text-center md:flex-row">
|
||||
<LinkButton className="flex-1" href="https://evloge.akos-rs.si/">
|
||||
Elektronska vloga
|
||||
</LinkButton>
|
||||
|
@ -1,13 +1,11 @@
|
||||
'use client';
|
||||
|
||||
import { morse } from '@/fonts/fonts';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Roboto_Mono } from 'next/font/google';
|
||||
|
||||
const robotoMono = Roboto_Mono({ subsets: ['latin'] });
|
||||
import { generateRandomCallsign } from '@/util/callsign-util';
|
||||
import { robotoMono } from '@/fonts/fonts';
|
||||
|
||||
export default function RandomCallsign() {
|
||||
const [callsign, setCallsign] = useState<string[]>('S50ZRS'.split(''));
|
||||
const [callsign, setCallsign] = useState<string>('S50ZRS');
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
@ -20,26 +18,9 @@ export default function RandomCallsign() {
|
||||
return (
|
||||
<div className="my-6 text-center">
|
||||
<div className={`text-4xl font-bold text-darker ${robotoMono.className}`}>
|
||||
{callsign.join('')}
|
||||
</div>
|
||||
<div className={`font-bold text-gray-500 ${morse.className}`}>
|
||||
{callsign.join(' ')}
|
||||
{callsign}
|
||||
</div>
|
||||
<div className={`morse font-bold text-gray-500`}>{callsign}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function generateRandomCallsign(): string[] {
|
||||
const length = Math.ceil(Math.random() * 3);
|
||||
const callsign = [
|
||||
'S',
|
||||
'5',
|
||||
String.fromCharCode(Math.floor(Math.random() * 10) + 48),
|
||||
];
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
callsign.push(String.fromCharCode(Math.floor(Math.random() * 26) + 65));
|
||||
}
|
||||
|
||||
return callsign;
|
||||
}
|
||||
|
216
src/app/page.tsx
216
src/app/page.tsx
@ -1,4 +1,4 @@
|
||||
import { faCheckCircle, faCircle } from '@fortawesome/free-regular-svg-icons';
|
||||
import { faCheckCircle } from '@fortawesome/free-regular-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Link from 'next/link';
|
||||
|
||||
@ -24,117 +24,122 @@ const povezave = [
|
||||
export default function Home() {
|
||||
return (
|
||||
<>
|
||||
<div className="content container my-10">
|
||||
<div className="content container my-12">
|
||||
<h3>Kaj je radioamaterstvo?</h3>
|
||||
<p>.... --- .-- / ... .... --- ..- .-.. -.. / .. / -.- -. --- .--</p>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
|
||||
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
|
||||
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
|
||||
aliquip ex ea commodo consequat. Duis aute irure dolor in
|
||||
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
|
||||
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
|
||||
culpa qui officia deserunt mollit anim id est laborum.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h3>Primerjava kategorij</h3>
|
||||
<div className="flex flex-col gap-6 md:flex-row">
|
||||
<div className="flex flex-1 flex-col gap-4 rounded-lg bg-light p-6 shadow-md">
|
||||
<h4 className="text-center">N razred</h4>
|
||||
<p>
|
||||
N razred je namenjen začetnikom, ki se šele spoznavajo z
|
||||
radioamaterstvom in niso še tako vešči v elektroniki.
|
||||
</p>
|
||||
<div className="bg-light">
|
||||
<div className="content container py-12">
|
||||
<h3 className="text-center">Primerjava kategorij</h3>
|
||||
<div className="flex flex-col items-center justify-center gap-6 md:flex-row md:items-stretch">
|
||||
<div className="flex max-w-sm flex-1 flex-col gap-4 rounded-2xl bg-white p-6">
|
||||
<h4 className="text-center">N razred</h4>
|
||||
<p>
|
||||
N razred je namenjen začetnikom, ki se šele spoznavajo z
|
||||
radioamaterstvom in niso še tako vešči v elektroniki.
|
||||
</p>
|
||||
|
||||
<div className="border-t border-gray-400" />
|
||||
<div className="border-t border-gray-400" />
|
||||
|
||||
<ul className="flex flex-col gap-2">
|
||||
<li className="flex flex-row items-center gap-2">
|
||||
<FontAwesomeIcon
|
||||
icon={faCircle}
|
||||
className="h-4 text-gray-500"
|
||||
/>
|
||||
<span>Uporaba le glavnih radioamaterskih frekvenc</span>
|
||||
</li>
|
||||
<li className="flex flex-row items-center gap-2">
|
||||
<FontAwesomeIcon
|
||||
icon={faCircle}
|
||||
className="h-4 text-gray-500"
|
||||
/>
|
||||
<span>Manjša moč</span>
|
||||
</li>
|
||||
<li className="flex flex-row items-center gap-2">
|
||||
<FontAwesomeIcon
|
||||
icon={faCircle}
|
||||
className="h-4 text-gray-500"
|
||||
/>
|
||||
<span>Ozek izbor klicnih znakov</span>
|
||||
</li>
|
||||
</ul>
|
||||
<ul className="flex flex-col gap-2">
|
||||
<li className="flex flex-row items-baseline gap-2">
|
||||
<FontAwesomeIcon
|
||||
icon={faCheckCircle}
|
||||
className="h-3 text-primary"
|
||||
/>
|
||||
<span>Uporaba le glavnih radioamaterskih frekvenc</span>
|
||||
</li>
|
||||
<li className="flex flex-row items-baseline gap-2">
|
||||
<FontAwesomeIcon
|
||||
icon={faCheckCircle}
|
||||
className="h-3 text-primary"
|
||||
/>
|
||||
<span>Manjša moč</span>
|
||||
</li>
|
||||
<li className="flex flex-row items-baseline gap-2">
|
||||
<FontAwesomeIcon
|
||||
icon={faCheckCircle}
|
||||
className="h-3 text-primary"
|
||||
/>
|
||||
<span>Ozek izbor klicnih znakov</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div className="border-t border-gray-400" />
|
||||
<div className="border-t border-gray-400" />
|
||||
|
||||
<h5 className="text-center">Klicni znaki</h5>
|
||||
<ul>
|
||||
<li>S52AAA - S52XZZ in S52ZAA - S52ZZZ</li>
|
||||
<li>S58AAA - S58XZZ</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="flex flex-1 flex-col gap-4 rounded-lg bg-light p-6 shadow-md">
|
||||
<h4 className="text-center">A razred</h4>
|
||||
<p>
|
||||
A razred je namenjen tistim, ki želijo delovati na vseh amaterskih
|
||||
frekvencah in z večjo močjo.
|
||||
</p>
|
||||
<h5 className="text-center">Klicni znaki</h5>
|
||||
<ul>
|
||||
<li>S52AAA - S52XZZ in S52ZAA - S52ZZZ</li>
|
||||
<li>S58AAA - S58XZZ</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="flex max-w-sm flex-1 flex-col gap-4 rounded-2xl bg-dark p-6 text-white">
|
||||
<h4 className="text-center">A razred</h4>
|
||||
<p>
|
||||
A razred je namenjen tistim, ki želijo delovati na vseh
|
||||
amaterskih frekvencah in z večjo močjo.
|
||||
</p>
|
||||
|
||||
<div className="border-t border-gray-400" />
|
||||
<div className="border-t border-gray-400" />
|
||||
|
||||
<ul className="flex flex-col gap-2">
|
||||
<li className="flex flex-row items-center gap-2">
|
||||
<FontAwesomeIcon
|
||||
icon={faCheckCircle}
|
||||
className="h-4 text-green-500"
|
||||
/>
|
||||
<span>Uporaba vseh radioamaterskih frekvenc</span>
|
||||
</li>
|
||||
<li className="flex flex-row items-center gap-2">
|
||||
<FontAwesomeIcon
|
||||
icon={faCheckCircle}
|
||||
className="h-4 text-green-500"
|
||||
/>
|
||||
<span>Večja moč</span>
|
||||
</li>
|
||||
<li className="flex flex-row items-center gap-2">
|
||||
<FontAwesomeIcon
|
||||
icon={faCheckCircle}
|
||||
className="h-4 text-green-500"
|
||||
/>
|
||||
<span>Širši izbor klicnih znakov</span>
|
||||
</li>
|
||||
<li className="flex flex-row items-center gap-2">
|
||||
<FontAwesomeIcon
|
||||
icon={faCheckCircle}
|
||||
className="h-4 text-green-500"
|
||||
/>
|
||||
<span>Uporaba radioamaterskih satelitskih storitev</span>
|
||||
</li>
|
||||
</ul>
|
||||
<ul className="flex flex-col gap-2">
|
||||
<li className="flex flex-row items-baseline gap-2">
|
||||
<FontAwesomeIcon
|
||||
icon={faCheckCircle}
|
||||
className="h-3 text-primary"
|
||||
/>
|
||||
<span>Uporaba vseh radioamaterskih frekvenc</span>
|
||||
</li>
|
||||
<li className="flex flex-row items-baseline gap-2">
|
||||
<FontAwesomeIcon
|
||||
icon={faCheckCircle}
|
||||
className="h-3 text-primary"
|
||||
/>
|
||||
<span>Večja moč</span>
|
||||
</li>
|
||||
<li className="flex flex-row items-baseline gap-2">
|
||||
<FontAwesomeIcon
|
||||
icon={faCheckCircle}
|
||||
className="h-3 text-primary"
|
||||
/>
|
||||
<span>Širši izbor klicnih znakov</span>
|
||||
</li>
|
||||
<li className="flex flex-row items-baseline gap-2">
|
||||
<FontAwesomeIcon
|
||||
icon={faCheckCircle}
|
||||
className="h-3 text-primary"
|
||||
/>
|
||||
<span>Uporaba radioamaterskih satelitskih storitev</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div className="border-t border-gray-400" />
|
||||
<div className="border-t border-gray-400" />
|
||||
|
||||
<h5 className="text-center">Klicni znaki</h5>
|
||||
<ul>
|
||||
<li>S50A - S59Z</li>
|
||||
<li>S50AA - S59ZZ</li>
|
||||
<li>S50AAA - S50XZZ</li>
|
||||
<li>S54AAA - S54XZZ in S54ZAA - S54ZZZ</li>
|
||||
<li>S56AAA - S56XZZ in S56ZAA - S56ZZZ</li>
|
||||
<li>S57AAA - S57XZZ in S57ZAA - S57ZZZ</li>
|
||||
<li>S58ZAA - S58ZZZ</li>
|
||||
</ul>
|
||||
<h5 className="text-center">Klicni znaki</h5>
|
||||
<ul>
|
||||
<li>S50A - S59Z</li>
|
||||
<li>S50AA - S59ZZ</li>
|
||||
<li>S50AAA - S50XZZ</li>
|
||||
<li>S54AAA - S54XZZ in S54ZAA - S54ZZZ</li>
|
||||
<li>S56AAA - S56XZZ in S56ZAA - S56ZZZ</li>
|
||||
<li>S57AAA - S57XZZ in S57ZAA - S57ZZZ</li>
|
||||
<li>S58ZAA - S58ZZZ</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5>Preizkus sprejema in oddaje Morzejevih znakov</h5>
|
||||
<p>
|
||||
Kandidat, ki na lastno željo opravlja izpit iz predmeta Sprejem in
|
||||
oddaja Morzejevih znakov, mora dokazati, da je sposoben v Morzejevih
|
||||
znakih (mednarodni Morse-kod) sprejemati na sluh in s tipkalom
|
||||
oddajati odprti tekst, skupine številk, ločila in druge znake pri
|
||||
hitrosti 25 znakov na minuto.
|
||||
</p>
|
||||
|
||||
<div className="content container my-12">
|
||||
<h3>O izpitu</h3>
|
||||
<p>Na izpitu se preverja znanje iz naslednjih področij:</p>
|
||||
<ul>
|
||||
@ -157,6 +162,15 @@ export default function Home() {
|
||||
, ki se lahko pojavijo na izpitu.
|
||||
</p>
|
||||
|
||||
<h5>Preizkus sprejema in oddaje Morzejevih znakov</h5>
|
||||
<p>
|
||||
Kandidat, ki na lastno željo opravlja izpit iz predmeta Sprejem in
|
||||
oddaja Morzejevih znakov, mora dokazati, da je sposoben v Morzejevih
|
||||
znakih (mednarodni Morse-kod) sprejemati na sluh in s tipkalom
|
||||
oddajati odprti tekst, skupine številk, ločila in druge znake pri
|
||||
hitrosti 25 znakov na minuto.
|
||||
</p>
|
||||
|
||||
<h3>Vsebine za pripravo na izpit</h3>
|
||||
<p>
|
||||
Vsa snov, ki se lahko pojavi v izpitnih vprašanjih je vsebovana v{' '}
|
||||
@ -217,8 +231,8 @@ export default function Home() {
|
||||
Po opravljenem izpitu lahko zaprosiš za klicni znak (CEPT licenco) na
|
||||
agenciji za komunikacijska omrežja in storitve Republike Slovenije
|
||||
(AKOS). Več o tem si lahko prebereš na podstrani{' '}
|
||||
<Link className="link" href="/znaki">
|
||||
Klicni znaki
|
||||
<Link className="link" href="/licenca">
|
||||
Licenca
|
||||
</Link>
|
||||
.
|
||||
</p>
|
||||
|
@ -121,7 +121,7 @@ export default function VajaQuiz() {
|
||||
</div>
|
||||
</SubHeader>
|
||||
|
||||
<div className="mx-auto flex max-w-xl flex-col gap-12">
|
||||
<div className="container flex max-w-xl flex-col gap-12">
|
||||
{questions.slice(0, displayed).map((question, qi) => (
|
||||
<QuestionCard
|
||||
key={qi}
|
||||
@ -141,7 +141,7 @@ export default function VajaQuiz() {
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mx-auto w-full max-w-xl">
|
||||
<div className="container w-full max-w-xl">
|
||||
<div className="flex flex-row justify-end gap-3">
|
||||
{questions.length > displayed && (
|
||||
<Button onClick={loadMore}>Naloži več</Button>
|
||||
|
@ -1,8 +1,10 @@
|
||||
export default function sitemap() {
|
||||
const pages = ['', '/priprave', '/izpit-sim'].map((page) => ({
|
||||
url: `https://izpit.jkob.cc${page}`,
|
||||
lastModified: new Date().toISOString(),
|
||||
}));
|
||||
const pages = ['', '/licenca', '/zbirka', '/priprave', '/izpit-sim'].map(
|
||||
(page) => ({
|
||||
url: `https://izpit.jkob.cc${page}`,
|
||||
lastModified: new Date().toISOString(),
|
||||
})
|
||||
);
|
||||
|
||||
return pages;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ export function QuestionList() {
|
||||
}, [questions.length]);
|
||||
|
||||
return (
|
||||
<div className="mx-auto my-10 flex max-w-xl flex-col gap-12">
|
||||
<div className="container my-10 flex max-w-xl flex-col gap-12">
|
||||
{questions.map((question) => (
|
||||
<QuestionCard
|
||||
key={question.id}
|
||||
|
@ -1,10 +1,8 @@
|
||||
'use client';
|
||||
|
||||
import { morse } from '@/fonts/fonts';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
|
||||
const nav = [
|
||||
{ href: '/', label: 'Domov' },
|
||||
@ -16,8 +14,6 @@ const nav = [
|
||||
];
|
||||
|
||||
export default function Header() {
|
||||
const [navbar, setNavbar] = useState<boolean>(false);
|
||||
|
||||
const pathname = usePathname();
|
||||
|
||||
return (
|
||||
@ -30,11 +26,8 @@ export default function Header() {
|
||||
<Link href="/">
|
||||
<h1 className="text-4xl">Radioamaterski izpit</h1>
|
||||
</Link>
|
||||
<div
|
||||
data-nosnippet
|
||||
className={`mt-1 text-sm text-gray-400 ${morse.className}`}
|
||||
>
|
||||
C Q | D E | Z R S
|
||||
<div data-nosnippet className="morse mt-1 text-sm text-gray-400">
|
||||
CQ|DE|ZRS
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -42,7 +35,7 @@ export default function Header() {
|
||||
</div>
|
||||
|
||||
<div className="bg-dark">
|
||||
<nav className="container flex flex-row justify-start">
|
||||
<nav className="container flex flex-row flex-wrap justify-start">
|
||||
{nav.map(({ href, label }) => (
|
||||
<Link
|
||||
key={href}
|
||||
|
@ -1,3 +1,9 @@
|
||||
import { Roboto_Mono } from 'next/font/google';
|
||||
import localFont from 'next/font/local';
|
||||
|
||||
export const morse = localFont({ src: './morse.ttf' });
|
||||
export const morse = localFont({
|
||||
src: './morse.ttf',
|
||||
variable: '--font-morse',
|
||||
});
|
||||
|
||||
export const robotoMono = Roboto_Mono({ subsets: ['latin'] });
|
||||
|
@ -57,3 +57,13 @@
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.morse {
|
||||
font-family: var(--font-morse);
|
||||
letter-spacing: 0.6em;
|
||||
}
|
||||
|
||||
.text-center .morse,
|
||||
.text-center.morse {
|
||||
text-indent: 0.6em;
|
||||
}
|
||||
|
78
src/util/callsign-util.ts
Normal file
78
src/util/callsign-util.ts
Normal file
@ -0,0 +1,78 @@
|
||||
export function generateRandomCallsign(): string {
|
||||
const length = Math.ceil(Math.random() * 3);
|
||||
let callsign = `S5${String.fromCharCode(
|
||||
Math.floor(Math.random() * 10) + 48
|
||||
)}`;
|
||||
for (let i = 0; i < length; i++) {
|
||||
callsign += String.fromCharCode(Math.floor(Math.random() * 26) + 65);
|
||||
}
|
||||
|
||||
return callsign;
|
||||
}
|
||||
|
||||
export function cwWeight(text: string): number {
|
||||
text = text.toUpperCase();
|
||||
let ret = (text.length - 1) * 3;
|
||||
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
if (text[i] === ' ') {
|
||||
ret += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
const cw = cwMap.get(text[i]);
|
||||
if (!cw) throw new Error(`No cw for ${text[i]}`);
|
||||
|
||||
ret += cw.length - 1;
|
||||
for (const c in cw) {
|
||||
if (cw[c] == '.') ret += 1;
|
||||
else ret += 3;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const cwMap = new Map<String, String>([
|
||||
['A', '.-'],
|
||||
['B', '-...'],
|
||||
['C', '-.-.'],
|
||||
['D', '-..'],
|
||||
['E', '.'],
|
||||
['F', '..-.'],
|
||||
['G', '--.'],
|
||||
['H', '....'],
|
||||
['I', '..'],
|
||||
['J', '.---'],
|
||||
['K', '-.-'],
|
||||
['L', '.-..'],
|
||||
['M', '--'],
|
||||
['N', '-.'],
|
||||
['O', '---'],
|
||||
['P', '.--.'],
|
||||
['Q', '--.-'],
|
||||
['R', '.-.'],
|
||||
['S', '...'],
|
||||
['T', '-'],
|
||||
['U', '..-'],
|
||||
['V', '...-'],
|
||||
['W', '.--'],
|
||||
['X', '-..-'],
|
||||
['Y', '-.--'],
|
||||
['Z', '--..'],
|
||||
['0', '-----'],
|
||||
['1', '.----'],
|
||||
['2', '..---'],
|
||||
['3', '...--'],
|
||||
['4', '....-'],
|
||||
['5', '.....'],
|
||||
['6', '-....'],
|
||||
['7', '--...'],
|
||||
['8', '---..'],
|
||||
['9', '----.'],
|
||||
['.', '.-.-.-'],
|
||||
[',', '--..--'],
|
||||
['?', '..--..'],
|
||||
['/', '-..-.'],
|
||||
['=', '-...-'],
|
||||
]);
|
Loading…
x
Reference in New Issue
Block a user