Compare commits
No commits in common. "7a847905d773d67bbb92cf09b24da6baec3e7cd7" and "fe7f626c01444a8a0db2e4d400f4a6a09e816b39" have entirely different histories.
7a847905d7
...
fe7f626c01
102
src/main.rs
102
src/main.rs
|
@ -7,8 +7,8 @@ use dioxus::desktop::{Config, LogicalSize, WindowBuilder};
|
||||||
use dioxus::{logger::tracing, prelude::*};
|
use dioxus::{logger::tracing, prelude::*};
|
||||||
#[cfg(feature = "bundled")]
|
#[cfg(feature = "bundled")]
|
||||||
use include_dir::{Dir, include_dir};
|
use include_dir::{Dir, include_dir};
|
||||||
use models::{Phase, Question, QuestionState, Questions};
|
use models::{Question, Questions};
|
||||||
use rand::{rngs::ThreadRng, seq::SliceRandom};
|
use rand::seq::SliceRandom;
|
||||||
#[cfg(feature = "desktop")]
|
#[cfg(feature = "desktop")]
|
||||||
use std::{env, fs};
|
use std::{env, fs};
|
||||||
#[cfg(not(feature = "web"))]
|
#[cfg(not(feature = "web"))]
|
||||||
|
@ -78,25 +78,21 @@ fn get_questions() -> Questions {
|
||||||
.clone()
|
.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_rand_questions() -> Questions {
|
fn get_rand_questions() -> Vec<Question> {
|
||||||
let mut questions = get_questions();
|
let mut questions = get_questions().questions;
|
||||||
let mut rng = rand::rng();
|
let mut rng = rand::rng();
|
||||||
|
|
||||||
// Randomize the answers
|
// Randomize the answers
|
||||||
randomize_answers(&mut rng, &mut questions);
|
questions
|
||||||
|
.iter_mut()
|
||||||
|
.for_each(|q| q.answers.shuffle(&mut rng));
|
||||||
|
|
||||||
// Randomize the questions list
|
// Randomize the questions list
|
||||||
questions.shuffle(&mut rng);
|
questions.shuffle(&mut rng);
|
||||||
|
|
||||||
questions.count = questions.questions.len();
|
|
||||||
|
|
||||||
questions
|
questions
|
||||||
}
|
}
|
||||||
|
|
||||||
fn randomize_answers(rng: &mut ThreadRng, questions: &mut [Question]) {
|
|
||||||
questions.iter_mut().for_each(|q| q.answers.shuffle(rng));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
#[cfg(feature = "desktop")]
|
#[cfg(feature = "desktop")]
|
||||||
{
|
{
|
||||||
|
@ -126,60 +122,41 @@ fn App() -> Element {
|
||||||
let mut correct_questions = use_signal(|| 0);
|
let mut correct_questions = use_signal(|| 0);
|
||||||
let mut wrong_questions = use_signal(|| 0);
|
let mut wrong_questions = use_signal(|| 0);
|
||||||
|
|
||||||
let mut phase = use_signal(|| Phase::Running);
|
let mut has_finished = use_signal(|| false);
|
||||||
let mut next_phase = use_signal(|| Phase::Running);
|
let mut has_restart = use_signal(|| false);
|
||||||
|
|
||||||
use_effect(move || {
|
use_effect(move || {
|
||||||
let current_phase = phase();
|
let has_restart = has_restart();
|
||||||
match current_phase {
|
if has_restart {
|
||||||
Phase::Restart => {
|
let mut questions_lock = questions.write();
|
||||||
let mut questions_lock = questions.write();
|
|
||||||
|
|
||||||
*questions_lock = get_rand_questions();
|
*questions_lock = get_rand_questions();
|
||||||
|
|
||||||
correct_questions.set(0);
|
correct_questions.set(0);
|
||||||
wrong_questions.set(0);
|
wrong_questions.set(0);
|
||||||
|
|
||||||
next_phase.set(Phase::Running);
|
has_finished.set(false);
|
||||||
}
|
|
||||||
Phase::RestartWrongs => {
|
|
||||||
let mut questions_lock = questions.write();
|
|
||||||
|
|
||||||
let wrongs = questions_lock.wrong_questions.to_vec();
|
|
||||||
|
|
||||||
questions_lock.count = wrongs.len();
|
|
||||||
questions_lock.questions = wrongs;
|
|
||||||
questions_lock.wrong_questions.clear();
|
|
||||||
|
|
||||||
let mut rng = rand::rng();
|
|
||||||
randomize_answers(&mut rng, &mut questions_lock);
|
|
||||||
|
|
||||||
correct_questions.set(0);
|
|
||||||
wrong_questions.set(0);
|
|
||||||
|
|
||||||
next_phase.set(Phase::Running);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// I am not a fan of this..._reactivity_
|
|
||||||
use_effect(move || {
|
use_effect(move || {
|
||||||
let next_phase = next_phase();
|
let has_finished = has_finished();
|
||||||
phase.set(next_phase);
|
if !has_finished {
|
||||||
|
has_restart.set(false);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
rsx! {
|
rsx! {
|
||||||
document::Link { rel: "stylesheet", href: MAIN_CSS }
|
document::Link { rel: "stylesheet", href: MAIN_CSS }
|
||||||
if phase() == Phase::Running {
|
if !has_finished() {
|
||||||
QuestionForm { questions, correct_questions, wrong_questions, phase }
|
QuestionForm { questions, correct_questions, wrong_questions, has_finished, has_restart }
|
||||||
}
|
}
|
||||||
else if phase() != Phase::Running {
|
else if has_finished() {
|
||||||
Report {
|
Report {
|
||||||
questions: questions(),
|
questions: questions(),
|
||||||
correct_questions: correct_questions(),
|
correct_questions: correct_questions(),
|
||||||
wrong_questions: wrong_questions(),
|
wrong_questions: wrong_questions(),
|
||||||
phase,
|
has_restart,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,12 +165,13 @@ fn App() -> Element {
|
||||||
#[allow(clippy::redundant_closure)]
|
#[allow(clippy::redundant_closure)]
|
||||||
#[component]
|
#[component]
|
||||||
pub fn QuestionForm(
|
pub fn QuestionForm(
|
||||||
questions: Signal<Questions>,
|
questions: Signal<Vec<Question>>,
|
||||||
correct_questions: Signal<i32>,
|
correct_questions: Signal<i32>,
|
||||||
wrong_questions: Signal<i32>,
|
wrong_questions: Signal<i32>,
|
||||||
phase: Signal<Phase>,
|
has_finished: Signal<bool>,
|
||||||
|
has_restart: Signal<bool>,
|
||||||
) -> Element {
|
) -> Element {
|
||||||
let mut current = use_signal(move || Question::default());
|
let mut current = use_signal(move || questions()[0].clone());
|
||||||
|
|
||||||
use_effect(move || {
|
use_effect(move || {
|
||||||
let _correct_count = correct_questions();
|
let _correct_count = correct_questions();
|
||||||
|
@ -202,7 +180,7 @@ pub fn QuestionForm(
|
||||||
let mut questions_lock = questions.write();
|
let mut questions_lock = questions.write();
|
||||||
|
|
||||||
if questions_lock.is_empty() {
|
if questions_lock.is_empty() {
|
||||||
phase.set(Phase::Finished);
|
has_finished.set(true);
|
||||||
} else {
|
} else {
|
||||||
let new_question = questions_lock.remove(0);
|
let new_question = questions_lock.remove(0);
|
||||||
current.set(new_question);
|
current.set(new_question);
|
||||||
|
@ -245,7 +223,6 @@ pub fn QuestionForm(
|
||||||
sleep(Duration::from_millis(600)).await;
|
sleep(Duration::from_millis(600)).await;
|
||||||
|
|
||||||
let mut current_lock = current.write();
|
let mut current_lock = current.write();
|
||||||
let mut questions_lock = questions.write();
|
|
||||||
let mut correct_questions_lock = correct_questions.write();
|
let mut correct_questions_lock = correct_questions.write();
|
||||||
let mut wrong_questions_lock = wrong_questions.write();
|
let mut wrong_questions_lock = wrong_questions.write();
|
||||||
|
|
||||||
|
@ -260,8 +237,6 @@ pub fn QuestionForm(
|
||||||
*correct_questions_lock += 1;
|
*correct_questions_lock += 1;
|
||||||
} else if is_wrong {
|
} else if is_wrong {
|
||||||
*wrong_questions_lock += 1;
|
*wrong_questions_lock += 1;
|
||||||
let current_question = current_lock.clone();
|
|
||||||
questions_lock.wrong_questions.push(current_question);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset animation flags
|
// Reset animation flags
|
||||||
|
@ -378,11 +353,11 @@ pub fn Result(is_correct: bool, is_wrong: bool) -> Element {
|
||||||
#[allow(clippy::redundant_closure)]
|
#[allow(clippy::redundant_closure)]
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Info(
|
pub fn Info(
|
||||||
questions: Signal<Questions>,
|
questions: Signal<Vec<Question>>,
|
||||||
correct_questions: Signal<i32>,
|
correct_questions: Signal<i32>,
|
||||||
wrong_questions: Signal<i32>,
|
wrong_questions: Signal<i32>,
|
||||||
) -> Element {
|
) -> Element {
|
||||||
let total_questions = questions().count;
|
let total_questions = get_questions().len();
|
||||||
let current_question = use_memo(move || questions().len());
|
let current_question = use_memo(move || questions().len());
|
||||||
let left_questions = use_memo(move || total_questions - current_question());
|
let left_questions = use_memo(move || total_questions - current_question());
|
||||||
|
|
||||||
|
@ -406,10 +381,10 @@ pub fn Info(
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Report(
|
pub fn Report(
|
||||||
questions: Questions,
|
questions: Vec<Question>,
|
||||||
correct_questions: i32,
|
correct_questions: i32,
|
||||||
wrong_questions: i32,
|
wrong_questions: i32,
|
||||||
phase: Signal<Phase>,
|
has_restart: Signal<bool>,
|
||||||
) -> Element {
|
) -> Element {
|
||||||
let questions_size = questions.len();
|
let questions_size = questions.len();
|
||||||
|
|
||||||
|
@ -429,17 +404,12 @@ pub fn Report(
|
||||||
div {
|
div {
|
||||||
button {
|
button {
|
||||||
onclick: move |_| {
|
onclick: move |_| {
|
||||||
phase.set(Phase::Restart);
|
has_restart.set(true);
|
||||||
},
|
},
|
||||||
"Restart"
|
"Restart"
|
||||||
},
|
},
|
||||||
if wrong_questions > 0 {
|
button {
|
||||||
button {
|
"Restart with only wrong questions"
|
||||||
onclick: move |_| {
|
|
||||||
phase.set(Phase::RestartWrongs);
|
|
||||||
},
|
|
||||||
"Restart with only wrong questions"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,24 +2,9 @@ use std::ops::{AddAssign, Deref, DerefMut};
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, PartialEq)]
|
#[derive(Debug, Default, Clone, Deserialize)]
|
||||||
pub enum Phase {
|
|
||||||
#[default]
|
|
||||||
Running,
|
|
||||||
Finished,
|
|
||||||
Restart,
|
|
||||||
RestartWrongs,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Deserialize)]
|
|
||||||
pub struct Questions {
|
pub struct Questions {
|
||||||
pub questions: Vec<Question>,
|
pub questions: Vec<Question>,
|
||||||
|
|
||||||
#[serde(default, skip)]
|
|
||||||
pub wrong_questions: Vec<Question>,
|
|
||||||
|
|
||||||
#[serde(default, skip)]
|
|
||||||
pub count: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddAssign for Questions {
|
impl AddAssign for Questions {
|
||||||
|
@ -42,21 +27,10 @@ impl DerefMut for Questions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
||||||
pub enum QuestionState {
|
|
||||||
#[default]
|
|
||||||
None,
|
|
||||||
Correct,
|
|
||||||
Wrong,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Deserialize)]
|
|
||||||
pub struct Question {
|
pub struct Question {
|
||||||
pub message: String,
|
pub message: String,
|
||||||
pub answers: Vec<Answer>,
|
pub answers: Vec<Answer>,
|
||||||
|
|
||||||
#[serde(default, skip)]
|
|
||||||
pub state: QuestionState,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
||||||
|
|
Loading…
Reference in New Issue