brought both code in 1 repo, working on merging them!

This commit is contained in:
RezHackXYZ 2025-05-26 08:37:44 +05:30
parent d1c8ae269b
commit 9f927cf2e9
No known key found for this signature in database
82 changed files with 3220 additions and 20 deletions

View file

@ -1,6 +1,6 @@
{
"name": "kahootclone",
"private": true,
"name": "class-room-stuff",
"private": false,
"version": "0.0.1",
"type": "module",
"scripts": {
@ -27,6 +27,12 @@
"vite": "^6.0.0"
},
"dependencies": {
"@supabase/supabase-js": "^2.49.4"
"@supabase/supabase-js": "^2.49.4",
"chart.js": "^4.4.9",
"drag-drop-touch": "^1.3.1",
"kokoro-js": "^1.2.1",
"random-words": "^2.0.1",
"svelte-spa-router": "^4.0.1",
"word-exists": "^1.0.0"
}
}

View file

@ -1,8 +1,34 @@
<script>
let { children } = $props();
import { confettiAnimation } from "./Confetti.js";
let ShowAlertDiv = $state(false);
let ShowAlertText = $state("this Code is bad");
let ShowAlertType = $state("Error");
export function ShowAlert(text, type) {
ShowAlertDiv = true;
ShowAlertType = type;
ShowAlertText = text;
setTimeout(() => {
ShowAlertDiv = false;
}, 1500);
if (type == "success") {
confettiAnimation();
}
}
</script>
<div class="h-full text-white">{@render children()}</div>
<div id="root">
<div class="h-full text-white">{@render children()}</div>
</div>
{#if ShowAlertDiv == true}
<div id="alert">
<h1 class={ShowAlertType}>{ShowAlertText}</h1>
</div>
{/if}
<style>
@import "https://www.nerdfonts.com/assets/css/webfont.css";
@ -14,4 +40,33 @@
font-family: "Comfortaa", sans-serif;
font-weight: 300;
}
#root {
height: 100%;
margin: 0;
font-family: "Sour Gummy", sans-serif;
}
#alert {
position: fixed;
top: 10px;
color: white;
left: 50%;
transform: translate(-50%, 0);
h1 {
margin: 0;
padding: 10px 20px;
border-radius: 20px;
font-family: "Sour Gummy", sans-serif;
}
.error {
background-color: #830000;
}
.warning {
background-color: #975b00;
}
.success {
background-color: #006b00;
}
}
</style>

View file

@ -1,18 +1,246 @@
<div class="bg-grey-900 flex h-full items-center justify-center">
<div class="flex flex-col items-center justify-center gap-1 rounded-lg bg-gray-900 p-8 shadow-lg">
<h1 class="m-[0] text-6xl">DaKahootClone</h1>
<p class="m-[0] mb-2 text-lg text-gray-400">The best ever kahoot clone.</p>
<a href="./join">
<button
class="cursor-pointer rounded-full bg-green-700 p-2 transition-all hover:scale-110 hover:-rotate-10"
>Join a game</button
></a
<div id="root">
<img
src="https://hc-cdn.hel1.your-objectstorage.com/s/v3/77e7a04f27807b4e0c16bcda09ea222f9e091616_group_18.svg"
id="logo"
alt="ClassRoomStuff Logo"
/>
<h2>A collection of awesome tools, games, and more — made to be used in any classroom!</h2>
<h3>MAIN</h3>
<div id="items2">
<a href="/KahhotClone">
<button class="button2">
<span class="front2">
<svg
xmlns="http://www.w3.org/2000/svg"
height="70px"
viewBox="0 -960 960 960"
width="70px"
fill="#e3e3e3"
><path
d="M560-360q17 0 29.5-12.5T602-402q0-17-12.5-29.5T560-444q-17 0-29.5 12.5T518-402q0 17 12.5 29.5T560-360Zm-30-128h60q0-29 6-42.5t28-35.5q30-30 40-48.5t10-43.5q0-45-31.5-73.5T560-760q-41 0-71.5 23T446-676l54 22q9-25 24.5-37.5T560-704q24 0 39 13.5t15 36.5q0 14-8 26.5T578-596q-33 29-40.5 45.5T530-488ZM320-240q-33 0-56.5-23.5T240-320v-480q0-33 23.5-56.5T320-880h480q33 0 56.5 23.5T880-800v480q0 33-23.5 56.5T800-240H320Zm0-80h480v-480H320v480ZM160-80q-33 0-56.5-23.5T80-160v-560h80v560h560v80H160Zm160-720v480-480Z"
/></svg
>
DaKahootClone
<p>The best ever kahoot clone.</p></span
>
</button></a
>
</div>
<h3>OTHERS</h3>
<div id="items">
<a href="/IdleScreen">
<button>
<span class="front">
<svg
xmlns="http://www.w3.org/2000/svg"
height="30px"
viewBox="0 -960 960 960"
width="30px"
fill="#FFFFFF"
><path
d="m612-292 56-56-148-148v-184h-80v216l172 172ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-400Zm0 320q133 0 226.5-93.5T800-480q0-133-93.5-226.5T480-800q-133 0-226.5 93.5T160-480q0 133 93.5 226.5T480-160Z"
/></svg
>
Timetable
<p>Clock included!</p></span
>
</button></a
>
<a href="#/RandomName">
<button>
<span class="front">
<svg
xmlns="http://www.w3.org/2000/svg"
height="30px"
viewBox="0 -960 960 960"
width="30px"
fill="#FFFFFF"
><path
d="M0-240v-63q0-43 44-70t116-27q13 0 25 .5t23 2.5q-14 21-21 44t-7 48v65H0Zm240 0v-65q0-32 17.5-58.5T307-410q32-20 76.5-30t96.5-10q53 0 97.5 10t76.5 30q32 20 49 46.5t17 58.5v65H240Zm540 0v-65q0-26-6.5-49T754-397q11-2 22.5-2.5t23.5-.5q72 0 116 26.5t44 70.5v63H780Zm-455-80h311q-10-20-55.5-35T480-370q-55 0-100.5 15T325-320ZM160-440q-33 0-56.5-23.5T80-520q0-34 23.5-57t56.5-23q34 0 57 23t23 57q0 33-23 56.5T160-440Zm640 0q-33 0-56.5-23.5T720-520q0-34 23.5-57t56.5-23q34 0 57 23t23 57q0 33-23 56.5T800-440Zm-320-40q-50 0-85-35t-35-85q0-51 35-85.5t85-34.5q51 0 85.5 34.5T600-600q0 50-34.5 85T480-480Zm0-80q17 0 28.5-11.5T520-600q0-17-11.5-28.5T480-640q-17 0-28.5 11.5T440-600q0 17 11.5 28.5T480-560Zm1 240Zm-1-280Z"
/></svg
>
Name selector
<p>for any class activity!</p></span
>
</button></a
>
<a href="#/Wordle">
<button>
<span class="front">
<svg
xmlns="http://www.w3.org/2000/svg"
height="30px"
viewBox="0 -960 960 960"
width="30px"
fill="#FFFFFF"
><path
d="M182-200q-51 0-79-35.5T82-322l42-300q9-60 53.5-99T282-760h396q60 0 104.5 39t53.5 99l42 300q7 51-21 86.5T778-200q-21 0-39-7.5T706-230l-90-90H344l-90 90q-15 15-33 22.5t-39 7.5Zm16-86 114-114h336l114 114q2 2 16 6 11 0 17.5-6.5T800-304l-44-308q-4-29-26-48.5T678-680H282q-30 0-52 19.5T204-612l-44 308q-2 11 4.5 17.5T182-280q2 0 16-6Zm482-154q17 0 28.5-11.5T720-480q0-17-11.5-28.5T680-520q-17 0-28.5 11.5T640-480q0 17 11.5 28.5T680-440Zm-80-120q17 0 28.5-11.5T640-600q0-17-11.5-28.5T600-640q-17 0-28.5 11.5T560-600q0 17 11.5 28.5T600-560ZM310-440h60v-70h70v-60h-70v-70h-60v70h-70v60h70v70Zm170-40Z"
/></svg
>
Wordle
<p>Challenge your vocabulary!</p></span
>
</button></a
>
<a href="#/announcer">
<button>
<span class="front">
<svg
xmlns="http://www.w3.org/2000/svg"
height="30px"
viewBox="0 -960 960 960"
width="30px"
fill="#FFFFFF"
><path
d="M720-440v-80h160v80H720Zm48 280-128-96 48-64 128 96-48 64Zm-80-480-48-64 128-96 48 64-128 96ZM200-200v-160h-40q-33 0-56.5-23.5T80-440v-80q0-33 23.5-56.5T160-600h160l200-120v480L320-360h-40v160h-80Zm240-182v-196l-98 58H160v80h182l98 58Zm120 36v-268q27 24 43.5 58.5T620-480q0 41-16.5 75.5T560-346ZM300-480Z"
/></svg
>
Announcer
<p>to shout from the speakers!</p></span
>
</button></a
>
<a href="./create">
<button
class="cursor-pointer rounded-full bg-blue-700 p-2 transition-all hover:scale-110 hover:-rotate-10"
>Create and Host a game</button
>
</a>
</div>
</div>
<div id="BottomBadge">
Made by <a href="https://rezhack.xyz" target="_blank">RezHackXYZ</a> for
<a href="https://neighborhood.hackclub.com/" target="_blank">Neighborhood</a>!
<a href="https://github.com/RezHackXYZ/ClassRoomStuff" target="_blank">Contribute here</a> if you
want.
</div>
<style>
#root {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
}
h1 {
text-align: center;
margin: 0;
font-size: 60px;
}
h2 {
text-align: center;
margin: 0;
color: #797979;
font-size: 30px;
margin-bottom: 40px;
}
#items2 {
display: flex;
justify-content: center;
align-items: center;
gap: 20px;
flex-wrap: wrap;
margin-top: 10px;
margin-bottom: 20px;
}
#items {
margin-top: 10px;
display: flex;
justify-content: center;
align-items: center;
gap: 20px;
flex-wrap: wrap;
}
button {
background: #292929;
border-radius: 12px;
border: none;
padding: 0;
cursor: pointer;
outline-offset: 4px;
}
.front {
display: flex;
flex-direction: column;
text-align: center;
align-items: center;
padding: 5px 15px;
border-radius: 12px;
font-size: 1.25rem;
background: #4d4d4d;
color: white;
transform: translateY(-7px);
transition: all 0.1s ease-in-out;
font-family: "JetBrains Mono", monospace;
font-size: 30px;
}
.front2 {
display: flex;
flex-direction: column;
text-align: center;
align-items: center;
padding: 3px 30px;
border-radius: 12px;
background: #4d4d4d;
color: white;
transform: translateY(-7px);
transition: all 0.1s ease-in-out;
font-family: "JetBrains Mono", monospace;
font-size: 50px;
}
p {
font-size: 12px;
color: #aaaaaa;
margin: 0;
text-align: center;
}
.front2 > p {
font-size: 20px;
}
button:hover .front {
transform: translateY(-10px);
}
button:active .front {
transform: translateY(-3px);
}
#BottomBadge {
position: fixed;
bottom: 0;
left: 50%;
transform: translate(-50%, 0);
background-color: #242424;
color: #aaaaaa;
margin-bottom: 10px;
width: fit-content;
align-self: center;
padding: 5px;
font-size: 20px;
border-radius: 10px;
}
a {
color: #aaaaaa;
}
h3 {
text-align: center;
margin: 0;
color: #aaaaaa;
font-size: 30px;
}
#logo {
width: 500px;
margin-bottom: 20px;
align-self: center;
}
</style>

316
src/routes/Confetti.js Normal file
View file

@ -0,0 +1,316 @@
export function confettiAnimation() {
(() => {
"use strict";
// Utility functions grouped into a single object
const Utils = {
// Parse pixel values to numeric values
parsePx: (value) => parseFloat(value.replace(/px/, "")),
// Generate a random number between two values, optionally with a fixed precision
getRandomInRange: (min, max, precision = 0) => {
const multiplier = Math.pow(10, precision);
const randomValue = Math.random() * (max - min) + min;
return Math.floor(randomValue * multiplier) / multiplier;
},
// Pick a random item from an array
getRandomItem: (array) =>
array[Math.floor(Math.random() * array.length)],
// Scaling factor based on screen width
getScaleFactor: () => Math.log(window.innerWidth) / Math.log(1920),
// Debounce function to limit event firing frequency
debounce: (func, delay) => {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), delay);
};
},
};
// Precomputed constants
const DEG_TO_RAD = Math.PI / 180;
// Centralized configuration for default values
const defaultConfettiConfig = {
confettiesNumber: 250,
confettiRadius: 6,
confettiColors: [
"#fcf403",
"#62fc03",
"#f4fc03",
"#03e7fc",
"#03fca5",
"#a503fc",
"#fc03ad",
"#fc03c2",
],
emojies: [],
svgIcon: null, // Example SVG link
};
// Confetti class representing individual confetti pieces
class Confetti {
constructor({
initialPosition,
direction,
radius,
colors,
emojis,
svgIcon,
}) {
const speedFactor =
Utils.getRandomInRange(0.9, 1.7, 3) *
Utils.getScaleFactor();
this.speed = { x: speedFactor, y: speedFactor };
this.finalSpeedX = Utils.getRandomInRange(0.2, 0.6, 3);
this.rotationSpeed =
emojis.length || svgIcon
? 0.01
: Utils.getRandomInRange(0.03, 0.07, 3) *
Utils.getScaleFactor();
this.dragCoefficient = Utils.getRandomInRange(
0.0005,
0.0009,
6
);
this.radius = { x: radius, y: radius };
this.initialRadius = radius;
this.rotationAngle =
direction === "left"
? Utils.getRandomInRange(0, 0.2, 3)
: Utils.getRandomInRange(-0.2, 0, 3);
this.emojiRotationAngle = Utils.getRandomInRange(
0,
2 * Math.PI
);
this.radiusYDirection = "down";
const angle =
direction === "left"
? Utils.getRandomInRange(82, 15) * DEG_TO_RAD
: Utils.getRandomInRange(-15, -82) * DEG_TO_RAD;
this.absCos = Math.abs(Math.cos(angle));
this.absSin = Math.abs(Math.sin(angle));
const offset = Utils.getRandomInRange(-150, 0);
const position = {
x:
initialPosition.x +
(direction === "left" ? -offset : offset) * this.absCos,
y: initialPosition.y - offset * this.absSin,
};
this.position = { ...position };
this.initialPosition = { ...position };
this.color =
emojis.length || svgIcon
? null
: Utils.getRandomItem(colors);
this.emoji = emojis.length ? Utils.getRandomItem(emojis) : null;
this.svgIcon = null;
// Preload SVG if provided
if (svgIcon) {
this.svgImage = new Image();
this.svgImage.src = svgIcon;
this.svgImage.onload = () => {
this.svgIcon = this.svgImage; // Mark as ready once loaded
};
}
this.createdAt = Date.now();
this.direction = direction;
}
draw(context) {
const { x, y } = this.position;
const { x: radiusX, y: radiusY } = this.radius;
const scale = window.devicePixelRatio;
if (this.svgIcon) {
context.save();
context.translate(scale * x, scale * y);
context.rotate(this.emojiRotationAngle);
context.drawImage(
this.svgIcon,
-radiusX,
-radiusY,
radiusX * 2,
radiusY * 2
);
context.restore();
} else if (this.color) {
context.fillStyle = this.color;
context.beginPath();
context.ellipse(
x * scale,
y * scale,
radiusX * scale,
radiusY * scale,
this.rotationAngle,
0,
2 * Math.PI
);
context.fill();
} else if (this.emoji) {
context.font = `${radiusX * scale}px serif`;
context.save();
context.translate(scale * x, scale * y);
context.rotate(this.emojiRotationAngle);
context.textAlign = "center";
context.fillText(this.emoji, 0, radiusY / 2); // Adjust vertical alignment
context.restore();
}
}
updatePosition(deltaTime, currentTime) {
const elapsed = currentTime - this.createdAt;
if (this.speed.x > this.finalSpeedX) {
this.speed.x -= this.dragCoefficient * deltaTime;
}
this.position.x +=
this.speed.x *
(this.direction === "left" ? -this.absCos : this.absCos) *
deltaTime;
this.position.y =
this.initialPosition.y -
this.speed.y * this.absSin * elapsed +
(0.00125 * Math.pow(elapsed, 2)) / 2;
if (!this.emoji && !this.svgIcon) {
this.rotationSpeed -= 1e-5 * deltaTime;
this.rotationSpeed = Math.max(this.rotationSpeed, 0);
if (this.radiusYDirection === "down") {
this.radius.y -= deltaTime * this.rotationSpeed;
if (this.radius.y <= 0) {
this.radius.y = 0;
this.radiusYDirection = "up";
}
} else {
this.radius.y += deltaTime * this.rotationSpeed;
if (this.radius.y >= this.initialRadius) {
this.radius.y = this.initialRadius;
this.radiusYDirection = "down";
}
}
}
}
isVisible(canvasHeight) {
return this.position.y < canvasHeight + 100;
}
}
class ConfettiManager {
constructor() {
this.canvas = document.createElement("canvas");
// @ts-ignore
this.canvas.style =
"position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 1000; pointer-events: none;";
document.body.appendChild(this.canvas);
this.context = this.canvas.getContext("2d");
this.confetti = [];
this.lastUpdated = Date.now();
window.addEventListener(
"resize",
Utils.debounce(() => this.resizeCanvas(), 200)
);
this.resizeCanvas();
requestAnimationFrame(() => this.loop());
}
resizeCanvas() {
this.canvas.width = window.innerWidth * window.devicePixelRatio;
this.canvas.height =
window.innerHeight * window.devicePixelRatio;
}
addConfetti(config = {}) {
const {
confettiesNumber,
confettiRadius,
confettiColors,
emojies,
svgIcon,
} = {
...defaultConfettiConfig,
...config,
};
const baseY = (5 * window.innerHeight) / 7;
for (let i = 0; i < confettiesNumber / 2; i++) {
this.confetti.push(
new Confetti({
initialPosition: { x: 0, y: baseY },
direction: "right",
radius: confettiRadius,
colors: confettiColors,
emojis: emojies,
svgIcon,
})
);
this.confetti.push(
new Confetti({
initialPosition: { x: window.innerWidth, y: baseY },
direction: "left",
radius: confettiRadius,
colors: confettiColors,
emojis: emojies,
svgIcon,
})
);
}
}
resetAndStart(config = {}) {
// Clear existing confetti
this.confetti = [];
// Add new confetti
this.addConfetti(config);
}
loop() {
const currentTime = Date.now();
const deltaTime = currentTime - this.lastUpdated;
this.lastUpdated = currentTime;
this.context.clearRect(
0,
0,
this.canvas.width,
this.canvas.height
);
this.confetti = this.confetti.filter((item) => {
item.updatePosition(deltaTime, currentTime);
item.draw(this.context);
return item.isVisible(this.canvas.height);
});
requestAnimationFrame(() => this.loop());
}
}
const manager = new ConfettiManager();
manager.addConfetti();
const triggerButton = document.getElementById("show-again");
if (triggerButton) {
triggerButton.addEventListener("click", () =>
manager.addConfetti()
);
}
const resetInput = document.getElementById("reset");
if (resetInput) {
resetInput.addEventListener("input", () => manager.resetAndStart());
}
})();
}

View file

@ -0,0 +1,180 @@
<script module>
import Time from "./time.svelte";
import TimeTable from "./timeTable.svelte";
import EditTimetableDiv from "./EditTimetable.svelte";
function EditTimetable() {
console.log("Edit timetable");
TabOpen.v = true;
}
let TabOpen = $state({ v: false });
export let ShowSeconds = $state({ v: true });
</script>
<div id="wrap">
<div id="nav">
<a href="#/" aria-label="Back to main menu"
><button aria-label="Back to main menu"
><span class="front"
><svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="#FFFFFF"
><path
d="M240-200h120v-240h240v240h120v-360L480-740 240-560v360Zm-80 80v-480l320-240 320 240v480H520v-240h-80v240H160Zm320-350Z"
/></svg
> GO BACK
</span></button
></a
>
<h1>Idle Screen</h1>
<div>
<button
aria-label="Back to main menu"
onclick={() => {
ShowSeconds.v = !ShowSeconds.v;
localStorage.setItem("ShowSeconds", String(ShowSeconds.v));
}}
><span class="front"
>{#if ShowSeconds.v}Disable Seconds{:else}Enable Seconds{/if}</span
></button
><button
aria-label="Back to main menu"
onclick={() => EditTimetable()}
><span class="front"
><svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="#FFFFFF"
><path
d="M200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v200h-80v-40H200v400h280v80H200Zm0-560h560v-80H200v80Zm0 0v-80 80ZM560-80v-123l221-220q9-9 20-13t22-4q12 0 23 4.5t20 13.5l37 37q8 9 12.5 20t4.5 22q0 11-4 22.5T903-300L683-80H560Zm300-263-37-37 37 37ZM620-140h38l121-122-18-19-19-18-122 121v38Zm141-141-19-18 37 37-18-19Z"
/></svg
> Edit timetable
</span></button
>
</div>
</div>
<div id="root">
<TimeTable /><Time />
</div>
</div>
{#if TabOpen.v !== false}
<div id="UpperLayer">
<div id="wrapClose">
<EditTimetableDiv />
<button
class="close"
onclick={() => (TabOpen.v = false)}
aria-label="close">CLOSE</button
>
</div>
</div>
{/if}
<style>
#wrap {
display: flex;
flex-direction: column;
height: 100%;
}
#root {
display: flex;
flex-direction: column;
height: 100%;
justify-content: space-evenly;
}
#nav {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #121212;
color: white;
}
button {
background: #292929;
border-radius: 12px;
border: none;
margin: 10px;
padding: 2px 0px;
cursor: pointer;
outline-offset: 4px;
max-width: 400px;
}
button:hover .front {
transform: translateY(-7px);
}
button:active .front {
transform: translateY(-2px);
}
.front {
display: flex;
text-align: center;
align-items: center;
padding: 5px;
border-radius: 12px;
background: #4d4d4d;
color: white;
transform: translateY(-4px);
transition: all 0.1s ease-in-out;
font-family: "JetBrains Mono", monospace;
font-size: 25px;
}
h1 {
text-align: center;
margin: 5px 0px;
text-decoration: underline #444;
position: fixed;
top: 0;
left: 50%;
transform: translate(-50%, 0);
}
span {
font-size: 0.5em;
text-decoration: none;
color: #444;
}
#UpperLayer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
backdrop-filter: blur(5px);
background-color: rgba(0, 0, 0, 0.5);
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
}
#wrapClose {
display: flex;
flex-direction: column;
}
.close {
background-color: #2b2b2b;
color: #888;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
align-self: center;
}
</style>

View file

@ -0,0 +1,348 @@
<script>
import { newTable } from "./timeTable.svelte";
let table = JSON.parse(localStorage.getItem("TimeTable"));
let TabOpen = false;
let csv = "";
</script>
<div class="root">
<div id="wrap">
<div id="left">
<div class="Header Row">
<span class="DayOfWeek" style="Opacity: 0;"></span>
{#each table.Times as time}
<input
type="text"
onchange={() => {
newTable(table);
}}
bind:value={time}
/>
{/each}
</div>
<div class="Row">
<span class="DayOfWeek">Monday</span>
{#each table.Monday as time}
<input
type="text"
onchange={() => {
newTable(table);
}}
bind:value={time}
/>
{/each}
</div>
<div class="Row">
<span class="DayOfWeek">Tuesday</span>
{#each table.Tuesday as time}
<input
type="text"
onchange={() => {
newTable(table);
}}
bind:value={time}
/>
{/each}
</div>
<div class="Row">
<span class="DayOfWeek">Wednesday</span>
{#each table.Wednesday as time}
<input
type="text"
onchange={() => {
newTable(table);
}}
bind:value={time}
/>
{/each}
</div>
<div class="Row">
<span class="DayOfWeek">Thursday</span>
{#each table.Thursday as time}
<input
type="text"
onchange={() => {
newTable(table);
}}
bind:value={time}
/>
{/each}
</div>
<div class="Row">
<span class="DayOfWeek">Friday</span>
{#each table.Friday as time}
<input
type="text"
onchange={() => {
newTable(table);
}}
bind:value={time}
/>
{/each}
</div>
</div>
<div id="right">
<button
onclick={() => {
table.Times.push("");
table.Monday.push("");
table.Tuesday.push("");
table.Wednesday.push("");
table.Thursday.push("");
table.Friday.push("");
newTable(table);
table = JSON.parse(localStorage.getItem("TimeTable"));
}}
><svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="#FFFFFF"
><path
d="M440-440H200v-80h240v-240h80v240h240v80H520v240h-80v-240Z"
/></svg
>Add new Period
</button>
<button
onclick={() => {
if (
confirm(
"This will remove the last period, it is not reversible! are you sure?"
)
) {
table.Times.pop();
table.Monday.pop();
table.Tuesday.pop();
table.Wednesday.pop();
table.Thursday.pop();
table.Friday.pop();
newTable(table);
table = JSON.parse(localStorage.getItem("TimeTable"));
}
}}
><svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="#FFFFFF"
><path
d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z"
/></svg
>
Delete last Period
</button>
<button
onclick={() => {
TabOpen = true;
}}
><svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="#FFFFFF"
><path
d="M230-360h120v-60H250v-120h100v-60H230q-17 0-28.5 11.5T190-560v160q0 17 11.5 28.5T230-360Zm156 0h120q17 0 28.5-11.5T546-400v-60q0-17-11.5-31.5T506-506h-60v-34h100v-60H426q-17 0-28.5 11.5T386-560v60q0 17 11.5 30.5T426-456h60v36H386v60Zm264 0h60l70-240h-60l-40 138-40-138h-60l70 240ZM160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h640q33 0 56.5 23.5T880-720v480q0 33-23.5 56.5T800-160H160Zm0-80h640v-480H160v480Zm0 0v-480 480Z"
/></svg
>
Import From CSV
</button>
</div>
</div>
</div>
{#if TabOpen !== false}
<div id="UpperLayer">
<div id="wrapClose">
<div class="root">
<h1>Paste CSV here:</h1>
<p></p>
<textarea
bind:value={csv}
id="box"
placeholder="Duration 1, Duration 2, Duration 3, Duration 4
Subject 01, Subject 02, Subject 03, Subject 04
Subject 08, Subject 09, Subject 10, Subject 12
Subject 13, Subject 13, Subject 14, Subject 15"
></textarea>
</div>
<div id="options">
<button
class="close"
id="cancel"
onclick={() => (TabOpen = false)}
aria-label="close">CANCEL</button
>
<button
class="close"
id="save"
onclick={() => {
TabOpen = false;
let lines = csv.split("\n");
table.Times = lines[0].split(",");
table.Monday = lines[1].split(",");
table.Tuesday = lines[2].split(",");
table.Wednesday = lines[3].split(",");
table.Thursday = lines[4].split(",");
table.Friday = lines[5].split(",");
newTable(table);
table = JSON.parse(localStorage.getItem("TimeTable"));
}}
aria-label="close">SAVE</button
>
</div>
</div>
</div>
{/if}
<style>
.root {
display: flex;
flex-direction: column;
gap: 5px;
margin: 10px;
justify-content: center;
background-color: #303030;
padding: 10px;
margin: 20px;
border-radius: 10px;
width: fit-content;
}
#wrap {
display: flex;
background-color: #252525;
padding: 20px;
border-radius: 20px;
gap: 20px;
}
.Row {
display: flex;
gap: 2px;
}
span {
font-size: 15px;
color: white;
background-color: #3f3f3f;
padding: 5px;
border-radius: 10px;
width: 100px;
text-align: center;
}
.DayOfWeek {
width: 100px;
background-color: #30492e;
}
input {
font-size: 15px;
color: white;
background-color: #3f3f3f;
padding: 5px;
border-radius: 10px;
width: 100px;
text-align: center;
}
.Header > input {
background-color: #30492e;
}
#left {
gap: 5px;
display: flex;
flex-direction: column;
}
#right {
gap: 10px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
#right > button {
background-color: rgb(63, 63, 63);
color: white;
border: 2px solid white;
border-radius: 10px;
cursor: pointer;
transition: all 0.1s ease-in-out;
display: flex;
flex-direction: column;
align-items: center;
max-width: 100px;
}
#right > button:hover {
transform: scale(1.2);
background-color: rgb(50, 50, 50);
}
#UpperLayer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
backdrop-filter: blur(10px);
background-color: rgba(0, 0, 0, 0.5);
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
}
#wrapClose {
display: flex;
flex-direction: column;
}
.close {
background-color: #2b2b2b;
color: #888;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
align-self: center;
}
#box {
width: 700px;
height: 300px;
background-color: #121212;
color: white;
border-radius: 10px;
resize: vertical;
font-size: 20px;
}
h1,
p {
margin: 0;
}
#options {
display: flex;
gap: 10px;
justify-content: center;
}
#cancel {
background-color: #580000;
color: #ffffff;
}
#save {
background-color: #004611;
color: #ffffff;
}
</style>

View file

@ -0,0 +1,231 @@
<script>
import { ShowSeconds } from "./+page.svelte";
import { onMount } from "svelte";
let hour1;
let hour2;
let min1;
let min2;
let sec1;
let sec2;
let AmOrPm;
function DecideScrool(Object, currentTime, legnth, LastZeroPos) {
if (currentTime == 0) {
if (Object.scrollTop != 0) {
Object.scrollTop = LastZeroPos * legnth;
setTimeout(() => {
Object.scroll({
top: 0,
behavior: "instant",
});
}, 500);
}
} else {
Object.scrollTop = currentTime * legnth;
}
}
function updateTime() {
const now = new Date();
let hours = now.getHours().toString().padStart(2, "0");
if (now.getHours() >= 12) {
hours = (now.getHours() - 12).toString().padStart(2, "0");
AmOrPm = "PM";
} else {
AmOrPm = "AM";
}
const minutes = now.getMinutes().toString().padStart(2, "0");
const seconds = now.getSeconds().toString().padStart(2, "0");
DecideScrool(hour1, parseInt(hours[0]), 200, 2);
DecideScrool(hour2, parseInt(hours[1]), 200, 10);
DecideScrool(min1, parseInt(minutes[0]), 200, 6);
DecideScrool(min2, parseInt(minutes[1]), 200, 10);
if (ShowSeconds) {
DecideScrool(sec1, parseInt(seconds[0]), 75, 6);
DecideScrool(sec2, parseInt(seconds[1]), 75, 10);
}
}
onMount(() => {
updateTime();
setInterval(updateTime, 1000);
});
let TempLocalStorage = localStorage.getItem("ShowSeconds") || "";
if (TempLocalStorage == "false") {
ShowSeconds.v = false;
}
</script>
<div id="root">
<div id="wrap">
<div id="time">
<div class="rowOfNumbers" bind:this={hour1}>
<h1>0</h1>
<h1>1</h1>
<h1>0</h1>
</div>
<div class="rowOfNumbers" bind:this={hour2}>
<h1>0</h1>
<h1>1</h1>
<h1>2</h1>
<h1>3</h1>
<h1>4</h1>
<h1>5</h1>
<h1>6</h1>
<h1>7</h1>
<h1>8</h1>
<h1>9</h1>
<h1>0</h1>
</div>
<h1 id="HourMinDivider">:</h1>
<div class="rowOfNumbers" bind:this={min1}>
<h1>0</h1>
<h1>1</h1>
<h1>2</h1>
<h1>3</h1>
<h1>4</h1>
<h1>5</h1>
<h1>0</h1>
</div>
<div class="rowOfNumbers" bind:this={min2}>
<h1>0</h1>
<h1>1</h1>
<h1>2</h1>
<h1>3</h1>
<h1>4</h1>
<h1>5</h1>
<h1>6</h1>
<h1>7</h1>
<h1>8</h1>
<h1>9</h1>
<h1>0</h1>
</div>
{#if ShowSeconds.v}
<h1 id="MinSecDivider">.</h1>
<div class="rowOfNumbersSec" bind:this={sec1}>
<h1>0</h1>
<h1>1</h1>
<h1>2</h1>
<h1>3</h1>
<h1>4</h1>
<h1>5</h1>
<h1>0</h1>
</div>
<div class="rowOfNumbersSec" bind:this={sec2}>
<h1>0</h1>
<h1>1</h1>
<h1>2</h1>
<h1>3</h1>
<h1>4</h1>
<h1>5</h1>
<h1>6</h1>
<h1>7</h1>
<h1>8</h1>
<h1>9</h1>
<h1>0</h1>
</div>{/if}
<h1 id="AmOrPm">{AmOrPm}</h1>
</div>
<div id="date">
<h2>
{new Date().toLocaleString("en-US", { weekday: "short" })}
{new Date().getDate()},
{new Date().toLocaleString("en-US", { month: "short" })}
{new Date().getFullYear()}
</h2>
</div>
</div>
</div>
<style>
#root {
display: grid;
place-items: center;
}
#wrap {
background-color: #252525;
padding: 20px 70px;
border-radius: 20px;
}
#time {
display: flex;
justify-content: center;
align-items: baseline;
margin: -30px;
}
#HourMinDivider {
font-size: 200px;
margin: 0;
}
#MinSecDivider {
font-size: 75px;
margin: 0;
color: #585858;
}
.rowOfNumbers {
display: flex;
flex-direction: column;
height: 200px;
overflow-y: hidden;
scroll-behavior: smooth;
}
.rowOfNumbers h1 {
height: 200px;
display: flex;
align-items: center;
justify-content: center;
}
.rowOfNumbers > h1 {
font-size: 200px;
margin: 0;
}
.rowOfNumbersSec {
display: flex;
flex-direction: column;
height: 75px;
overflow-y: hidden;
scroll-behavior: smooth;
}
.rowOfNumbersSec > h1 {
height: 75px;
display: flex;
align-items: center;
justify-content: center;
}
.rowOfNumbersSec > h1 {
font-size: 75px;
margin: 0;
color: #585858;
}
#AmOrPm {
font-size: 75px;
margin: 0;
margin-left: 30px;
color: #585858;
}
h2 {
margin: 0;
font-size: 40px;
color: #888;
text-align: center;
}
</style>

View file

@ -0,0 +1,198 @@
<script module>
export function newTable(timetable) {
localStorage.setItem("TimeTable", JSON.stringify(timetable));
table = timetable;
}
let TemplateTable = {
Times: [
"07:50 - 08:50",
"08:50 - 09:40",
"09:40 - 10:30 ",
"10:30 - 11:00",
"11:00 - 12:00",
"12:00 - 01:00",
"01:00 - 02:00",
],
Monday: [
"English",
"Sanskrit",
"Math",
"Lunch",
"Hindi",
"Social Science",
"Science",
],
Tuesday: [
"English",
"Art & Craft",
"Math",
"Lunch",
"Hindi",
"Social Science",
"Science",
],
Wednesday: [
"English",
"GK",
"Math",
"Lunch",
"Hindi",
"Social Science",
"Science",
],
Thursday: [
"English",
"Sanskrit",
"Math",
"Lunch",
"Hindi",
"Social Science",
"Science",
],
Friday: [
"English",
"Computers",
"Math",
"Lunch",
"Hindi",
"Social Science",
"Science",
],
};
let table = $state();
let TempTimeTable = localStorage.getItem("TimeTable") || "";
if (TempTimeTable != "") {
table = JSON.parse(TempTimeTable);
} else {
newTable($state.snapshot(TemplateTable));
}
</script>
<div id="root">
<div id="wrap">
<div class="Header Row">
<span class="DayOfWeek" style="Opacity: 0;"></span>
{#each table.Times as time}
<span>{time}</span>
{/each}
</div>
<div class="Row">
{#if new Date().getDay() == 1}
<span class="DayOfWeek NavHighlight">Monday</span>
{:else}
<span class="DayOfWeek">Monday</span>
{/if}
{#each table.Monday as time}
{#if new Date().getDay() == 1}
<span class="highlight">{time}</span>
{:else}
<span>{time}</span>
{/if}
{/each}
</div>
<div class="Row">
{#if new Date().getDay() == 2}
<span class="DayOfWeek NavHighlight">Tuesday</span>
{:else}
<span class="DayOfWeek">Tuesday</span>
{/if}
{#each table.Tuesday as time}
{#if new Date().getDay() == 2}
<span class="highlight">{time}</span>
{:else}
<span>{time}</span>
{/if}
{/each}
</div>
<div class="Row">
{#if new Date().getDay() == 3}
<span class="DayOfWeek NavHighlight">Wednesday</span>
{:else}
<span class="DayOfWeek">Wednesday</span>
{/if}
{#each table.Wednesday as time}
{#if new Date().getDay() == 3}
<span class="highlight">{time}</span>
{:else}
<span>{time}</span>
{/if}
{/each}
</div>
<div class="Row">
{#if new Date().getDay() == 4}
<span class="DayOfWeek NavHighlight">Thursday</span>
{:else}
<span class="DayOfWeek">Thursday</span>
{/if}
{#each table.Thursday as time}
{#if new Date().getDay() == 4}
<span class="highlight">{time}</span>
{:else}
<span>{time}</span>
{/if}
{/each}
</div>
<div class="Row">
{#if new Date().getDay() == 5}
<span class="DayOfWeek NavHighlight">Friday</span>
{:else}
<span class="DayOfWeek">Friday</span>
{/if}
{#each table.Friday as time}
{#if new Date().getDay() == 5}
<span class="highlight">{time}</span>
{:else}
<span>{time}</span>
{/if}
{/each}
</div>
</div>
</div>
<style>
#root {
display: grid;
place-items: center;
}
#wrap {
display: flex;
background-color: #252525;
padding: 20px;
border-radius: 20px;
flex-direction: column;
gap: 10px;
}
.Row {
display: flex;
gap: 5px;
}
span {
font-size: 20px;
color: white;
background-color: #3f3f3f;
padding: 5px;
border-radius: 10px;
width: 140px;
text-align: center;
}
.Header > span {
background-color: #30492e;
}
.DayOfWeek {
width: 120px;
background-color: #30492e;
}
.highlight {
background-color: #707070;
display: block;
}
.NavHighlight {
background-color: #3b8235;
display: block;
}
</style>

View file

@ -0,0 +1,18 @@
<div class="bg-grey-900 flex h-full items-center justify-center">
<div class="flex flex-col items-center justify-center gap-1 rounded-lg bg-gray-900 p-8 shadow-lg">
<h1 class="m-[0] text-6xl">DaKahootClone</h1>
<p class="m-[0] mb-2 text-lg text-gray-400">The best ever kahoot clone.</p>
<a href="./join">
<button
class="cursor-pointer rounded-full bg-green-700 p-2 transition-all hover:scale-110 hover:-rotate-10"
>Join a game</button
></a
>
<a href="./create">
<button
class="cursor-pointer rounded-full bg-blue-700 p-2 transition-all hover:scale-110 hover:-rotate-10"
>Create and Host a game</button
>
</a>
</div>
</div>

View file

@ -49,7 +49,6 @@
<Answers questionsIndex={index} {answersIndex} />
{/each}
</div>
<input type="file">
<GenerateOptionsUsingAI {index} />
</div>
</div>

View file

@ -0,0 +1,51 @@
<script>
import { newNames, RandomNamesState } from "./main.svelte";
let names =
RandomNamesState.NotSelectedYet.join("\n") +
"\n" +
RandomNamesState.Selected.join("\n") +
"\n" +
RandomNamesState.Absent.join("\n");
let namesArray = [];
</script>
<div id="root">
<div id="root">
<h1>Edit Names</h1>
<p></p>
<textarea
bind:value={names}
id="box"
onchange={() => {
let namesArray = names.split("\n");
newNames(namesArray);
}}
></textarea>
</div>
</div>
<style>
#root {
display: flex;
flex-direction: column;
gap: 5px;
margin: 10px;
justify-content: center;
background-color: #303030;
padding: 10px;
margin: 20px;
border-radius: 10px;
}
#box {
width: 100%;
height: 500px;
background-color: #121212;
color: white;
border-radius: 10px;
resize: vertical;
font-size: 20px;
}
</style>

View file

@ -0,0 +1,163 @@
<script context="module">
import { RandomNamesState } from "./main.svelte";
let DragTempName = "na";
import "drag-drop-touch";
</script>
<div id="root">
<div
id="Selected"
on:dragover|preventDefault
role="list"
aria-label="drag name to this list!"
on:drop={(event) => {
event.preventDefault();
if (DragTempName !== "na") {
RandomNamesState.Selected.push(DragTempName);
DragTempName = "na";
}
}}
>
<h1>Selected</h1>
<div class="wrap">
{#each RandomNamesState.Selected as name, i}
<span
class="Selected"
draggable="true"
role="listitem"
aria-label="drag name to different list!"
on:dragstart={() => {
setTimeout(() => {
RandomNamesState.Selected.splice(i, 1);
DragTempName = name;
}, 100);
}}
>
{name}
</span>
{/each}
</div>
</div>
<hr />
<div
id="NotSelectedYet"
on:dragover|preventDefault
role="list"
aria-label="drag name to this list!"
on:drop={(event) => {
event.preventDefault();
if (DragTempName !== "na") {
RandomNamesState.NotSelectedYet.push(DragTempName);
DragTempName = "na";
}
}}
>
<h1>Not Selected Yet</h1>
<div class="wrap">
{#each RandomNamesState.NotSelectedYet as name, i}
<span
class="NotSelectedYet"
draggable="true"
role="listitem"
aria-label="drag name to different list!"
on:dragstart={() => {
setTimeout(() => {
RandomNamesState.NotSelectedYet.splice(i, 1);
DragTempName = name;
}, 100);
}}
>
{name}
</span>
{/each}
</div>
</div>
<hr />
<div
id="Absent"
on:dragover|preventDefault
role="list"
aria-label="drag name to this list!"
on:drop={(event) => {
event.preventDefault();
if (DragTempName !== "na") {
RandomNamesState.Absent.push(DragTempName);
DragTempName = "na";
}
}}
>
<h1>Absent</h1>
<div class="wrap">
{#each RandomNamesState.Absent as name, i}
<span
draggable="true"
class="Absent"
role="listitem"
aria-label="drag name to different list!"
on:dragstart={() => {
setTimeout(() => {
RandomNamesState.Absent.splice(i, 1);
DragTempName = name;
}, 100);
}}
>
{name}
</span>
{/each}
</div>
</div>
</div>
<style>
#root {
display: flex;
overflow-x: hidden;
}
span {
margin: 5px;
padding: 5px;
border-radius: 5px;
background-color: #4d4d4d;
color: white;
font-size: 30px;
}
h1 {
text-align: center;
font-size: 40px;
margin: 0;
}
#NotSelectedYet,
#Selected {
min-width: 40%;
max-width: 40%;
}
#Absent {
min-width: 20%;
max-width: 20%;
}
.wrap {
display: flex;
flex-wrap: wrap;
height: fit-content;
justify-content: center;
}
.NotSelectedYet {
color: #ffe677;
}
.Selected {
color: #a3ffa3;
}
.Absent {
color: #242424;
}
</style>

View file

@ -0,0 +1,220 @@
<script module>
import Selector from "./selector.svelte";
import TopDisplay from "./TopDisplay.svelte";
import EditNameOfStudents from "./EditNameOfStudents.svelte";
import {ShowAlert} from "../+page.svelte";
export let RandomNamesState = $state({
NotSelectedYet: [],
Selected: [],
Absent: [],
selectedStudent: "None yet!",
});
export function SelectStudent() {
if (RandomNamesState.NotSelectedYet.length != 0) {
let randomIndex = Math.floor(
Math.random() * RandomNamesState.NotSelectedYet.length
);
RandomNamesState.selectedStudent =
RandomNamesState.NotSelectedYet[randomIndex];
RandomNamesState.Selected = [
RandomNamesState.NotSelectedYet[randomIndex],
...RandomNamesState.Selected,
];
RandomNamesState.NotSelectedYet.splice(randomIndex, 1);
} else {
ShowAlert("All students have been selected.", "warning");
}
}
let TabOpen = $state({
v: false,
});
export function newNames(Names) {
localStorage.setItem("Names", JSON.stringify(Names));
RandomNamesState.NotSelectedYet = Names;
RandomNamesState.Selected = [];
RandomNamesState.Absent = [];
RandomNamesState.selectedStudent = "None yet!";
}
let TempelateNames = ["John", "Jane", "Alice", "Bob"];
let TempNames = localStorage.getItem("Names") || "";
if (TempNames != "") {
RandomNamesState.NotSelectedYet = JSON.parse(TempNames);
RandomNamesState.Selected = [];
RandomNamesState.Absent = [];
RandomNamesState.selectedStudent = "None yet!";
} else {
newNames($state.snapshot(TempelateNames));
}
</script>
<div id="wrap">
<div id="nav">
<a href="#/" aria-label="Back to main menu"
><button aria-label="Back to main menu"
><span class="front"
><svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="#FFFFFF"
><path
d="M240-200h120v-240h240v240h120v-360L480-740 240-560v360Zm-80 80v-480l320-240 320 240v480H520v-240h-80v240H160Zm320-350Z"
/></svg
> GO BACK
</span></button
></a
>
<h1>Random student selector</h1>
<div>
<button
aria-label="Back to main menu"
onclick={() => (TabOpen.v = true)}
><span class="front"
><svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="#FFFFFF"
><path
d="M400-480q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 66-47 113t-113 47ZM80-160v-112q0-33 17-62t47-44q51-26 115-44t141-18h14q6 0 12 2-8 18-13.5 37.5T404-360h-4q-71 0-127.5 18T180-306q-9 5-14.5 14t-5.5 20v32h252q6 21 16 41.5t22 38.5H80Zm560 40-12-60q-12-5-22.5-10.5T584-204l-58 18-40-68 46-40q-2-14-2-26t2-26l-46-40 40-68 58 18q11-8 21.5-13.5T628-460l12-60h80l12 60q12 5 22.5 11t21.5 15l58-20 40 70-46 40q2 12 2 25t-2 25l46 40-40 68-58-18q-11 8-21.5 13.5T732-180l-12 60h-80Zm40-120q33 0 56.5-23.5T760-320q0-33-23.5-56.5T680-400q-33 0-56.5 23.5T600-320q0 33 23.5 56.5T680-240ZM400-560q33 0 56.5-23.5T480-640q0-33-23.5-56.5T400-720q-33 0-56.5 23.5T320-640q0 33 23.5 56.5T400-560Zm0-80Zm12 400Z"
/></svg
> Edit list of names
</span></button
>
</div>
</div>
<div id="root">
<Selector />
<div id="listWrap"><TopDisplay /></div>
</div>
</div>
{#if TabOpen.v !== false}
<div id="UperLayer">
<div id="wrapClose">
<EditNameOfStudents />
<button
class="close"
onclick={() => (TabOpen.v = false)}
aria-label="close">CLOSE</button
>
</div>
</div>
{/if}
<style>
#wrap {
height: 100%;
display: flex;
flex-direction: column;
}
#nav {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #121212;
color: white;
}
button {
background: #292929;
border-radius: 12px;
border: none;
margin: 10px;
padding: 2px 0px;
cursor: pointer;
outline-offset: 4px;
max-width: 400px;
}
button:hover .front {
transform: translateY(-7px);
}
button:active .front {
transform: translateY(-2px);
}
.front {
display: flex;
text-align: center;
align-items: center;
padding: 5px;
border-radius: 12px;
background: #4d4d4d;
color: white;
transform: translateY(-4px);
transition: all 0.1s ease-in-out;
font-family: "JetBrains Mono", monospace;
font-size: 25px;
}
#root {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
h1 {
text-align: center;
margin: 5px 0px;
text-decoration: underline #444;
position: fixed;
top: 0;
left: 50%;
transform: translate(-50%, 0);
}
span {
font-size: 0.5em;
text-decoration: none;
color: #444;
}
#listWrap {
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
}
#UperLayer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
backdrop-filter: blur(5px);
background-color: rgba(0, 0, 0, 0.5);
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
}
#wrapClose {
display: flex;
flex-direction: column;
}
.close {
background-color: #2b2b2b;
color: #888;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
align-self: center;
}
</style>

View file

@ -0,0 +1,135 @@
<script>
import { RandomNamesState, SelectStudent } from "./main.svelte";
</script>
<div id="root">
<p>The latest selected student is:</p>
<h1>{RandomNamesState.selectedStudent}</h1>
<div id="options">
<button
aria-label="Back to main menu"
id="selectStudent"
onclick={() => {
SelectStudent();
}}
><span class="front">
<span>Select a random student</span>
</span></button
>
<div>
{#if RandomNamesState.Selected.length > 0}
<button
aria-label="Back to main menu"
onclick={() => {
if (
confirm(
"Are you sure you want to reset all the Selected names? This action cannot be undone."
)
) {
RandomNamesState.NotSelectedYet = [
...RandomNamesState.NotSelectedYet,
...RandomNamesState.Selected,
];
RandomNamesState.Selected = [];
RandomNamesState.selectedStudent = "None yet!";
}
}}
><span class="front">
<span>Reset selected</span>
</span></button
>{/if}
{#if RandomNamesState.Absent.length > 0}
<button
aria-label="Back to main menu"
onclick={() => {
if (
confirm(
"Are you sure you want to reset all the names? this will also move all the students to the 'Not Selected Yet' list. This action cannot be undone."
)
) {
RandomNamesState.NotSelectedYet = [
...RandomNamesState.NotSelectedYet,
...RandomNamesState.Absent,
];
RandomNamesState.Absent = [];
RandomNamesState.selectedStudent = "None yet!";
}
}}
><span class="front">
<span>Reset absentees</span>
</span></button
>{/if}
</div>
</div>
</div>
<style>
#root {
background-color: #222;
border-radius: 30px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding-top: 20px;
padding-left: 20px;
padding-right: 20px;
padding-bottom: 0px;
margin: 20px;
}
#options {
display: flex;
justify-content: space-between;
width: 100%;
}
button {
background: #292929;
border-radius: 12px;
border: none;
margin: 10px;
padding: 2px 0px;
cursor: pointer;
outline-offset: 4px;
width: fit-content;
margin-bottom: 20px;
}
button:hover .front {
transform: translateY(-7px);
}
button:active .front {
transform: translateY(-2px);
}
.front {
display: flex;
text-align: center;
align-items: center;
padding: 5px;
border-radius: 12px;
background: #4d4d4d;
color: white;
transform: translateY(-4px);
transition: all 0.1s ease-in-out;
font-family: "JetBrains Mono", monospace;
font-size: 25px;
gap: 5px;
}
h1 {
font-size: 120px;
margin: 10px;
}
p {
color: #aaa;
margin: 0;
}
#selectStudent > .front {
background-color: #0e71e2;
}
</style>

View file

@ -0,0 +1,182 @@
<script>
let text = $state("");
function speak() {
window.speechSynthesis.speak(
Object.assign(new SpeechSynthesisUtterance(text), {
rate: 0.5,
})
);
}
let TempelateCommonAnounce = $state(["Please be quiet"]);
let CommonAnounce = $state([]);
export function newNames(Names) {
localStorage.setItem("CommonAnounce", JSON.stringify(Names));
}
let TempCommonAnounce = localStorage.getItem("CommonAnounce") || "";
if (TempCommonAnounce != "") {
CommonAnounce = JSON.parse(TempCommonAnounce);
} else {
CommonAnounce = $state.snapshot(TempelateCommonAnounce);
localStorage.setItem("CommonAnounce", JSON.stringify(CommonAnounce));
}
</script>
<div id="root">
<div id="wrap">
<h1>Most Announced announcements</h1>
<div id="mostanouncedanounements">
{#each CommonAnounce as anouncement, i}
<div>
<button
class="anuncement"
onclick={() => {
text = anouncement;
speak();
}}
>
{anouncement}
</button>
<button
aria-label="Delete anouncement"
onclick={() => {
if (
confirm(
"Are you sure you want to delete this anouncement?"
)
) {
CommonAnounce.splice(i, 1);
localStorage.setItem(
"CommonAnounce",
JSON.stringify(CommonAnounce)
);
}
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
height="15px"
viewBox="0 -960 960 960"
width="15px"
fill="#FFFFFF"
><path
d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z"
/></svg
></button
>
</div>
{/each}
</div>
<hr />
<h1>Or announce something else</h1>
<div>
<input
bind:value={text}
placeholder="Type in here what you want to announce"
/>
<button onclick={speak}>Play</button>
</div>
{#if text}
<button
id="new"
onclick={() => {
CommonAnounce.push(text);
text = "";
localStorage.setItem(
"CommonAnounce",
JSON.stringify(CommonAnounce)
);
}}>Add "{text}" to "Most Announced announcements"</button
>
{/if}
</div>
</div>
<style>
#root {
height: 100%;
display: grid;
place-items: center;
}
#wrap {
display: flex;
flex-direction: column;
gap: 5px;
padding: 20px;
border-radius: 20px;
width: fit-content;
}
input {
font-size: 20px;
padding: 10px;
border-radius: 12px;
border: none;
background-color: #292929;
color: white;
width: 400px;
}
button {
font-size: 20px;
padding: 10px;
border-radius: 12px;
border: none;
background-color: #292929;
color: white;
cursor: pointer;
transition: all 0.1s ease-in-out;
}
button:hover {
background-color: #414141;
transform: rotateZ(-15deg) scale(1.2);
}
hr {
width: 100%;
height: 2px;
background-color: #292929;
border: none;
margin: 0;
}
h1 {
text-align: center;
margin: 0;
font-size: 30px;
}
#mostanouncedanounements {
display: flex;
flex-direction: column;
justify-content: center;
gap: 10px;
}
.anuncement:hover {
transform: scale(1.1);
}
.anuncement {
width: calc(100% - 40px);
}
#new {
width: fit-content;
align-self: center;
font-size: 15px;
}
#new:hover {
transform: scale(1.1);
}
</style>

View file

@ -0,0 +1,100 @@
<script>
import ActualAnnouncer from "./ActualAnnouncer.svelte";
</script>
<div id="wrap">
<div id="nav">
<a href="#/" aria-label="Back to main menu"
><button aria-label="Back to main menu"
><span class="front"
><svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="#FFFFFF"
><path
d="M240-200h120v-240h240v240h120v-360L480-740 240-560v360Zm-80 80v-480l320-240 320 240v480H520v-240h-80v240H160Zm320-350Z"
/></svg
> GO BACK
</span></button
></a
>
<h1>Announcer</h1>
</div>
<div id="root">
<ActualAnnouncer />
</div>
</div>
<style>
#wrap {
height: 100%;
display: flex;
flex-direction: column;
}
#nav {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #121212;
color: white;
}
button {
background: #292929;
border-radius: 12px;
border: none;
margin: 10px;
padding: 2px 0px;
cursor: pointer;
outline-offset: 4px;
max-width: 400px;
}
button:hover .front {
transform: translateY(-7px);
}
button:active .front {
transform: translateY(-2px);
}
.front {
display: flex;
text-align: center;
align-items: center;
padding: 5px;
border-radius: 12px;
background: #4d4d4d;
color: white;
transform: translateY(-4px);
transition: all 0.1s ease-in-out;
font-family: "JetBrains Mono", monospace;
font-size: 25px;
}
#root {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
h1 {
text-align: center;
margin: 5px 0px;
text-decoration: underline #444;
position: fixed;
top: 0;
left: 50%;
transform: translate(-50%, 0);
}
span {
font-size: 0.5em;
text-decoration: none;
color: #444;
}
</style>

View file

@ -0,0 +1,45 @@
<script>
import { newGame, WordLegnth } from "../logic.svelte.js";
import { TabOpen } from "./main.svelte";
let LetersSelected = WordLegnth.v;
</script>
<div id="root">
<h4>Select The Word legnth (between 3 and 10 letters)</h4>
<input
type="range"
id="vol"
name="vol"
min="3"
max="10"
bind:value={LetersSelected}
/>
<button
onclick={() => {
WordLegnth.v = LetersSelected;
newGame();
TabOpen.v = "none";
}}
>Start New Game with Word legnth of {LetersSelected} letters
</button>
</div>
<style>
#root {
display: flex;
flex-direction: column;
gap: 5px;
margin: 10px;
justify-content: center;
background-color: #303030;
padding: 10px;
margin: 20px;
border-radius: 10px;
width: 400px;
}
h4 {
text-align: center;
margin: 0px;
}
</style>

View file

@ -0,0 +1,58 @@
<script module>
import { newGame, WordLegnth } from "../logic.svelte.js";
import WordLegnthSetings from "./WordLegnthSetings.svelte";
import Stats from "./stats.svelte";
export let TabOpen = $state({ v: "none" });
export function OpenTab(type) {
TabOpen.v = type;
}
</script>
{#if TabOpen.v !== "none"}
<div id="UperLayer">
<div id="wrap">
{#if TabOpen.v == "WordLength"}
<WordLegnthSetings />
{:else if TabOpen.v == "Stats"}
<Stats />
{/if}
<button
class="close"
onclick={() => (TabOpen.v = "none")}
aria-label="close">CLOSE</button
>
</div>
</div>
{/if}
<style>
#UperLayer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
backdrop-filter: blur(5px);
background-color: rgba(0, 0, 0, 0.5);
z-index: 1;
display: grid;
place-items: center;
}
#wrap {
display: flex;
flex-direction: column;
}
.close {
background-color: #2b2b2b;
color: #888;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
align-self: center;
}
</style>

View file

@ -0,0 +1,155 @@
<script>
import { data, WordLegnth } from "../logic.svelte.js";
// svelte-ignore non_reactive_update
let LetersSelected = JSON.stringify(WordLegnth.v);
let dataPoints = data.value[LetersSelected];
import { onMount } from "svelte";
import Chart from "chart.js/auto";
let canvas;
let chart;
onMount(() => {
const ctx = canvas.getContext("2d");
chart = new Chart(ctx, {
type: "line",
data: {
labels: dataPoints.map((_, i) => `Game ${i + 1}`),
datasets: [
{
label: "Number Of Guesses Taken to Win",
data: $state.snapshot(dataPoints),
borderColor: "rgba(75, 192, 192, 1)",
backgroundColor: "rgba(75, 192, 192, 0.2)",
fill: true,
tension: 0.3,
},
],
},
options: {
responsive: true,
scales: {
y: {
beginAtZero: true,
},
},
},
});
});
let Avgguesses = $state(
(
dataPoints.reduce((acc, val) => acc + val, 0) / dataPoints.length
).toFixed(2)
);
let TotalWins = $state(dataPoints.length);
$effect(() => {
const snapshot = JSON.stringify(data.value);
UpdateChart(data.value);
});
function UpdateChart(val) {
dataPoints = data.value[LetersSelected];
if (chart) {
chart.data.labels = dataPoints.map((_, i) => `Game ${i + 1}`);
chart.data.datasets[0].data = $state.snapshot(dataPoints);
chart.update();
}
Avgguesses = (
dataPoints.reduce((acc, val) => acc + val, 0) / dataPoints.length
).toFixed(2);
TotalWins = dataPoints.length;
}
</script>
<div id="root">
<p>
Stats For:
<select
bind:value={LetersSelected}
onchange={() => {
dataPoints = data.value[LetersSelected];
if (chart) {
chart.data.labels = dataPoints.map(
(_, i) => `Point ${i + 1}`
);
chart.data.datasets[0].data = $state.snapshot(dataPoints);
chart.update();
}
Avgguesses = (
dataPoints.reduce((acc, val) => acc + val, 0) /
dataPoints.length
).toFixed(2);
TotalWins = dataPoints.length;
}}
>
<option value="3">3 Letters</option>
<option value="4">4 Letters</option>
<option value="5" selected>5 Letters</option>
<option value="6">6 Letters</option>
<option value="7">7 Letters</option>
<option value="8">8 Letters</option>
<option value="9">9 Letters</option>
<option value="10">10 Letters</option>
</select>
</p>
<div id="toprow">
<div class="toprow">
<h2>Total WINS</h2>
<h1>{TotalWins}</h1>
</div>
<div class="toprow">
<h2>Avg No. of guesses</h2>
<h1>{Avgguesses}</h1>
</div>
</div>
<canvas bind:this={canvas}></canvas>
</div>
<style>
#root {
display: flex;
flex-direction: column;
gap: 5px;
margin: 10px;
justify-content: center;
background-color: #303030;
padding: 10px;
margin: 20px;
border-radius: 10px;
width: 700px;
}
h2,
h1,
p {
text-align: center;
margin: 0px;
}
h2 {
font-size: 20px;
color: #888;
}
#toprow {
display: inline-flex;
gap: 20px;
}
.toprow {
background-color: #3f3f3f;
border-radius: 10px;
}
.toprow:nth-child(1n) {
min-width: 35%;
}
.toprow:nth-child(2n) {
width: 100%;
}
</style>

View file

@ -0,0 +1,148 @@
<script>
import Keyboard from "./game/keyboard.svelte";
import Display from "./game/display.svelte";
import { onMount } from "svelte";
import { handleKey } from "./logic.svelte.js";
import Right from "./InfoAndSetings/main.svelte";
import { OpenTab } from "./InfoAndSetings/main.svelte";
onMount(() => {
window.addEventListener("keydown", handleKey);
});
</script>
<div id="nav">
<a href="#/" aria-label="Back to main menu"
><button aria-label="Back to main menu"
><span class="front"
><svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="#FFFFFF"
><path
d="M240-200h120v-240h240v240h120v-360L480-740 240-560v360Zm-80 80v-480l320-240 320 240v480H520v-240h-80v240H160Zm320-350Z"
/></svg
> GO BACK
</span></button
></a
>
<h1>Wordle</h1>
<div>
<button
aria-label="Back to main menu"
onclick={() => OpenTab("WordLength")}
><span class="front"
><svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="#FFFFFF"
><path
d="M320-80 160-240l160-160 57 56-64 64h334l-63-64 56-56 160 160L640-80l-57-56 64-64H313l63 64-56 56ZM200-480v-400h80v400h-80Zm240 0v-400h80v400h-80Zm240 0v-400h80v400h-80Z"
/></svg
> Change word legnth
</span></button
>
<button aria-label="Back to main menu" onclick={() => OpenTab("Stats")}
><span class="front"
><svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="#FFFFFF"
><path
d="m105-399-65-47 200-320 120 140 160-260 120 180 135-214 65 47-198 314-119-179-152 247-121-141-145 233Zm475 159q42 0 71-29t29-71q0-42-29-71t-71-29q-42 0-71 29t-29 71q0 42 29 71t71 29ZM784-80 676-188q-21 14-45.5 21t-50.5 7q-75 0-127.5-52.5T400-340q0-75 52.5-127.5T580-520q75 0 127.5 52.5T760-340q0 26-7 50.5T732-244l108 108-56 56Z"
/></svg
> Stats
</span></button
>
</div>
</div>
<div id="root">
<div id="left">
<Display />
<Keyboard />
</div>
<Right />
</div>
<style>
#nav {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #121212;
color: white;
}
button {
background: #292929;
border-radius: 12px;
border: none;
margin: 10px;
padding: 2px 0px;
cursor: pointer;
outline-offset: 4px;
max-width: 400px;
}
button:hover .front {
transform: translateY(-7px);
}
button:active .front {
transform: translateY(-2px);
}
.front {
display: flex;
text-align: center;
align-items: center;
padding: 5px;
border-radius: 12px;
background: #4d4d4d;
color: white;
transform: translateY(-4px);
transition: all 0.1s ease-in-out;
font-family: "JetBrains Mono", monospace;
font-size: 25px;
}
#root {
height: 90%;
display: flex;
margin: 0;
font-family: "Sour Gummy", sans-serif;
background-color: #121212;
color: white;
}
#left {
width: 100%;
height: 100%;
border-radius: 20px;
margin: 20px;
margin-top: 5px;
border: 2px solid #444;
font-family: "JetBrains Mono", monospace;
}
h1 {
text-align: center;
margin: 5px 0px;
text-decoration: underline #444;
position: fixed;
top: 0;
left: 50%;
transform: translate(-50%, 0);
}
span {
font-size: 0.5em;
text-decoration: none;
color: #444;
}
</style>

View file

@ -0,0 +1,73 @@
<script>
import { CurrentWord, words, WordLegnth } from "../logic.svelte.js";
</script>
<div id="DisplayOfWords">
{#each words.v as word}
<div class="word">
{#each word as letter}
<span class={letter[1]}>{letter[0]}</span>
{/each}
</div>
{/each}
<div class="word">
{#each Array(WordLegnth.v) as _, i}
<span>{CurrentWord.v[i] || ""}</span>
{/each}
</div>
</div>
<style>
#DisplayOfWords {
height: calc(100% - 320px);
border: 2px solid #202020;
margin: 20px;
border-radius: 10px;
overflow-y: auto;
}
.word {
display: flex;
gap: 5px;
margin: 10px;
justify-content: center;
}
span {
width: 70px;
height: 70px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 10px;
font-size: 50px;
border: 2px solid #444;
}
.c {
background-color: #2b5f2d;
}
.d {
background-color: #804d00;
}
.w {
background-color: #2b2b2b;
}
/* width */
::-webkit-scrollbar {
width: 10px;
}
/* Track */
::-webkit-scrollbar-track {
border: 1px solid #5c5c5c;
border-radius: 10px;
}
/* Handle */
::-webkit-scrollbar-thumb {
background: #3f3f3f;
border-radius: 10px;
}
</style>

View file

@ -0,0 +1,71 @@
<script>
import { keys, ButtonPressed } from "../logic.svelte.js";
</script>
<div id="root">
<div class="word">
{#each keys.v.slice(0, 10) as key}
<button on:click={() => ButtonPressed(key[0])} class={key[1]}
>{key[0]}</button
>
{/each}
</div>
<div class="word">
{#each keys.v.slice(10, 19) as key}
<button on:click={() => ButtonPressed(key[0])} class={key[1]}
>{key[0]}</button
>
{/each}
</div>
<div class="word">
{#each keys.v.slice(19) as key}
<button on:click={() => ButtonPressed(key[0])} class={key[1]}
>{key[0]}</button
>
{/each}
</div>
</div>
<style>
#root {
height: 255px;
margin: 20px;
border-radius: 10px;
border: 2px solid #202020;
}
.word {
display: flex;
gap: 5px;
margin: 10px;
justify-content: center;
}
button {
background: none;
font-family: "JetBrains Mono", monospace;
color: #888;
width: 80px;
height: 70px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 10px;
font-size: 50px;
border: 2px solid #444;
}
.c {
background-color: #2b5f2d;
}
.d {
background-color: #804d00;
}
.w {
background-color: #2b2b2b;
}
.o {
background-color: #00202c;
}
</style>

View file

@ -0,0 +1,220 @@
import wordExists from "word-exists";
import { generate } from "random-words";
import { ShowAlert } from "../+layout.svelte";
export let WordLegnth = $state({ v: 5 });
let CorrectWord = generate({
minLength: WordLegnth.v,
maxLength: WordLegnth.v,
});
console.log("CorrectWord: ", CorrectWord);
export let words = $state({ v: [] });
export let CurrentWord = $state({ v: [] });
export let keys = $state({
v: [
["Q", "n"],
["W", "n"],
["E", "n"],
["R", "n"],
["T", "n"],
["Y", "n"],
["U", "n"],
["I", "n"],
["O", "n"],
["P", "n"],
["A", "n"],
["S", "n"],
["D", "n"],
["F", "n"],
["G", "n"],
["H", "n"],
["J", "n"],
["K", "n"],
["L", "n"],
["⌫", "o"],
["Z", "n"],
["X", "n"],
["C", "n"],
["V", "n"],
["B", "n"],
["N", "n"],
["M", "n"],
["⏎", "o"],
],
});
export function newGame() {
CorrectWord = generate({
minLength: WordLegnth.v,
maxLength: WordLegnth.v,
});
console.log("CorrectWord: ", CorrectWord);
words.v = [];
CurrentWord.v = [];
keys.v = [
["Q", "n"],
["W", "n"],
["E", "n"],
["R", "n"],
["T", "n"],
["Y", "n"],
["U", "n"],
["I", "n"],
["O", "n"],
["P", "n"],
["A", "n"],
["S", "n"],
["D", "n"],
["F", "n"],
["G", "n"],
["H", "n"],
["J", "n"],
["K", "n"],
["L", "n"],
["⌫", "o"],
["Z", "n"],
["X", "n"],
["C", "n"],
["V", "n"],
["B", "n"],
["N", "n"],
["M", "n"],
["⏎", "o"],
];
}
function GameWin() {
ShowAlert("You win!", "success");
data.value[WordLegnth.v].push(words.v.length);
localStorage.setItem("WordleGamesData", JSON.stringify(data.value));
newGame();
}
function SendWord(word) {
let result = Array(word.length).fill(null);
let used = Array(CorrectWord.length).fill(false);
// First pass: exact matches
for (let i = 0; i < word.length; i++) {
if (word[i].toLowerCase() === CorrectWord[i].toLowerCase()) {
result[i] = [word[i].toUpperCase(), "c"];
used[i] = true;
}
}
// Second pass: wrong place but correct letter
for (let i = 0; i < word.length; i++) {
if (result[i]) continue;
let found = false;
for (let j = 0; j < CorrectWord.length; j++) {
if (!used[j] && word[i].toLowerCase() === CorrectWord[j].toLowerCase()) {
found = true;
used[j] = true;
break;
}
}
result[i] = found ? [word[i].toUpperCase(), "d"] : [word[i].toUpperCase(), "w"];
}
words.v.push(result);
setTimeout(() => {
document.getElementById("DisplayOfWords").scrollTo({
top: document.getElementById("DisplayOfWords").scrollHeight,
behavior: "smooth",
});
}, 100);
// Update keyboard status
for (let [letter, status] of result) {
let keyIndex = keys.v.findIndex((k) => k[0].toLowerCase() === letter.toLowerCase());
if (keyIndex !== -1) {
let current = keys.v[keyIndex][1];
if (status === "c") {
keys.v[keyIndex][1] = "c";
} else if (status === "d" && current === "n") {
keys.v[keyIndex][1] = "d";
} else if (status === "w" && current === "n") {
keys.v[keyIndex][1] = "w";
}
}
}
// Check for win
if (result.every(([_, status]) => status === "c")) {
GameWin();
}
}
export function ButtonPressed(key) {
document.getElementById("DisplayOfWords").scrollTo({
top: document.getElementById("DisplayOfWords").scrollHeight,
behavior: "smooth",
});
if (key === "⏎") {
if (CurrentWord.v.length === WordLegnth.v) {
let word = CurrentWord.v.join("").toUpperCase();
if (wordExists(word)) {
SendWord(CurrentWord.v);
CurrentWord.v = [];
} else {
ShowAlert("Not a valid word", "error");
}
}
return;
} else if (key === "⌫") {
CurrentWord.v.pop();
return;
}
if (CurrentWord.v.length === WordLegnth.v) {
return;
}
CurrentWord.v.push(key);
}
export function handleKey(event) {
const key = event.key.toLowerCase();
if (key === "enter") {
ButtonPressed("⏎");
} else if (key === "backspace") {
ButtonPressed("⌫");
} else if (/^[a-z]$/.test(key)) {
ButtonPressed(key.toUpperCase());
}
}
export let data = $state({
value: {
3: [],
4: [],
5: [],
6: [],
7: [],
8: [],
9: [],
10: [],
},
});
let WordleGamesData = localStorage.getItem("WordleGamesData") || "";
if (WordleGamesData != "") {
data.value = JSON.parse(WordleGamesData);
} else {
data.value = {
3: [],
4: [],
5: [],
6: [],
7: [],
8: [],
9: [],
10: [],
};
}