diff --git a/kikikoz.css b/kikikoz.css
index 0026108..66d5779 100644
--- a/kikikoz.css
+++ b/kikikoz.css
@@ -30,11 +30,11 @@ li.dernier_arrive {
color: darkgrey;
}
-.courante {
+.active section.queue {
background-color: lightgreen;
}
-.attente {
+.attente section.queue {
background-color: pink;
}
@@ -45,3 +45,7 @@ section.queue {
display: flex;
flex-direction: column;
}
+
+.hidden {
+ display: none;
+}
diff --git a/src/main.rs b/src/main.rs
index d378527..160a812 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,69 +1,270 @@
use sycamore::prelude::*;
+use sycamore::builder::prelude::*;
use sycamore::rt::JsCast;
use rand::prelude::*;
+use rand::distributions::Alphanumeric;
-enum Queue {
+enum NomQueue {
A, B
}
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, PartialEq, Eq)]
enum ModeQueue {
Chrono,
Aléatoire
}
-fn enqueue(queue: &mut Vec, s: A, mode: ModeQueue, rng: &mut ThreadRng) {
- //
- let n = queue.len();
- let k = match mode {
- ModeQueue::Chrono => 0,
- ModeQueue::Aléatoire => {
- // let mut rng = thread_rng();
- rng.gen_range(0, n + 1)
+impl ModeQueue {
+ fn set_aléatoire(&mut self, b: bool) {
+ match b {
+ false => { *self = ModeQueue::Chrono},
+ true => { *self = ModeQueue::Aléatoire},
}
- };
- queue.insert(k, s)
+ }
+}
+
+impl std::fmt::Display for ModeQueue {
+ fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+ let s = match self {
+ ModeQueue::Chrono => "Chrono",
+ ModeQueue::Aléatoire => "Aléatoire"
+ };
+ write!(fmt, "{}", s)
+ }
+}
+
+#[derive(Clone)]
+struct ÉtatQueue<'a> {
+ nom: String,
+ mode: &'a Signal,
+ contenu: &'a Signal>,
+ nouvelleau: &'a Signal,
+ priorité: &'a Signal,
+}
+
+impl<'a> ÉtatQueue<'a> {
+ fn new<'b>(cx: BoundedScope<'a, 'b>, nom: &str) -> Self {
+ ÉtatQueue {
+ nom: nom.into(),
+ mode: create_signal(cx, ModeQueue::Aléatoire),
+ contenu: create_signal(cx, vec![]),
+ nouvelleau: create_signal(cx, "".into()),
+ priorité: create_signal(cx, 1.into()),
+ }
+ }
+
+ fn len(&self) -> usize {
+ return self.contenu.get().len()
+ }
+
+ fn enqueue(&mut self, rng: &mut ThreadRng) {
+ //
+ let s = &self.nouvelleau;
+ let n = self.len();
+ let k = match *self.mode.get() {
+ ModeQueue::Chrono => n,
+ ModeQueue::Aléatoire => {
+ rng.gen_range(0, n + 1)
+ }
+ };
+ self.contenu.modify().insert(k, s.to_string())
+ }
+
+
+
+ fn dequeue(&mut self) -> Option {
+ if self.len() > 0 {
+ Some(self.contenu.modify().remove(0))
+ } else {
+ None
+ }
+ }
+
+}
+
+#[derive(Prop)]
+struct QueueProp<'a>{
+ q: ÉtatQueue<'a>
+}
+
+fn validate_queue<'a>(mut queue: ÉtatQueue<'a>) -> impl FnMut(web_sys::Event) + 'a {
+ move |ev: web_sys::Event| {
+ let mut rng = thread_rng();
+ let event : web_sys::KeyboardEvent = ev.unchecked_into();
+
+ if event.key_code() == 13 {
+ queue.enqueue(&mut rng);
+ queue.nouvelleau.set(String::new())
+ }
+ }
+}
+
+// #[component]
+// fn Queue<'a, G: Html>(cx: Scope<'a>, queue: QueueProp<'a>) -> View {
+// let queue_courante = use_context::>(cx);
+
+// }
+
+
+#[component]
+fn ConfigQueue<'a, G: Html>(cx: Scope<'a>, queue: QueueProp<'a>) -> View {
+ let prio_str = create_signal(cx, String::new());
+ let est_aléatoire = create_signal(cx, true); //*queue.q.mode.get() == ModeQueue::Aléatoire);
+ let nom = queue.q.nom;
+ let suffix = rand::thread_rng()
+ .sample_iter(&Alphanumeric)
+ .take(15)
+ .map(char::from)
+ .collect::();
+ create_effect(cx, ||
+ if let Ok(p) = prio_str.get().parse::() {
+ queue.q.priorité.set(p)
+ });
+ create_effect(cx, || prio_str.set(format!("{}", queue.q.priorité.get())));
+
+ create_effect(cx, ||
+ queue.q.mode.modify().set_aléatoire(*est_aléatoire.get()));
+ create_effect(cx, || est_aléatoire.set(*queue.q.mode.get() == ModeQueue::Aléatoire));
+
+ section()
+ .c(h3().dyn_t(move || nom.clone()))
+ .c(input()
+ .attr("type", "checkbox")
+ .dyn_attr("id", { let suffix = suffix.clone();
+ move || Some(format!("mode_queue_{}", &suffix.clone()))
+ })
+ .bind_checked(est_aléatoire)
+ )
+ .c(label()
+ .dyn_attr("for", {
+ let suffix = suffix.clone();
+ move || Some(format!("mode_queue_{}", &suffix.clone()))
+ })
+ .t("Entrée aléatoire")
+ )
+ .c(br())
+ .c(input()
+ .dyn_attr("id", { let suffix = suffix.clone();
+ move || Some(format!("prio_queue_{}", &suffix.clone()))
+ })
+ .attr("type", "range")
+ .attr("min", "1")
+ .attr("max", "7")
+ .bind_value(prio_str)
+ )
+ .c(
+ label()
+ .dyn_attr("for", { let suffix = suffix.clone();
+ move || Some(format!("prio_queue_{}", &suffix.clone()))
+ })
+ .dyn_t(|| format!("Priorité: {}", queue.q.priorité.get()))
+ )
+ .view(cx)
+}
+
+
+#[component]
+fn Queue<'a, G: Html>(cx: Scope<'a>, queue: QueueProp<'a>) -> View {
+ let ok_queue = validate_queue(queue.q.clone());
+ view! { cx,
+ div {
+ section(class="queue") {
+ h3 {(queue.q.nom)}
+ input(type="text", bind:value = queue.q.nouvelleau, on:keypress=ok_queue) {}
+ ul {
+ Keyed {
+ iterable: queue.q.contenu,
+ view: |cx, item: String| view! {cx, li { (item) }},
+ key: |x| x.clone()
+ }
+ }
+ }
+ }
+ }
}
fn main() {
sycamore::render(|cx| {
- let prochainə = create_signal(cx, String::from("Camille"));
- let queue_A = create_signal(cx, vec![]);
- let nouvelleau_queue_A = create_signal(cx, "".into());
- let mode_queue_A = create_signal(cx, ModeQueue::Aléatoire);
- let mut do_enqueue = |_queue| {
- let mut rng = thread_rng();
- let val: std::rc::Rc = nouvelleau_queue_A.get();
- enqueue(&mut queue_A.modify(), String::from(val.as_str()), *mode_queue_A.get(), &mut rng)
+ let prochainə = create_signal(cx, String::from("personne encore"));
+ let conf_visible = create_signal(cx, false);
+ let queue_A = ÉtatQueue::new(cx, "Gauche");
+ let queue_B = ÉtatQueue::new(cx, "Droite");
+ let queue_courante = create_signal(cx, NomQueue::A);
+ provide_context_ref(cx, queue_courante);
+ let next = {
+ let mut my_queue_A = queue_A.clone();
+ let mut my_queue_B = queue_B.clone();
+ move |_ev| {
+ let (queue, next) = match *queue_courante.get() {
+ NomQueue::A => (&mut my_queue_A, NomQueue::B),
+ NomQueue::B => (&mut my_queue_B, NomQueue::A)
+ };
+ match queue.dequeue() {
+ Some(p) => prochainə.set(p),
+ None => ()
+ }
+ queue_courante.set(next);
+ }
+
};
+
+ let queue_A_pour_aff = queue_A.clone();
+ let queue_A_pour_conf = queue_A.clone();
+ let queue_B_pour_aff = queue_B.clone();
+ let queue_B_pour_conf = queue_B.clone();
+
+
view! { cx,
main {
h1 { "Kikikoz" }
- p(class="orateurice") { (prochainə.get()) }
+ p(class="orateurice") {
+ "On écoute " (prochainə.get()) "."
+ br {}
+ button(on:click=next) { "Suivantə" }
+ }
section(id="les_queues") {
- section(id="queue_A", class="queue") {
- "Queue A"
- input(type="text", bind:value=nouvelleau_queue_A, on:keypress=move |ev: web_sys::Event| {
- let event : web_sys::KeyboardEvent = ev.unchecked_into();
-
- if event.key_code() == 13 {
- do_enqueue(Queue::A);
- nouvelleau_queue_A.set(String::new())
- }
- })
- ul {
- Indexed {
- iterable: &queue_A,
- view: |cx, item: String| view! {cx,
- li { (item) }
- },
- }
- }
+ div(class=(match *queue_courante.get(){NomQueue::A=> "active", NomQueue::B=>"attente"})) {
+ Queue {
+ q: queue_A_pour_aff
+ }
+ }
+
+ div(class=(match *queue_courante.get(){NomQueue::B=>"active", NomQueue::A=>"attente"})) {
+ Queue {
+ q: queue_B_pour_aff
+ }
}
- section(id="queue_B", class="queue") { "Queue B" }
}
}
-
+ aside {
+ button(on:click=|_| conf_visible.set(! *conf_visible.get())) {
+ (
+ if *conf_visible.get() {
+ "cacher"
+ } else {
+ "configuration"
+ }
+ )
+ }
+
+ div(class=if *conf_visible.get() { "visible" } else { "hidden" }) {
+ h2 { "Configuration" }
+ ConfigQueue {
+ q: queue_A_pour_conf
+ }
+ ConfigQueue {
+ q: queue_B_pour_conf
+ }
+ // section {
+ // h3 { "Queue B" }
+ // input(type="checkbox", id="mélanger_queue_B") {}
+ // label(for="enable_queue_B") {"Randomiser"}
+ // br {}
+ // input(type="range", id="prio_queue_B", min="1", max="7", bind:value=queue_B.priorité) {}
+ // label(for="prio_queue_B") {"Priorité "} // (queue_B.priorité.get())}
+ // }
+ }
+ }
}
});
}