Compare commits
10 commits
dc4674f031
...
389a7de0b5
Author | SHA1 | Date | |
---|---|---|---|
389a7de0b5 | |||
d448517fb3 | |||
ff726f6ba3 | |||
3571817524 | |||
b470cf0e39 | |||
2e09e54b18 | |||
f28f2caec5 | |||
d2878e7811 | |||
677176e0f9 | |||
dcf1fed0c3 |
6 changed files with 163 additions and 45 deletions
|
@ -3,25 +3,38 @@
|
||||||
import Card from "./card.svelte";
|
import Card from "./card.svelte";
|
||||||
import StatsAndButtons from "./StatsAndButtons.svelte";
|
import StatsAndButtons from "./StatsAndButtons.svelte";
|
||||||
|
|
||||||
import { stats, resetDeck,SetNewDeck } from "./logic.svelte.js";
|
import { stats, SelectNewDeck, SetNewDeck, StorageDeck } from "./logic.svelte.js";
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import tempelateDeck from "./tempelateDeck.json";
|
import tempelateDeck from "./tempelateDeck.json";
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
SetNewDeck(JSON.parse(localStorage.getItem("deck")) || tempelateDeck);
|
SetNewDeck(JSON.parse(localStorage.getItem("deck")) || tempelateDeck, true);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex h-full flex-col overflow-hidden">
|
<div class="flex h-full flex-col overflow-hidden">
|
||||||
{#if stats.isDeckEmpty}
|
{#if stats.isDeckEmpty}
|
||||||
<div class="flex flex-1 flex-col items-center justify-center gap-3">
|
<div class="flex flex-1 flex-col items-center justify-center gap-3">
|
||||||
<h1 class="text-4xl">Hey, You learned everything!</h1>
|
<h1 class="text-4xl">Choose a Deck To learn from!</h1>
|
||||||
<button onclick={() => resetDeck()} class="big btn green">Reset Deck</button>
|
<div>
|
||||||
|
<select
|
||||||
|
id="ChooseTheDeck"
|
||||||
|
onchange={(event) => {
|
||||||
|
SelectNewDeck(event.target.value);
|
||||||
|
}}
|
||||||
|
class="input"
|
||||||
|
>
|
||||||
|
<option value="" disabled selected> goo ahead choose one! </option>
|
||||||
|
{#each StorageDeck.v as deckOption, i}
|
||||||
|
<option value={i}>{deckOption.deckName}</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="flex flex-1 flex-col items-center justify-center gap-2">
|
<div class="flex flex-1 flex-col items-center justify-center">
|
||||||
<div class="flex flex-col gap-1 text-center">
|
<div class="flex flex-col gap-1 text-center">
|
||||||
<div class="flex items-center justify-center p-2">
|
<div class="flex flex-col items-center justify-center gap-5 p-2">
|
||||||
<StatsAndButtons />
|
<StatsAndButtons />
|
||||||
</div>
|
</div>
|
||||||
<Card />
|
<Card />
|
||||||
|
|
|
@ -1,24 +1,72 @@
|
||||||
<script>
|
<script>
|
||||||
import { SetNewDeck, deck, stats } from "./logic.svelte";
|
import { SetNewDeck, StorageDeck } from "./logic.svelte";
|
||||||
import toast from "svelte-5-french-toast";
|
import toast from "svelte-5-french-toast";
|
||||||
|
|
||||||
let LocalDeck = $state($state.snapshot(deck));
|
|
||||||
|
|
||||||
function saveDeck() {
|
function saveDeck() {
|
||||||
localStorage.setItem("deck", JSON.stringify(LocalDeck));
|
localStorage.setItem("deck", JSON.stringify(deck));
|
||||||
SetNewDeck(LocalDeck);
|
SetNewDeck(deck);
|
||||||
toast.success("Deck saved successfully! You can now close this window.");
|
toast.success("Deck saved successfully! You can now close this window.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let CurrentlyEditingDeckId = $state(0);
|
||||||
|
|
||||||
|
let deck = $state($state.snapshot(StorageDeck).v);
|
||||||
|
|
||||||
|
let DeckOptions;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex flex-col items-center gap-7 rounded border-2 bg-zinc-800 p-3">
|
<div class="flex flex-col items-center gap-7 rounded border-2 bg-zinc-800 p-3">
|
||||||
<div class="flex w-full flex-col gap-2">
|
<div class="flex w-full flex-col gap-2">
|
||||||
|
<div class="mb-2">
|
||||||
|
<label for="SelectOneDeckToEdit" class="text-lg leading-0.5 text-gray-500">
|
||||||
|
What deck do you want to edit?
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
bind:this={DeckOptions}
|
||||||
|
onchange={() => {
|
||||||
|
if (DeckOptions.value == "new") {
|
||||||
|
deck.push({
|
||||||
|
deckName: "Some New Deck",
|
||||||
|
cards: [{ Q: "Some Quetion", a: "Some Awnser" }],
|
||||||
|
});
|
||||||
|
CurrentlyEditingDeckId = deck.length - 1;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
DeckOptions.value = (deck.length - 1).toString();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
CurrentlyEditingDeckId = DeckOptions.value;
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
class="input"
|
||||||
|
id="SelectOneDeckToEdit"
|
||||||
|
>
|
||||||
|
{#each deck as d, i}
|
||||||
|
<option value={i}>{d.deckName}</option>
|
||||||
|
{/each}
|
||||||
|
<option value="new">Create a new deck</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-2">
|
||||||
|
<label for="NameOfthisDeck" class="text-lg leading-0.5 text-gray-500">
|
||||||
|
Name Of this Deck?
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="input mt-1"
|
||||||
|
bind:value={deck[CurrentlyEditingDeckId].deckName}
|
||||||
|
id="NameOfthisDeck"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="flex w-full gap-2 text-3xl">
|
<div class="flex w-full gap-2 text-3xl">
|
||||||
<span class="flex-1">Question</span>
|
<span class="flex-1">Question</span>
|
||||||
<span class="flex-1">Answer</span>
|
<span class="flex-1">Answer</span>
|
||||||
<button aria-label="delete" class="btn invisible"><i class="nf nf-md-delete"></i></button>
|
<button aria-label="delete" class="btn invisible h-0"><i class="nf nf-md-delete"></i></button>
|
||||||
</div>
|
</div>
|
||||||
{#each LocalDeck as card, i}
|
|
||||||
|
{#each deck[CurrentlyEditingDeckId].cards as card, i}
|
||||||
<div class="flex w-full gap-2">
|
<div class="flex w-full gap-2">
|
||||||
<input type="text" class="input flex-1" bind:value={card.Q} />
|
<input type="text" class="input flex-1" bind:value={card.Q} />
|
||||||
<input type="text" class="input flex-1" bind:value={card.a} />
|
<input type="text" class="input flex-1" bind:value={card.a} />
|
||||||
|
@ -26,20 +74,36 @@
|
||||||
aria-label="delete"
|
aria-label="delete"
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
if (confirm("Are you sure you want to delete this card?")) {
|
if (confirm("Are you sure you want to delete this card?")) {
|
||||||
LocalDeck.splice(i, 1);
|
deck[CurrentlyEditingDeckId].cards.splice(i, 1);
|
||||||
toast.success("Card deleted successfully! To make it apply, please save the deck.");
|
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
class="btn dull"><i class="nf nf-md-delete"></i></button
|
class="btn dull"
|
||||||
>
|
>
|
||||||
|
<i class="nf nf-md-delete"></i>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-3">
|
<div class="flex gap-3">
|
||||||
<button
|
<button
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
LocalDeck.push({ Q: "", a: "" });
|
if (deck.length == 2) {
|
||||||
toast.success("New card added! To make it apply, please save the deck.");
|
toast.error("You need to have at least 1 deck");
|
||||||
|
} else if (confirm("Are you sure you want to delete this deck?")) {
|
||||||
|
deck.splice(CurrentlyEditingDeckId, 1);
|
||||||
|
CurrentlyEditingDeckId = Math.max(0, CurrentlyEditingDeckId - 1);
|
||||||
|
DeckOptions.value = CurrentlyEditingDeckId.toString();
|
||||||
|
toast.success("Deck deleted successfully");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
class="btn"
|
||||||
|
>
|
||||||
|
<i class="nf nf-md-layers_remove"></i>
|
||||||
|
Delete this Deck
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onclick={() => {
|
||||||
|
deck[CurrentlyEditingDeckId].cards.push({ Q: "", a: "" });
|
||||||
}}
|
}}
|
||||||
class="btn"
|
class="btn"
|
||||||
>
|
>
|
||||||
|
@ -47,8 +111,8 @@
|
||||||
Add New Card
|
Add New Card
|
||||||
</button>
|
</button>
|
||||||
<button onclick={saveDeck} class="btn">
|
<button onclick={saveDeck} class="btn">
|
||||||
<i class="nf nf-fa-save"></i>
|
<i class="nf nf-md-content_save"></i>
|
||||||
Save
|
Save All Changes You Made
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
export let card = $state({ Q: "", a: "" });
|
export let card = $state({ Q: "", a: "" });
|
||||||
|
|
||||||
export let statusOfCard = $state({
|
export let statusOfCard = $state({
|
||||||
|
@ -9,37 +8,41 @@ export let statusOfCard = $state({
|
||||||
entering: false,
|
entering: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
export let deck = [
|
export let StorageDeck = $state({ v: [] });
|
||||||
{ Q: "Best programer in the world?", a: "RezHackXYZ" },
|
|
||||||
{ Q: "Best coding community?", a: "HackClub" },
|
|
||||||
{ Q: "Will @Shub go totally bankrupt?", a: "yes!" },
|
|
||||||
];
|
|
||||||
|
|
||||||
export function SetNewDeck (newDeck) {
|
export let deck = $state({ v: [] });
|
||||||
deck = newDeck;
|
|
||||||
|
export function SetNewDeck(newDeck, ThisIsOfPageLoad = true) {
|
||||||
|
StorageDeck.v = newDeck;
|
||||||
|
resetDeck();
|
||||||
|
stats.isDeckEmpty = ThisIsOfPageLoad;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SelectNewDeck(deckNumber) {
|
||||||
|
deck.v = StorageDeck.v[deckNumber].cards;
|
||||||
resetDeck();
|
resetDeck();
|
||||||
}
|
}
|
||||||
|
|
||||||
export let stats = $state({
|
export let stats = $state({
|
||||||
isDeckEmpty: false,
|
isDeckEmpty: true,
|
||||||
AnswerKnown: 0,
|
AnswerKnown: 0,
|
||||||
AnswerNotKnown: 0,
|
AnswerNotKnown: 0,
|
||||||
AnswerNotChecked: deck.length,
|
AnswerNotChecked: deck.v.length,
|
||||||
});
|
});
|
||||||
|
|
||||||
let CurrentDeck = {
|
let CurrentDeck = {
|
||||||
AnswersKnown: [],
|
AnswersKnown: [],
|
||||||
AnswersNotKnown: [],
|
AnswersNotKnown: [],
|
||||||
AnswersNotChecked: $state.snapshot(deck),
|
AnswersNotChecked: $state.snapshot(deck).v,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function resetDeck() {
|
export function resetDeck() {
|
||||||
CurrentDeck.AnswersKnown = [];
|
CurrentDeck.AnswersKnown = [];
|
||||||
CurrentDeck.AnswersNotKnown = [];
|
CurrentDeck.AnswersNotKnown = [];
|
||||||
CurrentDeck.AnswersNotChecked = $state.snapshot(deck);
|
CurrentDeck.AnswersNotChecked = $state.snapshot(deck).v;
|
||||||
stats.AnswerKnown = 0;
|
stats.AnswerKnown = 0;
|
||||||
stats.AnswerNotKnown = 0;
|
stats.AnswerNotKnown = 0;
|
||||||
stats.AnswerNotChecked = deck.length;
|
stats.AnswerNotChecked = deck.v.length;
|
||||||
stats.isDeckEmpty = false;
|
stats.isDeckEmpty = false;
|
||||||
SetNewCard();
|
SetNewCard();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,26 @@
|
||||||
[
|
[
|
||||||
{ "Q": "Best programer in the world?", "a": "RezHackXYZ" },
|
{
|
||||||
{ "Q": "Best coding community?", "a": "HackClub" },
|
"deckName": "Tech",
|
||||||
{ "Q": "Will @Shub go totally bankrupt?", "a": "yes!" }
|
"cards": [
|
||||||
|
{ "Q": "What is Svelte?", "a": "Best web dev Framework ever." },
|
||||||
|
{ "Q": "What is a component?", "a": "A reusable piece of UI in Svelte." },
|
||||||
|
{ "Q": "How do you create a reactive variable?", "a": "$: variableName = value;" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"deckName": "Math Basics",
|
||||||
|
"cards": [
|
||||||
|
{ "Q": "What is 2 + 2?", "a": "4" },
|
||||||
|
{ "Q": "What is the square root of 16?", "a": "4" },
|
||||||
|
{ "Q": "What is 5 * 6?", "a": "30" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"deckName": "Geography",
|
||||||
|
"cards": [
|
||||||
|
{ "Q": "What is the capital of France?", "a": "Paris" },
|
||||||
|
{ "Q": "Which continent is Egypt in?", "a": "Africa" },
|
||||||
|
{ "Q": "What is the largest ocean?", "a": "Pacific Ocean" }
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
import { createGame } from "./createGame.js";
|
import { createGame } from "./createGame.js";
|
||||||
|
|
||||||
let userInput = "";
|
let userInput = "";
|
||||||
|
let numberOfQuestions;
|
||||||
|
|
||||||
let AIPrompt = `
|
let AIPrompt = `
|
||||||
You are the AI of a quiz game.
|
You are the AI of a quiz game.
|
||||||
|
@ -13,19 +14,18 @@ Generate a list of quiz questions with possible answers and the correct answer i
|
||||||
Each question must have:
|
Each question must have:
|
||||||
- A "questionText" (what the question is about)
|
- A "questionText" (what the question is about)
|
||||||
- A "timeLimit" (in seconds, any of these: null (no time limit), 5, 10, 15, 30, 60, 120, 300)
|
- A "timeLimit" (in seconds, any of these: null (no time limit), 5, 10, 15, 30, 60, 120, 300)
|
||||||
- An "type" (only set to "SingleAnswer" for now)
|
|
||||||
- An "options" (an array of options with at least 2 and at most 8 options)
|
- An "options" (an array of options with at least 2 and at most 8 options)
|
||||||
- A "CorrectOption" (an object with a key "SingleAnswer" and a value that is the index of the correct answer)
|
- A "CorrectOption" (an object with a key "SingleAnswer" and a value that is the index of the correct answer)
|
||||||
- A "hasMedia" (boolean indicating if the question has media) only set to true if you are sure the URL is valid and related to the question.
|
|
||||||
- A "mediaURL" (a URL to the media, can be null if no media is present) only add this if you are sure the URL is valid and related to the question.
|
|
||||||
Ensure the questions are diverse.
|
Ensure the questions are diverse.
|
||||||
Example format:
|
Example format:
|
||||||
[{"questionText":"What should you do when you're free?","timeLimit":15,"type":"SingleAnswer","options":["Do something in real life!","Play video games","Code!","Touch grass!"],"CorrectOption":{"SingleAnswer":2},"hasMedia":false,"mediaURL":null},{"questionText":"Is RezHackXYZ the best programmer in the world?","timeLimit":5,"type":"SingleAnswer","options":["Yes :)","No :("],"CorrectOption":{"SingleAnswer":0},"hasMedia":true,"mediaURL":"https://github.com/RezHackXYZ.png"},{"questionText":"Best place in the world?","timeLimit":5,"type":"SingleAnswer","options":["Google","Microsoft","Apple","Samsung","Hack Club!! :D","Amazon","Facebook","Twitter"],"CorrectOption":{"SingleAnswer":4},"hasMedia":false,"mediaURL":null}]
|
[{"questionText":"What should you do when you're free?","timeLimit":15,"options":["Do something in real life!","Play video games","Code!","Touch grass!"],"CorrectOption":2},{"questionText":"Is RezHackXYZ the best programmer in the world?","timeLimit":5,"options":["Yes :)","No :("],"CorrectOption":0},{"questionText":"Best place in the world?","timeLimit":5,"options":["Google","Microsoft","Apple","Samsung","Hack Club!! :D","Amazon","Facebook","Twitter"],"CorrectOption":4}]
|
||||||
|
|
||||||
JUST PROVIDE THE JSON AND NOTHING ELSE.
|
JUST PROVIDE THE JSON AND NOTHING ELSE.
|
||||||
|
|
||||||
The user's topic of interest is:
|
The user's topic of interest is:
|
||||||
[topic]
|
[topic]
|
||||||
|
|
||||||
|
The User wants [number of questions] questions.
|
||||||
`;
|
`;
|
||||||
|
|
||||||
async function ApiCall() {
|
async function ApiCall() {
|
||||||
|
@ -38,7 +38,7 @@ The user's topic of interest is:
|
||||||
messages: [
|
messages: [
|
||||||
{
|
{
|
||||||
role: "user",
|
role: "user",
|
||||||
content: AIPrompt.replace("[topic]", userInput),
|
content: AIPrompt.replace("[topic]", userInput).replace("[number of questions]", numberOfQuestions),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
@ -46,7 +46,17 @@ The user's topic of interest is:
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
QuestionsData.v = JSON.parse(data.choices[0].message.content);
|
QuestionsData.v = JSON.parse(data.choices[0].message.content).map((q) => ({
|
||||||
|
questionText: q.questionText,
|
||||||
|
timeLimit: q.timeLimit,
|
||||||
|
type: "SingleAnswer",
|
||||||
|
options: q.options,
|
||||||
|
CorrectOption: {SingleAnswer: q.CorrectOption},
|
||||||
|
hasMedia: false,
|
||||||
|
mediaURL: null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (ParsingTry <= 5) {
|
if (ParsingTry <= 5) {
|
||||||
ParsingTry++;
|
ParsingTry++;
|
||||||
|
@ -60,7 +70,7 @@ The user's topic of interest is:
|
||||||
async function GenerateQuestionsUsingAI() {
|
async function GenerateQuestionsUsingAI() {
|
||||||
ParsingTry = 0;
|
ParsingTry = 0;
|
||||||
userInput = prompt(
|
userInput = prompt(
|
||||||
"Enter the topic and number of questions you want with any instructions for the ai, note: doing this will delete all you previous questions and its not undo able",
|
"Enter the topic you want with any instructions for the ai, note: doing this will delete all you previous questions and its not undo able",
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!userInput) {
|
if (!userInput) {
|
||||||
|
@ -68,6 +78,13 @@ The user's topic of interest is:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
numberOfQuestions = prompt("How many questions? (e.g. 5, not 'five')", "5");
|
||||||
|
|
||||||
|
if (isNaN(parseInt(numberOfQuestions)) || numberOfQuestions <= 0) {
|
||||||
|
toast.error("Please enter a valid number of questions.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await toast.promise(
|
await toast.promise(
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
import { colseModal, ShowSeconds } from "./IdleScreen/logic/TimeAndTableData.svelte.js";
|
import { colseModal, ShowSeconds } from "./IdleScreen/logic/TimeAndTableData.svelte.js";
|
||||||
import EditTimetableDiv from "./IdleScreen/components/timetable/EditTimetable.svelte";
|
import EditTimetableDiv from "./IdleScreen/components/timetable/EditTimetable.svelte";
|
||||||
import { TabOpen } from "./randomname/+page.svelte";
|
import { TabOpen } from "./randomname/+page.svelte";
|
||||||
import { resetDeck } from "./flashcards/logic.svelte";
|
import { resetDeck, stats } from "./flashcards/logic.svelte";
|
||||||
import EditCards from "./flashcards/editCards.svelte";
|
import EditCards from "./flashcards/editCards.svelte";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@
|
||||||
<button class="btn dull mini">Edit Decks</button>
|
<button class="btn dull mini">Edit Decks</button>
|
||||||
</Trigger>
|
</Trigger>
|
||||||
</Modal>
|
</Modal>
|
||||||
<button class="btn dull mini" onclick={() => resetDeck}> Reset current Deck </button>
|
<button class="btn dull mini" onclick={() => (stats.isDeckEmpty = true)}> Change Deck</button>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue