From 0bb6229b94c0de1298eccdc93ddc9d93ab8a6323 Mon Sep 17 00:00:00 2001
From: Marc-Antoine Manningham <marc-antoine.m@outlook.com>
Date: Fri, 22 Nov 2024 17:23:58 -0500
Subject: [PATCH] feat: new README

---
 README.md                             | 65 ++++++++++++++++---
 aep-schedule-website/Cargo.toml       |  8 +--
 combinatoric-solver/Cargo.lock        |  7 ---
 combinatoric-solver/Cargo.toml        |  6 --
 combinatoric-solver/README.md         | 26 --------
 combinatoric-solver/src/collection.rs | 60 ------------------
 combinatoric-solver/src/item.rs       |  6 --
 combinatoric-solver/src/lib.rs        |  7 ---
 combinatoric-solver/src/parameters.rs |  8 ---
 combinatoric-solver/src/score.rs      |  1 -
 combinatoric-solver/src/solver.rs     | 89 ---------------------------
 flake.lock                            | 12 ++--
 12 files changed, 65 insertions(+), 230 deletions(-)
 delete mode 100644 combinatoric-solver/Cargo.lock
 delete mode 100644 combinatoric-solver/Cargo.toml
 delete mode 100644 combinatoric-solver/README.md
 delete mode 100644 combinatoric-solver/src/collection.rs
 delete mode 100644 combinatoric-solver/src/item.rs
 delete mode 100644 combinatoric-solver/src/lib.rs
 delete mode 100644 combinatoric-solver/src/parameters.rs
 delete mode 100644 combinatoric-solver/src/score.rs
 delete mode 100644 combinatoric-solver/src/solver.rs

diff --git a/README.md b/README.md
index 7fab878..86370f0 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,62 @@
-# Aep Schedule Generator Rusty
+# Générateur d'horaire de l'AEP v2
 
-**Disclaimer** This is not yet the official AEP schedule.
+## 🛠️ Objectif du projet
 
-## The Stack
-The stack is LAC (Leptos + Axum + CSV)
+Le Générateur d'horaire de l'AEP v2 est une refonte complète du générateur d'horaire étudiant, conçu pour être rapide, flexible et accessible. Ce projet modernise une base de code vieille de 15 ans et optimise l'expérience utilisateur en adoptant des technologies modernes.
 
+## ❓ FAQ
 
-Leptos is a great frontend framework in Rust with web assembly to make a responsive UI. Axum is the fast backend serving the HTTP in Rust. The storage is done with CSV, but that's only because Poly give us CSV to represent all the courses.
+### Pourquoi une refonte complète ?
 
-## Programming Languages used to make this
-- Rust
+L'ancien générateur, en maintenance depuis plus de 15 ans, était obsolète avec une base de code mêlant 5 langages différents. Une refonte était essentielle pour garantir la maintenabilité et améliorer les performances.
 
-## Credit
-Marc-Antoine Manningham for the backend and the frontend
+### Comment est-il aussi rapide ?
 
-Raphael Salvas, Achille Saint-Hillier, Sunnee Chevalier and Gabriel Billard have made a figma that's the inspiration for the style
\ No newline at end of file
+- **Traitement local** : Les horaires sont générés directement dans le navigateur via WebAssembly, éliminant les délais liés aux serveurs.
+- **Optimisation intelligente** : Seuls les meilleurs horaires sont calculés, grâce à des algorithmes comme le *branch and bound* pour réduire l'espace de recherche et respecter les contraintes définies.
+
+### Où puis-je soumettre des suggestions ou rapports de bugs ?
+
+- Utilisez le bouton **Signaler un bug** pour soumettre vos idées ou signaler un problème.
+- Contributions bienvenues ! Rejoignez-nous si vous avez des compétences en Rust.
+
+## 👥 Crédits
+
+- **Développement** : Marc-Antoine Manningham (front-end & back-end)
+- **Design** : Raphael Salvas, Achille Saint-Hillier, Sunnee Chevalier et Gabriel Billard, inspirés par leur maquette Figma.
+
+
+Voici une version mise à jour du README, incluant des instructions pour l'auto-hébergement avec Docker :
+
+## ⚙️ Auto-hébergement avec Docker
+
+### Prérequis
+
+1. **Docker** : Assurez-vous que Docker est installé. [Installation Docker](https://docs.docker.com/get-docker/)
+2. **Docker Compose** : (optionnel, selon votre configuration).
+
+### Instructions
+
+1. **Téléchargez et exécutez l'image Docker** :
+   ```bash
+   docker pull git.step.polymtl.ca/Lemark/aep-schedule-generator:latest
+   docker run -d -p 8080:8080 --name aep-schedule-generator git.step.polymtl.ca/Lemark/aep-schedule-generator:latest
+   ```
+
+2. **Accédez à l'application** :
+   Ouvrez votre navigateur à l'adresse [http://localhost:8080](http://localhost:8080).
+
+3. **Configurer avec Docker Compose** (facultatif) :
+   Créez un fichier `docker-compose.yml` :
+   ```yaml
+   version: '3'
+   services:
+     aep-schedule-generator:
+       image: git.step.polymtl.ca/Lemark/aep-schedule-generator:latest
+       ports:
+         - "8080:8080"
+   ```
+   Lancez les services :
+   ```bash
+   docker-compose up -d
+   ```
diff --git a/aep-schedule-website/Cargo.toml b/aep-schedule-website/Cargo.toml
index 57f1e94..9c2731f 100644
--- a/aep-schedule-website/Cargo.toml
+++ b/aep-schedule-website/Cargo.toml
@@ -11,10 +11,10 @@ axum = { version = "0.7", optional = true, features = ["macros"] }
 console_error_panic_hook = "0.1"
 console_log = "1"
 cfg-if = "1"
-leptos = { version = "0.6", features = ["nightly"] }
-leptos_axum = { version = "0.6", optional = true }
-leptos_meta = { version = "0.6", features = ["nightly"] }
-leptos_router = { version = "0.6", features = ["nightly"] }
+leptos = { version = "0.7.0-rc0", features = ["nightly"] }
+leptos_axum = { version = "0.7.0-rc0", optional = true }
+leptos_meta = { version = "0.7.0-rc0", features = ["nightly"] }
+leptos_router = { version = "0.7.0-rc0", features = ["nightly"] }
 log = "0.4"
 rand = { version = "0.8", optional = true }
 simple_logger = "5"
diff --git a/combinatoric-solver/Cargo.lock b/combinatoric-solver/Cargo.lock
deleted file mode 100644
index d5d26d1..0000000
--- a/combinatoric-solver/Cargo.lock
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "combinatoric-solver"
-version = "0.1.0"
diff --git a/combinatoric-solver/Cargo.toml b/combinatoric-solver/Cargo.toml
deleted file mode 100644
index cd0e860..0000000
--- a/combinatoric-solver/Cargo.toml
+++ /dev/null
@@ -1,6 +0,0 @@
-[package]
-name = "combinatoric-solver"
-version = "0.1.0"
-edition = "2021"
-
-[dependencies]
diff --git a/combinatoric-solver/README.md b/combinatoric-solver/README.md
deleted file mode 100644
index 4da455b..0000000
--- a/combinatoric-solver/README.md
+++ /dev/null
@@ -1,26 +0,0 @@
-## Purpose
-
-This crate is a purely generic combinatoric solver.
-
-It allows to solve the problem of having n items to choose each with multiple variants and choosing the best combination of variants.
-
-A more pratical example is the original reason for writing this solver: given a list of university course that needs to be taken with multiple groups what is the top combination of group to maximise the number of day off and hours during the morning.
-
-## Limitation
-
-The algorithm explores all of the solution space for the number of combination even if it efficiently cut bad solutions. The problem is still NP-hard, so a combinatorial explosion can still happen with weak bounds and a large solution space.
-
-## Assumptions
-
-It function on the following assumptions:
-
-- Adding an item to the collection of item can only worsen or keep the score the same. In other words, the score function must be monotonic and decreasing.
-- An invalid combination can't become valid when adding the next variant.
-- The item object is really expensive to clone at lot of time, so a variant representation which is cheap to clone is used to iterate.
-- Only the top N combinations are interesting.
-
-## How it works
-
-- It iterate recursively on all variants until it has a variant for each item.
-- If an incomplete collection doesn't respect the constraint the rest of combination will not be explored.
-- If an incomplete collection have a worst score than the worst of the best n collection, the rest of the combination of this collection will not be explored. (Branch and bound)
diff --git a/combinatoric-solver/src/collection.rs b/combinatoric-solver/src/collection.rs
deleted file mode 100644
index 831e7a8..0000000
--- a/combinatoric-solver/src/collection.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-use crate::{item::ItemVariant, score::Score};
-
-#[derive(Clone)]
-pub struct Collection<const MAX_ITEMS: usize, S, V>
-where
-    S: Score,
-    V: ItemVariant,
-{
-    score: S,
-    item_variant: [V; MAX_ITEMS],
-}
-
-impl<const MAX_ITEMS: usize, S: Score, V: ItemVariant> Collection<MAX_ITEMS, S, V> {
-    #[inline]
-    pub fn push(&self, iteration: usize, item_variant: V) -> Self {
-        let mut new = self.clone();
-
-        new.item_variant[iteration] = item_variant;
-        new
-    }
-    #[inline]
-    pub fn item_variant(&self, iteration: usize) -> &[V] {
-        &self.item_variant[0..iteration]
-    }
-}
-
-impl<const MAX_ITEMS: usize, S: Score, V: ItemVariant> Default for Collection<MAX_ITEMS, S, V> {
-    #[inline]
-    fn default() -> Self {
-        let score = S::default();
-        let item_variant = [V::default(); MAX_ITEMS];
-        Self {
-            score,
-            item_variant,
-        }
-    }
-}
-
-impl<const MAX_ITEMS: usize, S: Score, V: ItemVariant> PartialEq for Collection<MAX_ITEMS, S, V> {
-    #[inline]
-    fn eq(&self, other: &Self) -> bool {
-        self.item_variant == other.item_variant
-    }
-}
-
-impl<const MAX_ITEMS: usize, S: Score, V: ItemVariant> PartialOrd for Collection<MAX_ITEMS, S, V> {
-    #[inline]
-    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
-        self.score.partial_cmp(&other.score)
-    }
-}
-
-impl<const MAX_ITEMS: usize, S: Score, V: ItemVariant> Eq for Collection<MAX_ITEMS, S, V> {}
-
-impl<const MAX_ITEMS: usize, S: Score, V: ItemVariant> Ord for Collection<MAX_ITEMS, S, V> {
-    #[inline]
-    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
-        self.score.cmp(&other.score)
-    }
-}
diff --git a/combinatoric-solver/src/item.rs b/combinatoric-solver/src/item.rs
deleted file mode 100644
index a37121c..0000000
--- a/combinatoric-solver/src/item.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-pub trait ItemVariant: Eq + Copy + Default {}
-
-pub trait CombinatoricItem {
-    type ItemVariant;
-    fn variants(&self) -> impl IntoIterator<Item = Self::ItemVariant>;
-}
diff --git a/combinatoric-solver/src/lib.rs b/combinatoric-solver/src/lib.rs
deleted file mode 100644
index 4d7930b..0000000
--- a/combinatoric-solver/src/lib.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-pub mod collection;
-pub mod item;
-pub mod parameters;
-pub mod score;
-pub mod solver;
-
-pub use crate::solver::Solver;
diff --git a/combinatoric-solver/src/parameters.rs b/combinatoric-solver/src/parameters.rs
deleted file mode 100644
index 2974100..0000000
--- a/combinatoric-solver/src/parameters.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-use crate::item::ItemVariant;
-
-pub trait Parameters<V>
-where
-    V: ItemVariant,
-{
-    fn is_valid(&self, previous_variants: &[V], new_variant: V) -> bool;
-}
diff --git a/combinatoric-solver/src/score.rs b/combinatoric-solver/src/score.rs
deleted file mode 100644
index 426175d..0000000
--- a/combinatoric-solver/src/score.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub trait Score: Ord + Default + Clone {}
diff --git a/combinatoric-solver/src/solver.rs b/combinatoric-solver/src/solver.rs
deleted file mode 100644
index a8f47fa..0000000
--- a/combinatoric-solver/src/solver.rs
+++ /dev/null
@@ -1,89 +0,0 @@
-use std::{cmp::Reverse, collections::BinaryHeap, num::NonZeroUsize};
-
-use crate::{
-    collection::Collection,
-    item::{CombinatoricItem, ItemVariant},
-    parameters::Parameters,
-    score::Score,
-};
-
-pub struct Solver<const MAX_ITEMS: usize, S, V, I, Parameters>
-where
-    S: Score,
-    V: ItemVariant,
-    I: CombinatoricItem,
-{
-    /// Min-heap to keep the best schedules and fetch the worst of the best in O(1)
-    top_items: BinaryHeap<Reverse<Collection<MAX_ITEMS, S, V>>>,
-    max_capacity: NonZeroUsize,
-    parameters: Parameters,
-    items: Vec<I>,
-}
-
-impl<'a, const MAX_ITEMS: usize, S, V, I, P> Solver<MAX_ITEMS, S, V, I, P>
-where
-    S: Score,
-    V: ItemVariant,
-    I: CombinatoricItem<ItemVariant = V>,
-    P: Parameters<V>,
-{
-    pub fn new(max_capacity: NonZeroUsize, items: Vec<I>, parameters: P) -> Self {
-        let top_items = BinaryHeap::with_capacity(max_capacity.into());
-        Self {
-            top_items,
-            max_capacity,
-            parameters,
-            items,
-        }
-    }
-    pub fn solve(mut self) -> Vec<I> {
-        let item = &self.items;
-        Self::rec_iter(
-            0,
-            Collection::default(),
-            self.max_capacity,
-            &self.parameters,
-            item,
-            &mut self.top_items,
-        );
-        vec![]
-    }
-    fn rec_iter(
-        i: usize,
-        collection: Collection<MAX_ITEMS, S, V>,
-        max_capacity: NonZeroUsize,
-        parameters: &P,
-        items: &'a [I],
-        top_items: &mut BinaryHeap<Reverse<Collection<MAX_ITEMS, S, V>>>,
-    ) {
-        if i >= items.len() {
-            // If it reach this branch it is already valid and better than the worst top schedule, so we can push
-            if top_items.len() >= max_capacity.into() {
-                top_items.pop();
-            }
-            top_items.push(Reverse(collection));
-            return;
-        }
-
-        for variant in items[i].variants() {
-            if !parameters.is_valid(collection.item_variant(i), variant) {
-                return;
-            }
-            let collections = collection.push(i, variant);
-            // SAFETY: if the len is greater than the max_capacity, it is greater than 0 enforced by the NonZeroUsize, which allows us to unwrap without checking if it is None
-            if top_items.len() >= max_capacity.into()
-                && unsafe { top_items.peek().unwrap_unchecked().0 >= collections }
-            {
-                return;
-            }
-            Self::rec_iter(
-                i + 1,
-                collections,
-                max_capacity,
-                parameters,
-                items,
-                top_items,
-            );
-        }
-    }
-}
diff --git a/flake.lock b/flake.lock
index 26bce65..c662d3b 100644
--- a/flake.lock
+++ b/flake.lock
@@ -2,11 +2,11 @@
   "nodes": {
     "nixpkgs": {
       "locked": {
-        "lastModified": 1716137900,
-        "narHash": "sha256-sowPU+tLQv8GlqtVtsXioTKeaQvlMz/pefcdwg8MvfM=",
+        "lastModified": 1729880355,
+        "narHash": "sha256-RP+OQ6koQQLX5nw0NmcDrzvGL8HDLnyXt/jHhL1jwjM=",
         "owner": "nixos",
         "repo": "nixpkgs",
-        "rev": "6c0b7a92c30122196a761b440ac0d46d3d9954f1",
+        "rev": "18536bf04cd71abd345f9579158841376fdd0c5a",
         "type": "github"
       },
       "original": {
@@ -42,11 +42,11 @@
         "systems": "systems"
       },
       "locked": {
-        "lastModified": 1710146030,
-        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
+        "lastModified": 1726560853,
+        "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
         "owner": "numtide",
         "repo": "flake-utils",
-        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
+        "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
         "type": "github"
       },
       "original": {
-- 
GitLab