diff --git a/content/cyb/.gitkeep b/content/cyb/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/content/cyb/tp/_index.md b/content/cyb/tp/_index.md new file mode 100644 index 0000000..3d72c83 --- /dev/null +++ b/content/cyb/tp/_index.md @@ -0,0 +1,10 @@ +--- +weight: 999 +title: "TP" +description: "Tp de programmation made in B2B" +icon: "folder" +date: "2024-08-20T12:30:18+02:00" +lastmod: "2024-08-20T12:30:18+02:00" +draft: false +toc: true +--- \ No newline at end of file diff --git a/content/cyb/tp/c_basics.md b/content/cyb/tp/c_basics.md new file mode 100644 index 0000000..b92f52b --- /dev/null +++ b/content/cyb/tp/c_basics.md @@ -0,0 +1,151 @@ +--- +title: "Basic" +author: "Clément" +description: "Subjects about C language" +--- + +# Introduction + +This category shows training exercises about C language. For all questions, +please ask on the BackToBasics' [Discord server](https://discord.gg/SJGWzkU2gd). + +We cannot use the intranet, so there are somes given files. Please play the +game and do not read the test file. You can download it +[here](https://github.com/BackToBasicsEpita/CyberRef). + +A Makefile is already given with these rules: + +- `basics`: compiles ; +- `debug`: compiles with debug flags ; +- `check`: runs the testsuite ; +- `clean`: removes all trash files. + + +You are only allowed to uses the functions defined in the following headers: +- stdio.h + +All of the code must be done inside a `basics.c` file. + +Your code must compile with the following flags: +`-std=c99 -pedantic -Wall -Wextra -Werror -Wvla`. + +Your code must not segfault and have any memory leak. + +# FizzBuzz + +## Goal + +You have to implement the following function: + +```c +void fizzbuzz(int n); +``` + +This function displays on stdout the numbers from 1 to `n` with newlines. +However, it must follow the rules: + +- for multiples of 3, it should print *"Fizz"* with a newline ; +- for multiples of 5, it should print *"Buzz"* with a newline ; +- for multiples of 3 and of 5, it should print *"FizzBuzz"* with a newline. + +## Example + +The output of `fizzbuzz(5)` is: + +```bash +1 +2 +Fizz +4 +Buzz +``` + +# My strlen + +You have to implement the following function: + +```c +size_t my_strlen(char *s); +``` + +This functions returns the length of the string argument. The string can be +null, and its size will be 0. + +# Binary number + +You have to implement the following function: + +```c +long binary_number(char str[]); +``` + +This function returns the integer in decimal corresponding to the binary number +given in argument. If a caracter does not correspond to a binary digit, return +-1. + +## Example + +The output of `binary_number("110")` is `6`. + +The output of `binary_number("This is not correct")` is `-1`. + +# Hamming Distance DNA + +You have to implement the following function: + +```c +int hamming_distance(char *dna1, char *dna2); +``` + +This function returns the number of differents characters between the two +strings given in arguments. + +We read DNA using the letters C,A,G and T. If there is another caracter than +the previous one, return -1. Moreover, if the size of the two parameters are +not equal, return -1. + +## Example + +The output of `hamming_distance("CAGT", "GAGT")` is `1`. + +# Isogram + +You have to implement the follwing function: + +```c +int is_isogram(char *s); +``` + +This function returns if the given string is an isogram. An isogram word or +sentence is a word or a phrase without a repetiting letter, however spaces and +non letter caracters are allowed to appear multiple times. + +## Example + +`House` is an isogram word, but `Test.` is not. + +# Move Robot + +You have to implement the following function: + +```c +struct pair move_robot(struct pair current, char *directions); +``` + +Moreover, you have to implement the `pair` structure with two integer: `x` and +`y`. + +This function moves a robot in the current coordinates on a grid from a string +of directions and returns the new coordinates of the robot. + +The string of directions corresponds to a string of operations done on the +robot: + +- `U` for up ; +- `L` for left ; +- `D` for down ; +- `R` for right. + +## Example + +The output of `move_robot({1, 1}, "UL")` is the structure pair `{0, 2}`. diff --git a/content/sup/maths/espaces_vectoriels/_index.md b/content/sup/maths/espaces_vectoriels/_index.md new file mode 100644 index 0000000..179f3ec --- /dev/null +++ b/content/sup/maths/espaces_vectoriels/_index.md @@ -0,0 +1,11 @@ +--- +weight: 999 +title: "Espaces Vectoriels" +description: "Cours & redif sur les espaces vectoriels" +icon: "folder" +date: "2024-08-27" +lastmod: "2023-08-26T20:43:23+01:00" +draft: false +toc: true +katex: false +--- diff --git a/content/sup/maths/espaces-vectoriels-video.md b/content/sup/maths/espaces_vectoriels/espaces-vectoriels-video.md similarity index 100% rename from content/sup/maths/espaces-vectoriels-video.md rename to content/sup/maths/espaces_vectoriels/espaces-vectoriels-video.md diff --git a/content/sup/maths/espaces-vectoriels.md b/content/sup/maths/espaces_vectoriels/espaces-vectoriels.md similarity index 75% rename from content/sup/maths/espaces-vectoriels.md rename to content/sup/maths/espaces_vectoriels/espaces-vectoriels.md index 9373caa..427ecb8 100644 --- a/content/sup/maths/espaces-vectoriels.md +++ b/content/sup/maths/espaces_vectoriels/espaces-vectoriels.md @@ -10,4 +10,4 @@ toc: true katex: true --- -Ceci est du markdown \ No newline at end of file +Il faut imaginer très fort que c'est un court sur les espaces vectoriels \ No newline at end of file diff --git a/content/sup/maths/moodle.md b/content/sup/moodle.md similarity index 72% rename from content/sup/maths/moodle.md rename to content/sup/moodle.md index d0380cb..867e043 100644 --- a/content/sup/maths/moodle.md +++ b/content/sup/moodle.md @@ -7,6 +7,6 @@ date: "2023-08-26T20:43:23+01:00" lastmod: "2023-08-26T20:43:23+01:00" draft: false -ressource: "https://moodle.cri.epita.fr/course/view.php?id=1491" +ressource: "https://moodle.epita.fr/mod/forum/view.php?id=27403" --- diff --git a/content/sup/tp/S1/_index.md b/content/sup/tp/S1/_index.md new file mode 100644 index 0000000..8e92fe0 --- /dev/null +++ b/content/sup/tp/S1/_index.md @@ -0,0 +1,10 @@ +--- +weight: 999 +title: "S1" +icon: "folder" +date: "2024-08-27" +lastmod: "2023-08-26T20:43:23+01:00" +draft: false +toc: true +katex: false +--- diff --git a/content/sup/tp/S1/arrays.md b/content/sup/tp/S1/arrays.md new file mode 100644 index 0000000..4449ffa --- /dev/null +++ b/content/sup/tp/S1/arrays.md @@ -0,0 +1,87 @@ +--- +title: "Tableaux" +date: 2023-06-18T00:00:00+02:00 +author: "Kolowy" +description: "Entrainements sur les tableaux de tableaux en C#" +--- +# Introduction + +Ce TP est un sujet d'entrainement pour les tableaux de tableaux en C#. + +Si vous avez le mondre probleme n'hésitez pas à aller sur le serveur de l'asso et poser vos questions ou à envoyer un MP à `kolowy_` sur discord + +# Code à compléter + +``` + +/// +/// Calcule la somme de deux tableaux de tableaux d'entiers. +/// +/// Le premier tableau de tableaux. +/// Le deuxième tableau de tableaux. +/// Le tableau de tableaux contenant la somme des éléments correspondants. +/// Il y a une exceptions a gérer dans cette fonction : +/// - Les tableaux de tableaux doivent avoir la même taille +static int[][] SumOfTwoArraysOfArrays(int[][] arrays1, int[][] arrays2) +{ + // TODO + throw new NotImplementedException(); +} + +/// +/// Affiche les éléments d'un tableau de tableaux. +/// +/// Le tableau de tableaux à afficher. +static void DisplayArrays(int[][] array) +{ + // TODO + throw new NotImplementedException(); +} + +static void Main() +{ + int[][] arrays1 = new int[][] + { + new int[] { 1, 2, 3 }, + new int[] { 4, 5, 6 }, + new int[] { 7, 8, 9 } + }; + + int[][] arrays2 = new int[][] + { + new int[] { 10, 11, 12 }, + new int[] { 13, 14, 15 }, + new int[] { 16, 17, 18 } + }; + + int[][] sumArrays = SumOfTwoArraysOfArrays(arrays1, arrays2); + + Console.WriteLine("Tableaux 1 :"); + DisplayArrays(arrays1); + + Console.WriteLine("Tableaux 2 :"); + DisplayArrays(arrays2); + + Console.WriteLine("Somme des tableaux :"); + DisplayArrays(sumArrays); +} + +Main(); +``` + + +Résultat attendu : +``` +Tableaux 1 : +1 2 3 +4 5 6 +7 8 9 +Tableaux 2 : +10 11 12 +13 14 15 +16 17 18 +Somme des tableaux : +11 13 15 +17 19 21 +23 25 27 +``` diff --git a/content/sup/tp/S1/classes_interfaces.md b/content/sup/tp/S1/classes_interfaces.md new file mode 100644 index 0000000..654a7f0 --- /dev/null +++ b/content/sup/tp/S1/classes_interfaces.md @@ -0,0 +1,251 @@ +--- +title: "Classes, Héritage et Interfaces" +date: 2023-06-18T00:00:00+02:00 +author: "Ilan Mayeux" +description: "Un court TP pour pratiquer les classes, l'héritage et les interfaces pour les rattrapages S1" +--- + +Bienvenue sur cet entraînement pour les rattrapages S1 sur les classes, l'héritage et les interfaces. + +Si vous avez le moindre problème n'hésitez pas à aller sur le serveur de l'asso et poser vos questions ou à envoyer un MP à `taliayaka` sur discord + +Avant de commencer, prenez le temps de relire la documentation sur : +- [Les classes](https://docs.microsoft.com/fr-fr/dotnet/csharp/programming-guide/classes-and-structs/classes) +- [L'héritage](https://docs.microsoft.com/fr-fr/dotnet/csharp/programming-guide/classes-and-structs/inheritance) +- [Les interfaces](https://docs.microsoft.com/fr-fr/dotnet/csharp/programming-guide/interfaces/) + +Pour ce TP, vous aurez besoin de créer un nouveau projet console. Pour cela, ouvrez Visual Studio ou Rider et cliquez sur `Créer un nouveau projet`. Sélectionnez `Application console (.NET Core)` et cliquez sur `Suivant`. Nommez votre projet `ClassesInheritanceInterfaces` et cliquez sur `Créer`. + +### Partie 1 : Les classes et l'héritage + +#### Shape.cs + +```csharp +/// +/// Écrire une classe abstraite Shape qui contient une méthode publique virtuelle CalculateArea() qui retourne un double 0. +/// +public abstract class Shape {} +public virtual double CalculateArea(); +``` +#### Circle.cs + +```csharp +/// +/// Écrire une classe Circle qui hérite de Shape et qui contient une propriété publique de type double appelée "Radius". +/// +public class Circle {} +``` +```csharp +/// +/// Écrire un constructeur qui prend un double radius et qui initialise Radius à radius. +/// +public Circle(double radius); +``` +```csharp +/// +/// Écrire une méthode CalculateArea() qui retourne l'aire du cercle. +/// L'aire d'un cercle est calculée en faisant radius * radius * Math.PI +/// +public override double CalculateArea(); +``` +```csharp +/// +/// Écrire une méthode ToString() qui retourne une string de la forme "Circle with radius {Radius}" +/// +public override string ToString(); +``` +```csharp +/// +/// Écrire une méthode statique CreateRandom qui prend un int maxRadius et qui retourne un nouveau cercle avec un rayon aléatoire entre 0 et maxRadius. +/// Si maxRadius est négatif, une exception `ArgumentOutOfRangeException` est levée. +/// Sa surcharge sans paramètre doit créer un cercle avec un rayon aléatoire entre 1 et 100. +/// +/// +/// Pour générer un nombre aléatoire, vous pouvez utiliser Random.Next. +/// +public static Circle CreateRandom(int maxRadius); +public static Circle CreateRandom(); +``` + +#### Rectangle.cs + +```csharp +/// +/// Écrire une classe Rectangle qui hérite de Shape et qui contient deux propriétés publiques : double Width et double Height. +/// +public class Rectangle {} +``` +```csharp +/// +/// Écrire un constructeur qui prend un double width et un double height et qui initialise Width à width et Height à height. +/// +public Rectangle(double width, double height); +``` +```csharp +/// +/// Écrire une méthode override CalculateArea() qui retourne l'aire du rectangle. +/// L'aire d'un rectangle est calculée en faisant width * height +/// +public override double CalculateArea(); +``` +```csharp +/// +/// Écrire une méthode override ToString() qui retourne une string de la forme "Rectangle with width {Width} and height {Height}" +/// +public override string ToString(); +``` +```csharp +/// +/// Écrire une méthode statique CreateRandom qui prend deux doubles (maxWidth et maxHeight) et qui retourne un nouveau rectangle avec une largeur entre 1 et maxWidth et une hauteur aléatoire entre 1 et maxHeight. +/// Si maxWidth ou maxHeight est négatif, une exception `ArgumentOutOfRangeException` est levée. +/// Sa surcharge sans paramètre doit créer un rectangle avec une largeur et une hauteur aléatoire entre 1 et 100. +/// +/// +/// Pour générer un nombre aléatoire, vous pouvez utiliser Random.Next. +/// +public static Rectangle CreateRandom(double maxWidth, double maxHeight); +public static Rectangle CreateRandom(); +``` + +#### Square.cs + +```csharp +/// +/// Écrire une classe Square qui hérite de Rectangle. +/// +public class Square {} +``` +```csharp +/// +/// Écrire un constructeur qui prend un double side et qui initialise Width et Height à side. +/// +/// +/// Le corps de ce constructeur doit être vide. +/// +public Square(double side); +``` +```csharp +/// +/// Écrire une méthode override ToString() qui retourne une string de la forme "Square with side {Width}" +/// +public override string ToString(); +``` +```csharp +/// +/// Écrire une méthode statique CreateRandom qui prend un double maxSide et qui retourne un nouveau carré avec un côté aléatoire entre 1 et maxSide. +/// Si maxSide est négatif, une exception `ArgumentOutOfRangeException` est levée. +/// Son override sans paramètre doit créer un carré avec un côté aléatoire entre 1 et 100. +/// +/// +/// Pour générer un nombre aléatoire, vous pouvez utiliser Random.Next. +/// +public static Square CreateRandom(double maxSide); +public new static Square CreateRandom(); +``` + +#### Shape.cs + +```csharp +/// +/// Écrire une méthode statique CreateRandom qui prend un int nbSquare, un int nbRectangle et un int nbCircle et qui retourne un tableau de Shape de longueur (nbSquare + nbRectangle + nbCircle). +/// Le tableau doit contenir nbSquare carrés, nbRectangle rectangles et nbCircle cercles généré aléatoirement. +/// Si nbSquare, nbRectangle ou nbCircle est négatif, une ArgumentOutOfRangeException est levée. +/// +/// +/// Vous pouvez utiliser les méthodes CreateRandom de Circle, Rectangle et Square. +/// +public static Shape[] CreateRandom(int nbSquare, int nbRectangle, int nbCircle); +``` + +### Partie 2 : Les interfaces + +#### IDrawable.cs + +```csharp +/// +/// Écrire une interface IDrawable qui contient une méthode public void Draw(). +/// +public interface IDrawable {} +``` +```csharp +/// +/// Écrire une méthode statique DrawAll qui prend un tableau de IDrawable et qui appelle la méthode Draw() de chaque élément du tableau. +/// +public static void DrawAll(IDrawable[] drawables); +``` + +#### Rectangle.cs + +```csharp +/// +/// Faire hériter Rectangle de IDrawable. +/// +public class Rectangle {} +``` +```csharp +/// +/// Écrire une méthode override Draw() qui affiche +/// ---------------- +/// | | +/// | | +/// ---------------- +/// +public override void Draw(); +``` + +#### Square.cs + +```csharp +/// +/// Override la méthode Draw() de Square pour qu'elle affiche +/// ------- +/// | | +/// | | +/// ------- +/// +public override void Draw(); +``` + +#### Circle.cs + +```csharp +/// +/// Faire hériter Circle de IDrawable. +/// +public class Circle {} +``` +```csharp +/// +/// Écrire une méthode override Draw() qui affiche +/// ________ +/// / \ +/// | | +/// \________/ +/// +public override void Draw(); +``` + +#### Line.cs + +```csharp +/// +/// Écrire une classe Line qui implémente IDrawable. +/// +public class Line {} +``` +```csharp +/// +/// Écrire un constructeur qui prend deux int x et y et qui initialise X à x et Y à y. +/// +public Line(); +``` +```csharp +/// +/// Écrire une méthode override Draw() qui affiche une ligne. +/// +public override void Draw(); +``` + + + + diff --git a/content/sup/tp/iteratif_recursif.md b/content/sup/tp/S1/iteratif_recursif.md similarity index 100% rename from content/sup/tp/iteratif_recursif.md rename to content/sup/tp/S1/iteratif_recursif.md diff --git a/content/sup/tp/S1/matrixes.md b/content/sup/tp/S1/matrixes.md new file mode 100644 index 0000000..1b68d69 --- /dev/null +++ b/content/sup/tp/S1/matrixes.md @@ -0,0 +1,53 @@ +--- +title: "Matrix" +date: 2023-06-18T00:00:00+02:00 +author: "Kolowy" +description: "Entrainements sur les matrices en C#" +--- +# Introduction +Ce TP est un sujet d'entrainement pour les matrices. + +Si vous avez le mondre probleme n'hésitez pas à aller sur le serveur de l'asso et poser vos questions ou à envoyer un MP à `kolowy_` sur discord + +# Le code à compléter + +``` +/// +/// Cette fonction doit afficher la matrice. Voir l'exemple ci-dessous pour plus d'informations +/// + +static void matrixPrint(int[,] matrix) +{ + // TODO + throw new NotImplementedException(); +} + +/// +/// Transpose une matrice carrée en échangeant les lignes et les colonnes. +/// +/// La matrice carrée à transposer. +/// La matrice transposée. +static int[,] matrixTranspose(int[,] matrix) +{ + // TODO + throw new NotImplementedException(); +} + +/// +/// Point d'entrée du programme. +/// +static void Main() +{ + int[,] matrix = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }; + + int[,] matriceTransposee = matrixTranspose(matrix); + + Console.WriteLine("Matrice d'origine :"); + matrixPrint(matrix); + + Console.WriteLine("\nMatrice transposée :"); + matrixPrint(matriceTransposee); +} + +Main(); +``` diff --git a/content/sup/tp/S1/stream.md b/content/sup/tp/S1/stream.md new file mode 100644 index 0000000..d2398c6 --- /dev/null +++ b/content/sup/tp/S1/stream.md @@ -0,0 +1,113 @@ +--- +title: "Stream" +date: 2023-10-31T10:56:56+01:00 +author: "Lenny" +description: "Entraînements sur la manipulation de fichiers en C#" +--- + +# Introduction + +Ce TP est un sujet d'entraînement pour à l'utilisation de streams et de la manipulations de fichiers en C#. + +Si vous avez la moindre question, n'hésitez pas à poser vos questions sur le [serveur Discord](https://discord.gg/SJGWzkU2gd) de BackToBasics ! :D + +Les streams nous permettent de lire et écrire dans un fichier. On parle alors de manipulation de fichiers. + +# Stream.cs + +Afin de pouvoir utiliser les fonctions pour manipuler des fichiers, n'oubliez pas de rajouter le `using` suivant : + +```csharp +using System.IO; +``` + +## Existfile +```csharp +/// +/// Fonction qui vérifie si le fichier associé à `path` existe. +/// +public static bool ExistFile(string path) + +``` + +## MyReplace + +```csharp + +/// +/// Remplace chaque itération du caracètre `char` dans le fichier `path` par le caractère `replace`. +/// Elle devra modifier le fichier inscrit dans `path` et le créer si celui-ci n'existe pas. +/// +/// + /// Le fichier modifié devra se finir par un retour à la ligne. + /// Si une erreur apparaît, renvoyer une ArgumentException avec comme message "Error". +/// +public static void MyReplace(string path, char toReplace, char replace) + +``` +Prenons le fichier : *test* +``` +Bonjour, +Ceci est un message de test. +J'espere que vous allez reussir vos exams :D. +``` + +```csharp +MyReplace(path, 'e', 'f'); // path est le chemin de mon fichier +``` +On aura alors le fichier *test* suivant: +``` +Bonjour, +Cfci fst un message de tfst. +J'fspfrf quf vous allfz rfussir vos fxams :D. + +``` + +## DeleteLines + +```csharp + +/// +/// Supprime toutes les lignes multiples de la variable `n` dans le fichier `path`. +/// Elle devra modifier le fichier et le créer si celui-ci n'existe pas. +/// +/// + /// Le fichier modifié devra se finir par un retour a la ligne + /// Si le fichier n'existe pas alors renvoyer une ArgumentException avec comme message "Error" +/// +public static void DeleteLines(string path, int n) + +``` + +Prenons le fichier : *ToDelete* +``` +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +``` + +```csharp +public static void DeleteLines(path, 2); // path est le chemin de mon fichier +``` +On aura alors le fichier *ToDelete* suivant: + +``` +1 +3 +5 +7 +9 +11 + +``` + diff --git a/content/sup/tp/S2/_index.md b/content/sup/tp/S2/_index.md new file mode 100644 index 0000000..fd0fe38 --- /dev/null +++ b/content/sup/tp/S2/_index.md @@ -0,0 +1,10 @@ +--- +weight: 999 +title: "S2" +icon: "folder" +date: "2024-08-27" +lastmod: "2023-08-26T20:43:23+01:00" +draft: false +toc: true +katex: false +--- diff --git a/content/sup/tp/S2/advent_of_code.md b/content/sup/tp/S2/advent_of_code.md new file mode 100644 index 0000000..aaef679 --- /dev/null +++ b/content/sup/tp/S2/advent_of_code.md @@ -0,0 +1,683 @@ +--- +title: "Advent of Code 2022 - Partiel S2" +date: 2023-05-15T11:30:03+00:00 +weight: 1 +author: "Arthur" +showToc: true +description: "Advent of Code en C# pour le partiel des S2 à EPITA" +--- + + +L'objectif du TP est de résoudre des problèmes posés dans l'Advent Of Code 2022 tout en travaillant les notions apprises en cours. + +### Comment se présente un problème ? ++ Un énoncé (enfantin certes, mais vous pourrez vous arracher des cheveux dessus, ne vous inquiétez surtout pas) ++ Deux parties ++ Un exemple par partie ++ Un set de données court et un long + +### Contenu ++ Partie 1: une interface pour manipuler les données facilement (difficulté: 4/10) ++ Partie 2: un exercice d'échauffement (difficulté: 2.5/10) ++ Partie 3: un exercice plus avancé (difficulté: 6.5 -> 9/10) ++ **Remarque 1: la difficulté est à considérer par rapport à celle qui peut être attendue du partiel.** ++ Remarque 2 : Une fonction dont le nom est suivi d'un * dans le sujet peut être réalisée en **une ligne** (un seul ';') -> **BONUS**. + +### Notions travaillées ++ Pour tout le TP + + LinQ + + Gestion des exceptions ++ Partie 1 (nécessaire pour la suite!) + + File Management + + IEnumerable et IEnumerator + + Indexer + + Predicates / Lambdas ++ Parties 2 et 3 + + Capacité à analyser et résoudre un problème donné + + Classes abstraites ++ Partie 3 (spécifiquement) + + Orienté objet + + Parsing de données + + Optimisation (bonus) + +### Pour setup le TP ++ Télécharger le squelette: `git clone https://github.com/aderugy/TP-S2-B2B-AOC.git` ou `git@github.com:aderugy/TP-S2-B2B-AOC.git` ++ Créer une solution ++ Créer un nouveau projet '.NET/Console Application' nommé 'Exercises' (faites attention à respecter l'archi du squelette pour éviter les conflits de namespace!) ++ Rajouter les fichiers donnés dans le squelette dans leur dossier respectif (voir la section d'après pour les tests) + +### Pour tester votre projet ++ Créer un nouveau projet '.NET/Unit Test Project' **AVEC XUnit** nommé 'Tests'. ++ Glisser les fichiers de code dans leur dossier respectif ! ++ Mettez le dossier 'tests' (à la racine du repo) où vous le souhaitez. ++ Remplacez le chemin d'accès dans 'Tests/Utils.cs' par celui du dossier donné. ++ Décommentez les assertions au fur et à mesure que vous avancez dans le code des tests (ExercisesTests et FileManagerTests). ++ Lancez les tests! + + S'il y a des erreurs -> **débuggage** + + + +# Partie 1 (Nécessaire pour la suite!) + +## Exceptions.cs +**Les exceptions ne sont pas des plaies !**
Elles permettent de mieux savoir où et pourquoi le code n'a pas fonctionné. On va donc créer les nôtres, de la même façon que dans les TP. Elles doivent hériter de 'System.Exception'. ++ NoSolutionException ++ EmptyDatasetException ++ InvalidDataException + +## FileManager.cs (hérite d'IEnumerable et d'IEnumerator) +L'interface qui nous permettra de manipuler facilement les données contenues dans les fichiers de tests. Ces données permettront de tester nos solutions aux problèmes. + +### Attributs ++ `private readonly List _lines;` : une liste contenant les lignes du fichier ++ `private int _index;` + +### Constructeur ++ `public FileManager(string path)` + + path: chemin d'accès au fichier que l'on doit charger ++ Initialisation des attributs + + \_lines doit contenir les chaque ligne du contenu du fichier + + \_index est initialisé à -1 ++ Si le fichier n'existe pas ou si c'est un dossier => FileNotFoundException ++ Si le contenu du fichier est vide => EmptyDatasetException + +### Indexer ++ Rappel du prototype: `public string this[int index] { get {...} }` ++ Si l'index est en dehors des bornes de la liste => IndexOutOfRangeException + +### GetEnumerator * ++ Prototype: `public IEnumerator GetEnumerator()` ++ Quel est l'IEnumerator ici ?... + +### MoveNext * ++ Prototype: `public bool MoveNext()` ++ Incrémenter l'index de 1 et return true s'il est toujours dans les bornes de la liste, sinon false. + +### Reset * ++ Prototype: `public void Reset()` ++ Reset l'index à sa valeur initiale (on revient au début de la liste.) + +### Current * ++ Prototype : `public object Current` ++ Return l'élément correspondant à la position actuelle dans la liste. + +### Ready * ++ Prototype : `public bool Ready()` ++ Return true si l'index est inférieur au nombre de lignes, sinon false. + +### Remarque ++ Vous aurez à manipuler les données. Gardez en mémoire que **dans cette implémentation** l'index doit toujours se situer **une position avant celle du prochain élément qui sortira**. ++ C'est pour cette raison que l'on commence à -1 et non à 0 ! (cf. MoveNext.) ++ Si vous ne faites pas attention à cela, vous risquez de **sauter un élément** ou de le faire **sortir deux fois**. + +### GetMultipleLines ++ Prototype : `public List GetMultipleLines(int number)` ++ Return les N lignes **suivantes**. ++ **L'index doit se trouver à la position du dernier élément renvoyé!!!!** ++ Si number est inférieur ou égal à 0 => ArgumentException ++ S'il n'y a pas assez d'éléments => IndexOutOfRangeException + +### SkipElement * ++ Prototype : `public void SkipElement()` ++ Incrémente l'index de 1. + +### ApplyToAll * ++ Prototype : `public void ApplyToAll(Func operation)` ++ Applique l'opération à toutes les lignes du fichier. ++ Remarque: 'operation' est une **fonction** 'string -> string'. + +### TESTEZ VOTRE CODE (méthodologie en introduction) !!!!! + +## Solution.cs + +### Cette classe abstraite aura : ++ Un attribut `protected readonly FileManager _inputData;` qui nous permettra de manipuler les données ++ Un constructeur `public Solution(string path)` + + Initialiser le FileManager + + Supprimer tous les espaces et tabulations autour des lignes du fichier (il y a une fonction de la classe string qui s'occupe de le faire pour vous et une autre dans FileManager pour l'appliquer à tous...) ++ `public abstract long SolvePart1();` ++ `public abstract long SolvePart2();` + +# Partie 2 - Exercice 1 (Day1 AOC 2022) + +## LES INPUTS DONNES SERONT CORRECTS POUR TOUS LES TESTS SUR LES EXERCICES !! + +Je vous recommande (très!) vivement de bien lire l'énoncé et d'essayer de **visualiser le problème**.
N'hésitez pas à faire des jolis dessins sur Paint si ça peut vous aider, mais réfléchir par vous même vous fera certainement beaucoup plus progresser que simplement appliquer une méthode toute faite ! Ce problème reste assez facile, et si vous avez correctement implémenté le FileManager, vous avez tous les outils pour le faire. +> **Un ingénieur est avant tout censé résoudre des problèmes, et c'est l'un des meilleurs moyens d'améliorer sa technique !** + +### Enoncé partie 1 (remarque: énoncés traduits avec ChatGPT -> faites remonter s'il y a des imprécisions) + +Les Elfes se relaient pour noter le nombre de Calories contenues dans les différents repas, collations, rations, etc. qu'ils ont apportés avec eux, un article par ligne. Chaque Elfe sépare son propre inventaire de l'inventaire de l'Elfe précédent (le cas échéant) par une ligne vide. + +Par exemple, supposons que les Elfes finissent d'écrire les Calories de leurs articles et se retrouvent avec la liste suivante : + +``` +1000 +2000 +3000 + +4000 + +5000 +6000 + +7000 +8000 +9000 + +10000 +``` + +Cette liste représente les Calories de la nourriture portée par cinq Elfes :
+ Le premier Elfe transporte des aliments avec 1000, 2000 et 3000 Calories, soit un total de 6000 Calories.
+ Le deuxième Elfe transporte un aliment avec 4000 Calories.
+ Le troisième Elfe transporte des aliments avec 5000 et 6000 Calories, soit un total de 11000 Calories.
+ Le quatrième Elfe transporte des aliments avec 7000, 8000 et 9000 Calories, soit un total de 24000 Calories.
+ Le cinquième Elfe transporte un aliment avec 10000 Calories.
+ +Au cas où les Elfes auraient faim et auraient besoin de collations supplémentaires, ils doivent savoir à quel Elfe demander : ils aimeraient savoir combien de Calories sont transportées par l'Elfe qui transporte le plus de Calories. Dans l'exemple ci-dessus, il s'agit de 24000 (portées par le quatrième Elfe).
+ +**Trouvez l'Elfe qui transporte le plus de Calories. Combien de Calories totales cet Elfe transporte-t-il ?** + + +## Exercise1/SolutionEx1.cs + +Cette classe hérite de 'Solution' => ajoutez lesprototypes manquants (Rider vous l'indiquera.) + +### Constructeur ++ Appelle 'base' avec le path. + +### IsInteger * ++ Prototype : `private static bool IsInteger(string input)` ++ return true si l'input contient au moins un caractère et uniquement des chiffres, sinon false. + +### SumAllCalories (méthode principale de ce problème) ++ Prototype : `private List SumAllCalories()` ++ Return une liste contenant la somme de chaque groupe de calories ++ **Remarque : utiliser uniquement des méthodes de FileManager !** ++ Exemple: si l'on reprend la liste donnée dans l'énoncé -> '\[6000, 4000, 11000, 24000, 10000\]'. + +### SolvePart1 ++ Return le maximum de la liste donnée par SumAllCalories. ++ S'il n'y a aucun élément -> NoSolutionException + + +## Enoncé partie 2 + +Au moment où vous calculez la réponse à la question des Elfes, ils ont déjà réalisé que l'Elfe qui transporte le plus de Calories en nourriture finirait peut-être par manquer de collations.
+ +Pour éviter cette situation inacceptable, les Elfes aimeraient plutôt connaître le total des Calories transportées par les trois premiers Elfes qui transportent le plus de Calories. Ainsi, même si l'un de ces Elfes manque de collations, ils ont encore deux réserves.
+ +Dans l'exemple ci-dessus, les trois premiers Elfes sont le quatrième Elfe (avec 24000 Calories), puis le troisième Elfe (avec 11000 Calories), puis le cinquième Elfe (avec 10000 Calories). La somme des Calories transportées par ces trois elfes est de 45000.
+ +**Trouvez les trois premiers Elfes transportant le plus de Calories. Combien de Calories ces Elfes transportent-ils au total ?**
+ +### SolvePart2 ++ Return le somme des trois plus grands éléments de la liste donnée par SumAllCalories. ++ S'il n'y a pas au moins trois éléments dans la liste -> NoSolutionException. + + +# Partie 3 - Exercice 2 (Day11 AOC 2022) + +**Même chose que pour l'exercice 1 : réflechissez au problème avant de vous lancer dans sa résolution.** + +## Enoncé partie 1 + +Enfin, vous commencez à remonter la rivière, vous vous rendez compte que votre sac est beaucoup plus léger que vous ne vous en souveniez. Juste à ce moment-là, l'un des objets de votre sac passe en volant au-dessus de votre tête. Des singes jouent à se lancer vos affaires !
+ +Pour récupérer vos affaires, vous devez être capable de prédire où les singes lanceront vos objets. Après une observation attentive, vous vous rendez compte que les singes agissent en fonction de votre niveau d'inquiétude pour chaque objet.
+ +Vous prenez quelques notes (votre entrée de puzzle) sur les objets que chaque singe possède actuellement, sur votre niveau d'inquiétude pour ces objets et sur la manière dont le singe prend des décisions en fonction de votre niveau d'inquiétude. Par exemple :
+ +``` +Monkey 0: + Starting items: 79, 98 + Operation: new = old * 19 + Test: divisible by 23 + If true: throw to monkey 2 + If false: throw to monkey 3 + +Monkey 1: + Starting items: 54, 65, 75, 74 + Operation: new = old + 6 + Test: divisible by 19 + If true: throw to monkey 2 + If false: throw to monkey 0 + +Monkey 2: + Starting items: 79, 60, 97 + Operation: new = old * old + Test: divisible by 13 + If true: throw to monkey 1 + If false: throw to monkey 3 + +Monkey 3: + Starting items: 74 + Operation: new = old + 3 + Test: divisible by 17 + If true: throw to monkey 0 + If false: throw to monkey 1 +``` + +Chaque singe a plusieurs attributs :
++ Les objets de départ listent votre niveau d'inquiétude pour chaque objet que le singe tient actuellement dans l'ordre où ils seront inspectés. ++ L'opération montre comment votre niveau d'inquiétude change lorsque ce singe inspecte un objet. (Une opération comme new = old * 5 signifie que votre niveau d'inquiétude après l'inspection du singe est cinq fois ce qu'il était avant l'inspection.) ++ Le test montre comment le singe utilise votre niveau d'inquiétude pour décider où lancer un objet ensuite. ++ Si "vrai" montre ce qui se passe avec un objet si le test était vrai. ++ Si "faux" montre ce qui se passe avec un objet si le test était faux. + +Après que chaque singe a inspecté un objet mais avant de tester votre niveau d'inquiétude, votre soulagement que l'inspection du singe n'ait pas endommagé l'objet fait que votre niveau d'inquiétude est divisé par trois et arrondi à l'entier le plus proche.
+ +Les singes se relaient pour inspecter et lancer des objets. À chaque tour d'un seul singe, il inspecte et lance tous les objets qu'il tient un à un et dans l'ordre indiqué. Le singe 0 commence, puis le singe 1, et ainsi de suite jusqu'à ce que chaque singe ait fait un tour. Le processus de chaque singe prenant un seul tour s'appelle un tour.
+ +Lorsqu'un singe lance un objet à un autre singe, l'objet se place à la fin de la liste du singe destinataire. Un singe qui commence un tour sans objet pourrait finir par inspecter et lancer de nombreux objets avant que son tour n'arrive. Si un singe ne tient aucun objet au début de son tour, son tour se termine.
+ +Dans l'exemple ci-dessus, le premier tour se déroule comme suit : + +
+ Déroulement d'un tour complet +Singe 0 :
+ Le singe inspecte un objet avec un niveau d'inquiétude de 79.
+ Le niveau d'inquiétude est multiplié par 19 pour atteindre 1501.
+ Le singe s'ennuie avec l'objet. Le niveau d'inquiétude est divisé par 3 pour atteindre 500.
+ Le niveau d'inquiétude actuel n'est pas divisible par 23.
+ L'objet avec un niveau d'inquiétude de 500 est lancé au singe 3.
+ Le singe inspecte un objet avec un niveau d'inquiétude de 98.
+ Le niveau d'inquiétude est multiplié par 19 pour atteindre 1862.
+ Le singe s'ennuie avec l'objet. Le niveau d'inquiétude est divisé par 3 pour atteindre 620.
+ Le niveau d'inquiétude actuel n'est pas divisible par 23.
+ L'objet avec un niveau d'inquiétude de 620 est lancé au singe 3.
+Singe 1 :
+ Le singe inspecte un objet avec un niveau d'inquiétude de 54.
+ Le niveau d'inquiétude augmente de 6 pour atteindre 60.
+ Le singe s'ennuie avec l'objet. Le niveau d'inquiétude est divisé par 3 pour atteindre 20.
+ Le niveau d'inquiétude actuel n'est pas divisible par 19.
+ L'objet avec un niveau d'inquiétude de 20 est lancé au singe 0.
+ Le singe inspecte un objet avec un niveau d'inquiétude de 65.
+ Le niveau d'inquiétude augmente de 6 pour atteindre 71.
+ Le singe s'ennuie avec l'objet. Le niveau d'inquiétude est divisé par 3 pour atteindre 23.
+ Le niveau d'inquiétude actuel n'est pas divisible par 19.
+ L'objet avec un niveau d'inquiétude de 23 est lancé au singe 0.
+ Le singe inspecte un objet avec un niveau d'inquiétude de 75.
+ Le niveau d'inquiétude augmente de 6 pour atteindre 81.
+ Le singe s'ennuie avec l'objet. Le niveau d'inquiétude est divisé par 3 pour atteindre 27.
+ Le niveau d'inquiétude actuel n'est pas divisible par 19.
+ L'objet avec un niveau d'inquiétude de 27 est lancé au singe 0.
+ Le singe inspecte un objet avec un niveau d'inquiétude de 74.
+ Le niveau d'inquiétude augmente de 6 pour atteindre 80.
+ Le singe s'ennuie avec l'objet. Le niveau d'inquiétude est divisé par 3 pour atteindre 26.
+ Le niveau d'inquiétude actuel n'est pas divisible par 19.
+ L'objet avec un niveau d'inquiétude de 26 est lancé au singe 0.
+Singe 2 :
+ Le singe inspecte un objet avec un niveau d'inquiétude de 79.
+ Le niveau d'inquiétude est multiplié par lui-même pour atteindre 6241.
+ Le singe s'ennuie avec l'objet. Le niveau d'inquiétude est divisé par 3 pour atteindre 2080.
+ Le niveau d'inquiétude actuel est divisible par 13.
+ L'objet avec un niveau d'inquiétude de 2080 est lancé au singe 1.
+ Le singe inspecte un objet avec un niveau d'inquiétude de 60.
+ Le niveau d'inquiétude est multiplié par lui-même pour atteindre 3600.
+ Le singe s'ennuie avec l'objet. Le niveau d'inquiétude est divisé par 3 pour atteindre 1200.
+ Le niveau d'inquiétude actuel n'est pas divisible par 13.
+ L'objet avec un niveau d'inquiétude de 1200 est lancé au singe 3.
Update README.md + Le singe inspecte un objet avec un niveau d'inquiétude de 97.
+ Le niveau d'inquiétude est multiplié par lui-même pour atteindre 9409.
+ Le singe s'ennuie avec l'objet. Le niveau d'inquiétude est divisé par 3 pour atteindre 3136.
+ Le niveau d'inquiétude actuel n'est pas divisible par 13.
old + L'objet avec un niveau d'inquiétude de 3136 est lancé au singe 3.
+Singe 3 :
+ Le singe inspecte un objet avec un niveau d'inquiétude de 74.
+ Le niveau d'inquiétude augmente de 3 pour atteindre 77.
+ Le singe s'ennuie avec l'objet. Le niveau d'inquiétude est divisé par 3 pour atteindre 25.
+ Le niveau d'inquiétude actuel n'est pas divisible par 17.
+ L'objet avec un niveau d'inquiétude de 25 est lancé au singe 1.
+ Le singe inspecte un objet avec un niveau d'inquiétude de 500.
+ Le niveau d'inquiétude augmente de 3 pour atteindre 503.
+ Le singe s'ennuie avec l'objet. Le niveau d'inquiétude est divisé par 3 pour atteindre 167.
+ Le niveau d'inquiétude actuel n'est pas divisible par 17.
+ L'objet avec un niveau d'inquiétude de 167 est lancé au singe 1.
+ Le singe inspecte un objet avec un niveau d'inquiétude de 620.
+ Le niveau d'inquiétude augmente de 3 pour atteindre 623.
+ Le singe s'ennuie avec l'objet. Le niveau d'inquiétude est divisé par 3 pour atteindre 207.
+ Le niveau d'inquiétude actuel n'est pas divisible par 17.
+ L'objet avec un niveau d'inquiétude de 207 est lancé au singe 1.
+ Le singe inspecte un objet avec un niveau d'inquiétude de 1200.
+ Le niveau d'inquiétude augmente de 3 pour atteindre 1203.
+ Le singe s'ennuie avec l'objet. Le niveau d'inquiétude est divisé par 3 pour atteindre 401.
+ Le niveau d'inquiétude actuel n'est pas divisible par 17.
+ L'objet avec un niveau d'inquiétude de 401 est lancé au singe 1.
+ Le singe inspecte un objet avec un niveau d'inquiétude de 3136.
+ Le niveau d'inquiétude augmente de 3 pour atteindre 3139.
+ Le singe s'ennuie avec l'objet. Le niveau d'inquiétude est divisé par 3Update README.md pour atteindre 1046.
+ Le niveau d'inquiétude actuel n'est pas divisible par 17.
+ L'objet avec un niveau d'inquiétude de 1046 est lancé au singe 1.
+ + +Après le premier tour, les singes tiennent des objets avec ces niveaux d'inquiétude :
+ +Singe 0 : 20, 23, 27, 26
+Singe 1 : 2080, 25, 167, 207, 401, 1046
+Singe 2 :
+Singe 3 :
+ +Les singes 2 et 3 ne tiennent aucun objet à la fin du tour ; ils ont tous deux inspecté des objets pendant le tour et les ont tous lancés avant la fin du tour.
+ +Ce processus se poursuit pendant quelques tours supplémentaires :
+ +Après le deuxième tour, les singes tiennent des objets avec ces niveaux d'inquiétude :
+Singe 0 : 695, 10, 71, 135, 350
+Singe 1 : 43, 49, 58, 55, 362
+Singe 2 :
+Singe 3 :
+ +Après le troisième tour, les singes tiennent des objets avec ces niveaux d'inquiétude :
+Singe 0 : 16, 18, 21, 20, 122
+Singe 1 : 1468, 22, 150, 286, 739
+Singe 2 :
+Singe 3 :
+ +Après le quatrième tour, les singes tiennent des objets avec ces niveaux d'inquiétude :
+Singe 0 : 491, 9, 52, 97, 248, 34
+Singe 1 : 39, 45, 43, 258
+Singe 2 :
old +Singe 3 :
+ +Après le cinquième tour, les singes tiennent des objets avec ces niveaux d'inquiétude :
+Singe 0 : 15, 17, 16, 88, 1037
+Singe 1 : 20, 110, 205, 524, 72
+Singe 2 :
+Singe 3 :
+ +Après le sixième tour, les singes tiennent des objets avec ces niveaux d'inquiétude : +Singe 0 : 8, 70, 176, 26, 34 +Singe 1 : 481, 32, 36, 186, 2190 +Singe 2 : +Singe 3 : + +Après le septième tour, les singes tiennent des objets avec ces niveaux d'inquiétude :
+Singe 0 : 162, 12, 14, 64, 732, 17
+Singe 1 : 148, 372, 55, 72
+Singe 2 :
+Singe 3 :
+ +Après le huitième tour, les singes tiennent des objets avec ces niveaux d'inquiétude : +Singe 0 : 51, 126, 20, 26, 136 +Singe 1 : 343, 26, 30, 1546, 36 +Singe 2 : +Singe 3 : + +Après le neuvième tour, les singes tiennent des objets avec ces niveaux d'inquiétude :
+Singe 0 : 116, 10, 12, 517, 14
+Singe 1 : 108, 267, 43, 55, 288
+Singe 2 :
+Singe 3 :
+ +Après le dixième tour, les singes tiennent des objets avec ces niveaux d'inquiétude :
+Singe 0 : 91, 16, 20, 98
+Singe 1 : 481, 245, 22, 26, 1092, 30
+Singe 2 :
+Singe 3 :
+ +... + +Après le quinzième tour, les singes tiennent des objets avec ces niveaux d'inquiétude :
+Singe 0 : 83, 44, 8, 184, 9, 20, 26, 102
+Singe 1 : 110, 36
+Singe 2 :
+Singe 3 :
+ +... + +Après le vingtième tour, les singes tiennent des objets avec ces niveaux d'inquiétude :
+Singe 0 : 10, 12, 14, 26, 34
+Singe 1 : 245, 93, 53, 199, 115
+Singe 2 :
+Singe 3 :
+ +Poursuivre tous les singes en même temps est impossible ; vous allez devoir vous concentrer sur les deux singes les plus actifs si vous voulez avoir une chance de récupérer vos affaires. Comptez le nombre total de fois que chaque singe inspecte des objets sur 20 tours :
+ +Le singe 0 a inspecté des objets 101 fois.
+Le singe 1 a inspecté des objets 95 fois.
+Le singe 2 a inspecté des objets 7 fois.
+Le singe 3 a inspecté des objets 105 fois.
+ +
+ Dans cet exemple, les deux singes **les plus actifs ont inspecté des objets 101 et 105 fois**.
+
+ **CONSIGNE** + **Le résultat dans cette situation peut être trouvé en multipliant les deux plus grands nombres d'inspections parmi les singes ensemble : 10605**.
+ **Découvrez quels singes poursuivre en comptant combien d'objets ils inspectent sur 20 tours. Quel est le résultat après 20 tours ?** + +## Exercise2/Monkey.cs ++ Cette classe nous permettra de simuler le comportement d'un singe tel qu'il l'est décrit dans l'énoncé. ++ Pourquoi avoir créé une classe ? + + On peut voir dans les données qu'on aura plusieurs singes à simuler. + + On devra donc instancier plusieurs objets au comportement similaire. + + C'est précisement le but de l'orienté objet ! + + Les attributs correspondent aux données initiales de nos singes (ex: l'inventaire, le test, les cibles selon le résultat du test...) + + Les comportements seront simulés par des **lambdas**, ie. des fonctions 'stockées dans des variables' (plus exactement définie lorsque l'on lance le programme et en s'appuyant sur des données calculées at runtime) + + Ces comportements / attributs seront extraits des données, il faudra faire un parser (simple.) + +### Attributs ++ `private readonly Queue _inventory;` : les objets tenus par un singe +> On utilise une queue car on veut sortir les éléments **dans l'ordre d'arrivée**. ++ `private readonly Func _operation;` : L'opération appliquée à un objet lors de l'inspection. ++ `public readonly int Divider;` : le diviseur du test de divisibilité lors de l'inspection. ++ `private readonly int _targetTestTrue;` : le numéro du singe auquel renvoyer l'objet si le test échoue. ++ `private readonly int _targetTestFalse;` : le numéro du singe auquel renvoyer l'objet si le test réussi. ++ `public int InspectionCount = 0;` : on comptera le nombre de fois qu'un singe inspecte un objet. + +### Constructeur ++ Prototype : `public Monkey(Queue inventory, Func operation, int divider, int targetTestTrue, int targetTestFalse)` + +### HasItemsLeft * ++ Prorotype :`public bool HasItemsLeft()` + +### GetNextItem * ++ Prototype : `public long GetNextItem()` ++ Dequeue un objet et le return. + +### AddItem * ++ Prorotype : `public void AddItem(long item)` ++ Ajouter un objet à l'inventaire. + +### ApplyOperation * ++ Prototype : `public long ApplyOperation()` ++ Appliquer l'opération (voir les attributs) au prochain objet dans l'inventaire. + +### Test * ++ Prototype : `public int Test(long value)` ++ Vérifier si value est divisible par Diviser et return le bon attribut en conséquence **(regardez les attributes !!)** + +### ParseMonkeyInventory * ++ Prototype : `public static IEnumerable ParseMonkeyInventory(string data)` ++ Remarque: long = un integer de 64 bits +> Exemple: `Starting items: 79, 98` -> `[79, 98]` + +### ParseMonkeyOperation ++ Prototype : `public static Func ParseOperation(string data)` ++ Vous devez return une lambda + + Type: 'long -> long' + + Paramètre: old (long) + + Opérateurs pris en charge : '+, -, /, \*' + + Méthodologie : + + L'opération est de la forme 'Operation: new = {MEMBRE DE GAUCHE} {OPERATEUR} {MEMBRE DE DROITE}' + + Trouver la valeur du membre gauche et du membre droit de l'opération + + Si c'est "old", remplacer par la valeur de old en paramètre, sinon c'est la valeur du membre de l'opération + + Faire le calcul avec l'opérateur... + + ** ON TRAVAILLE AVEC DES 'LONG' ICI** +> Cette méthode peut s'avérer compliquée à implémenter. Voir le cours de Gollum sur les lambdas ! +> Exemple: 'Operation: new = old * 19' : `(old) => { return old * 19;} // CECI EST UNE FONCTION LAMBDA... à vous de l'automatiser` +> Petit rappel: une lambda se définit de la façon suivante +``` +(type1 param1, type2 param2...) => { + // Des choses à faire; + return value; +} +``` + +
+ ParseMonkeyOperation corrigée (essayez avant!!!) + Désolé pour le formattage pas trouvé !
+ public static Func ParseMonkeyOperation(string data) + { + string[] operation = data[(data.IndexOf('=') + 2)..].Split(' '); + + if (operation.Length != 3 || operation[1].Length != 1) + throw new InvalidDataException(); + + return (old) => + { + long leftMember = operation[0] == "old" ? old : Convert.ToInt64(operation[0]); + long rightMember = operation[2] == "old" ? old : Convert.ToInt64(operation[2]); + + return operation[1][0] switch + { + '+' => leftMember + rightMember, + '-' => leftMember - rightMember, + '/' => leftMember / rightMember, + '*' => leftMember * rightMember, + _ => throw new InvalidDataException() + }; + }; + } + +
+ +### GetLastValueAsInt * ++ Prototype : `public static int GetLastValueAsInt(string data)` ++ Extraire le dernier 'mot' d'un string et return sa valeur en int. +> Exemple : GetLastValueAsInt('Test: divisible by 19') -> 19 + +### Parse (La fonction la plus importante de la classe !) ++ Prototype : `public static Monkey Parse(List data)` ++ Convertit une liste de string en une instance de la classe Monkey. ++ S'il n'y a pas exactement 6 éléments dans data -> InvalidDataException ++ De manière générale, s'il y a une exception lors de l'extraction des données -> InvalidDataException +> Vous devez gérer TOUTES les exceptions qui peuvent survenir, il existe une notation qui permet de gérer efficacement les exceptions...) ++ Vous utiliserez les fonctions définies avant celle-ci pour récupérer toutes les données nécessaires à l'instantiation d'un Monkey. + +## Exercise2/SolutionEx2.cs + +### Attributes ++ `private readonly List _monkeys;` : la liste contenant toutes nos instances des singes + +### Constructeur ++ Appeler le constructeur 'base' avec en argument 'path'. ++ Initialiser \_monkeys avec une liste vide. ++ Tant que le l'\_inputData est prêt: + + Lire 6 lignes du fichier + + Créer un Monkey avec ces données + + L'ajouter à notre liste de singes + + Skip une ligne (il y a une newline entre chaque définition de singe dans notre set de données!) + +### SolvePart1 ++ Il y a **20 tours**. ++ Chaque tour consiste en: + + Pour chaque singe: + + Tant qu'il lui reste des objets: + + Récupérer la valeur de l'objet qu'il étudie (le résultat de l'application de son opération divisé par 3) + + Trouver à qui renvoyer l'objet (en effectuant le test) => l'index de la cible dans la liste de singes + + Incrémenter l'InspectionCount + + Rajouter l'objet au singe correspondant dans la liste ++ Déterminer les deux singes avec le plus grand InspectionCount, multiplier ces deux valeurs entre elles et en return le produit. + +## Enoncé partie 2 + +Tu es inquiet de ne peut-être jamais récupérer tes objets. Si inquiet, en fait, que ton soulagement qu'une inspection de singe n'ait pas endommagé un objet ne divise plus ton niveau d'inquiétude par trois.
+ +Malheureusement, ce soulagement était tout ce qui empêchait tes niveaux d'inquiétude d'atteindre des niveaux ridicules. Tu devras trouver une autre manière de garder tes niveaux d'inquiétude gérables.
+ +À ce rythme, tu risques de supporter ces singes pendant très longtemps - peut-être 10000 tours !
+ +Avec ces nouvelles règles, tu peux encore comprendre les singeries après 10000 tours. En utilisant le même exemple ci-dessus :
+ +
+ Exemple d'un tour +== Après le tour 1 ==
+Singe 0 a inspecté les objets 2 fois.
+Singe 1 a inspecté les objets 4 fois.
+Singe 2 a inspecté les objets 3 fois.
+Singe 3 a inspecté les objets 6 fois.
+ +== Après le tour 20 ==
+Singe 0 a inspecté les objets 99 fois.
+Singe 1 a inspecté les objets 97 fois.
+Singe 2 a inspecté les objets 8 fois.
+Singe 3 a inspecté les objets 103 fois.
+ +== Après le tour 1000 ==
+Singe 0 a inspecté les objets 5204 fois.
+Singe 1 a inspecté les objets 4792 fois.
+Singe 2 a inspecté les objets 199 fois.
+Singe 3 a inspecté les objets 5192 fois.
+ +== Après le tour 2000 ==
+Singe 0 a inspecté les objets 10419 fois.
+Singe 1 a inspecté les objets 9577 fois.
+Singe 2 a inspecté les objets 392 fois.
+Singe 3 a inspecté les objets 10391 fois.
+ +== Après le tour 3000 ==
+Singe 0 a inspecté les objets 15638 fois.
+Singe 1 a inspecté les objets 14358 fois.
+Singe 2 a inspecté les objets 587 fois.
+Singe 3 a inspecté les objets 15593 fois.
+ +== Après le tour 4000 ==
+Singe 0 a inspecté les objets 20858 fois.
+Singe 1 a inspecté les objets 19138 fois.
+Singe 2 a inspecté les objets 780 fois.
+Singe 3 a inspecté les objets 20797 fois.
+ +== Après le tour 5000 ==
+Singe 0 a inspecté les objets 26075 fois.
+Singe 1 a inspecté les objets 23921 fois.
+Singe 2 a inspecté les objets 974 fois.
+Singe 3 a inspecté les objets 26000 fois.
+ +== Après le tour 6000 ==
+Singe 0 a inspecté les objets 31294 fois.
+Singe 1 a inspecté les objets 28702 fois.
+Singe 2 a inspecté les objets 1165 fois.
+Singe 3 a inspecté les objets 31204 fois.
+ +== Après le tour 7000 ==
+Singe 0 a inspecté les objets 36508 fois.
+Singe 1 a inspecté les objets 33488 fois.
+Singe 2 a inspecté les objets 1360 fois.
+Singe 3 a inspecté les objets 36400 fois.
+ +== Après le tour 8000 ==
+Singe 0 a inspecté les objets 41728 fois.
+Singe 1 a inspecté les objets 38268 fois.
+Singe 2 a inspecté les objets 1553 fois.
+Singe 3 a inspecté les objets 41606 fois.
+ +== Après le tour 9000 ==
+Singe 0 a inspecté les objets 46945 fois.
+Singe 1 a inspecté les objets 43051 fois.
+Singe 2 a inspecté les objets 1746 fois.
+Singe 3 a inspecté les objets 46807 fois.
+ +== Après le tour 10000 ==
+Singe 0 a inspecté les objets 52166 fois.
+Singe 1 a inspecté les objets 47830 fois.
+Singe 2 a inspecté les objets 1938 fois.
+Singe 3 a inspecté les objets 52013 fois.
+
+ +Après 10000 tours, les deux singes les plus actifs ont inspecté les objets 52166 et 52013 fois.
**En multipliant ces chiffres ensemble, le résultat est maintenant de 2713310158.**
+ +**Les niveaux d'inquiétude ne sont plus divisés par trois après chaque inspection d'objet**; tu devras trouver une autre manière de garder tes niveaux d'inquiétude gérables.
+**En repartant de l'état initial dans les données de ton puzzle, quel est le niveau de singeries après 10000 tours ?** + +### SolvePart2 (**QUESTION BONUS**) ++ Il y a **10000 tours** ++ Le fonctionnement d'un tour est le même sauf **qu'on ne divise pas par 3 le résultat de l'application** ++ Si vous essayez vous verrez qu'il faut optimiser quelque chose... :) +> Indice: p et q deux entiers premiers, n un naturel -> p divise n => p divise n % (p * q) + +# FIN + +Si vous avez réussi à finir, vous aurez une excellente note au partiel :)
+Sinon, pas de panique, le sujet est devenu vraiment difficile à partir de ParseMonkeyOperation. diff --git a/content/sup/tp/S2/basics_partiels.md b/content/sup/tp/S2/basics_partiels.md new file mode 100644 index 0000000..73f65b1 --- /dev/null +++ b/content/sup/tp/S2/basics_partiels.md @@ -0,0 +1,93 @@ +--- +title: "Basics partiel S2" +date: 2023-05-15T11:30:03+00:00 +author: "Kolowy" +description: "Entraînements basic pour le partiel des S2 à EPITA" +--- + +Voici un entraînement aux basic de partiel de programmation S2 + +Si vous avez le moindre problème n'hésitez pas à aller sur le serveur de l'asso et poser vos questions ou à envoyer un MP à `kolowy#6639` sur discord + +``` +/* + * Ecrire une fonction **FiBuzz(int n)** qui affiche tous les entiers de 1 à n, un par ligne. + * Si l'entier est multiple de 3, afficher "Fizz" au lieu de l'entier. + * Si l'entier est multiple de 5, afficher "Buzz" au lieu de l'entier. + * Si l'entier est à la fois multiple de 3 et de 5, afficher "FizzBuzz" au lieu de l'entier. + */ +static void FiBuzz(int n) +{ + // TODO + throw new NotImplementedException(); +} + +/* + * Ecrire une fonction récursive Factorielle(int n), + * qui prend en entrée un entier positif n et retourne sa factorielle. + */ +static int Factorielle(int n) +{ + // TODO + throw new NotImplementedException(); +} + +/* + * Ecrire une fonction Fibonacci : F(n) = F(n-1) + F(n-2) + * La suite de Fibonacci est une suite d'entiers dans laquelle chaque terme est la somme des deux termes qui le précèdent. + * Elle commence par les termes 0 et 1. + */ +static int Fibonacci(int n) +{ + // TODO + throw new NotImplementedException(); +} + +/* + * Ecrire une fonction EstPalindrome(string s) qui prend en entrée une chaîne de caractères + * et qui retourne vrai si la chaîne est un palindrome + * (c'est-à-dire si elle peut être lue de la même façon de gauche à droite et de droite à gauche), et faux sinon. + * Attention a prendre en compte les majuscule et les espaces + * Exemple : "kayak" est un palindrome, "Eric notre valet alla te laver ton cire» en est un aussi + */ +static bool EstPalindrome(string s) +{ + // TODO + throw new NotImplementedException(); +} + +/* + * Ecrire une fonction FilterList(List liste, Func predicate), + * qui prend en entrée une liste d'entiers et une fonction prédicat, + * et qui retourne une nouvelle liste ne contenant que les éléments de la liste d'origine + * pour lesquels la fonction prédicat retourne vrai. + * La fonction doit utiliser une lambda expression pour le prédicat. + */ +static List FilterList(List list, Func predicate) +{ + // TODO + throw new NotImplementedException(); +} + +/* + * Ecrire une fonction InverserPile(Stack pile), qui prend en entrée une pile d'entiers + * et qui retourne une nouvelle pile contenant les éléments de la pile d'origine dans l'ordre inverse. + * La fonction doit utiliser une file pour inverser la pile. + */ +static Stack InverserPile(Stack pile) +{ + // TODO + throw new NotImplementedException(); +} + +/* + * Ecrire une fonction SelectionnerPairs(List liste), qui prend en entrée une liste d'entiers + * et qui retourne une nouvelle liste contenant tous les nombres pairs de la liste d'origine, + * triés par ordre croissant. La fonction doit utiliser la syntaxe de requête Linq. + */ +List SelectionnerPairs(List liste) +{ + // TODO + throw new NotImplementedException(); +} +``` diff --git a/content/sup/tp/S2/collections.md b/content/sup/tp/S2/collections.md new file mode 100644 index 0000000..c9bf98f --- /dev/null +++ b/content/sup/tp/S2/collections.md @@ -0,0 +1,137 @@ +--- +title: "Collections" +date: 2023-06-19T17:55:42+02:00 +author: Greg +--- + +# Introduction + +Au cours de ce sujet, nous allons aborder les collections en C#. +Avant de commencer, je vous invite à lire [cette page](https://learn.microsoft.com/fr-fr/dotnet/csharp/programming-guide/concepts/collections) +afin de vous mettre en jambes. Vous y trouverez par ailleurs tous outils +nécessaires pour réaliser ce TP de révision. + +Ce TP se déroulera en 2 parties, et abordera les collections suivantes (une par +partie) : +- Listes +- Dictionnaires + + +# Listes + +Pour s'entrainer à manipuler les listes, vous allez pouvoir faire quelques +fonctions qui manipulent les listes afin de mieux les maîtriser. + +## Tri fusion + +Nous allons faire ici deux fonctions qui font toutes les deux un tri fusion, +mais de manière très différente : + +```csharp +/// +/// Tri la liste list sans la modifier. +/// +/// +/// Retourne la liste triée +/// +public static List TriFusion(List list) {} +``` +```csharp +/// +/// Tri la liste list en place. +/// +/// +/// Retourne la liste triée +/// +/// +/// Vous pouvez créer vos propres fonctions. +/// +public static void TriFusion(List list) {} +``` + +## Des partitions + +On dit qu'une liste est une partition avec une valeur pivot si : +1. La valeur pivot est dans la liste +2. Les valeurs à gauche du pivot sont inférieures ou égales au pivot +3. Les valeurs à droite du pivot sont supérieures ou égales au pivot + +```csharp +/// +/// Cherche un pivot dans une liste. +/// +/// +/// L'indexe du pivot. Si plusieurs pivots sont trouvés, retourner le premier. +/// Si il n'y a pas de pivot, retourner `-1` +/// +public static int FindPivot(List list) {} +``` + +Rajoutons maintenant une nouvelle condition : +4. Il faut que les valeurs à gauche du pivot soient triées par ordre croissant. +5. Il faut que les valeurs à droite du pivot soient triées par ordre + décroissant. + +En suivant les même spécifications, voici la fonction à écrire : +```csharp +/// +/// Cherche un pivot dans une liste. +/// +/// +/// L'indexe du pivot. Si plusieurs pivots sont trouvés, retourner le premier. +/// Si il n'y a pas de pivot, retourner `-1` +/// +public static int FindPivotSorted(List list) {} +``` + + +# Les Dictionnaires + +## Le Morse +Pour s'entrainer à l'utilisation des dictionnaires, vous allez commencer par +implémenter une fonction qui vous permettra de décoder le langage morse. +Les messages codés seront de la forme suivante (chaque lettre est séparée par un +espace) : +``` +-... .. . -. / .--- --- ..- . / - ..- / .- ... / - .-. --- ..- ...- . / .-.. . / -- . ... ... .- --. . / -.-. .- -.-. .... . +``` + +{{< figure src="resources/images/morse.png" width=200 caption="Code Morse International" >}} + + +### Création du dictionnaire + +La première étape est d'abord de créer un dictionnaire. Pour ce faire, vous +pouvez créer la classe statique `Morse` qui contiendra la propriété +`Dictionary MorseToLetter`. + +### Décodons tout ça ! + +```csharp +/// +/// Encode une chaine en morse (en séparant chaque lettre par un espace) +/// +public static string DecodeMorse(string message) {} +``` + + +## Analyse fréquentielle + +Dans cette partie, vous allez devoir compter les mots d'un texte pour ensuite +fournir des informations à l'utilisateur. Vous devrez afficher des informations +dans la console : +- Nombre de mots +- Nombre de mots différents +- Le mot le plus fréquent +- Le mot le moins fréquent + +Vous utiliserez bien entendu un dictionnaire pour regrouper toutes ces +informations. + +```csharp +/// +/// Affiche des informations sur un texte +/// +public static void DisplayInfo(string text) {} +``` + diff --git a/content/sup/tp/S2/files.md b/content/sup/tp/S2/files.md new file mode 100644 index 0000000..2e925e9 --- /dev/null +++ b/content/sup/tp/S2/files.md @@ -0,0 +1,169 @@ +--- +title: "Les fichiers" +date: 2023-06-19T13:41:00+02:00 +author: Greg +description: "Un TP sur la manipulation de fichiers" +tags: + - Fichiers +--- + +# Introduction + +Ce TP se composera de plusieurs parties indépendantes les unes des autres. Si +vous avez besoin d'aide, n'hésitez pas à poser vos questions sur le serveur +discord de BackToBasics ! + +Vous pouvez aussi trouver la documentation concernant la manipulation des fichiers juste [ici](https://learn.microsoft.com/fr-fr/dotnet/api/system.io.file?view=net-7.0). + +## Partie 1 : des sudokus par milliers + +Pour cette première partie, nous allons essayer de lire des grilles de sudoku +enregistrées dans des fichiers, et même d'en enregistrer de nouvelles ! + +Le but de cet exercice est de compléter une classe `Sudoku` afin de pouvoir +enregistrer et charger des grilles de sudoku provenant de fichiers textes. + +Les grilles de sudoku seront enregistrées sous ce format dans les fichiers : + +```text +... ..4 58. +... 721 ..3 +4.3 ... ... + +21. .67 ..4 +.7. ... 2.. +63. .49 ..1 + +3.6 ... ... +... 158 ..6 +... ..6 95. +``` +_Note : les `.` correspondent à une case vide, et seront représenté par l'entier `0` + dans la matrice contenant le sudoku._ + +_Note bis : le fichier se termine par un retour à la ligne final._ + +### `Sudoku.cs` + +Ce fichier sera l'unique fichier de code de cette partie. +Dans ce fichier, vous devrez implémenter une classe statique `Sudoku` appartenant au +namespace `Sudoku`. Elle possèdera ces deux propriétés : + +Voici les fonctions que vous devrez implémenter : + +```cs +/// +/// Charge la grille contenue dans le fichier filename +/// +/// +/// Lève une exception de type `InvalidArgumentException` si le fichier n'existe +/// pas +/// +public static int[,] LoadGrid(string filename) {} + +/// +/// Enregistre la grille grid dans le fichier +/// filename +/// +public static void SaveGrid(int[,] grid, string filename) {} +``` + + + + + +## Partie 2 : des logs + +Dans cette partie, vous allez devoir écrire un fichier de log. +Un fichier de log ne doit contenir qu'un seul message par ligne. Un message ne +doit pas s'étaler sur plusieurs lignes. + +Toute bonne ligne de log doit contenir, dans cet ordre, au moins ces +informations : +1. La date au format de votre choix +2. L'heure, au format HH:MM:SS +3. Le niveau de log (info, avertissement, erreur) +4. Un message descriptif + +### `Logs.cs` + +Commencez par créer une énumération nommée `LogLevel` avec les valeurs +suivantes : +- Info +- Warning +- Error + +Vous allez devoir écrire ces fonctions dans votre fichier : + +```cs +/// +/// Créé un fichier de log. +/// +/// +/// `true` si le fichier a été créé avec succès, `false` sinon. +/// +/// +/// Si ce fichier existe déjà, retourner `false` sans effectuer de modifications +/// +public static bool CreateLogFile(string filename) {} + + +/// +/// Supprime un fichier de log. +/// +/// +/// `true` si le fichier a été supprimé avec succès, `false` sinon. +/// +public static bool DeleteLogFile(string filename) {} + + + + +/// +/// Ajoute le message message au fichier de log +/// logfile +/// +public static bool AddLog(string logfile, LogLevel level, string message) {} + + +/// +/// Récupère toutes les lignes de log comprises entre startLine +/// et endLine (comprises). +/// +/// +/// Lève une exception `InvalidArgumentException` si le fichier est trop court +/// ou n'existe pas +/// +public static string[] GetLines(string logfile, int startLine, int endLine) {} + + +/// +/// Supprime la ligne line du fichier de log. +/// +/// +/// Lève une exception `InvalidArgumentException` si le fichier est trop court +/// ou n'existe pas +/// +public static void RemoveLine(string logfile, int line) {} + + +/// +/// Modifie la ligne line du fichier de log. +/// +/// +/// Lève une exception `InvalidArgumentException` si le fichier est trop court +/// ou n'existe pas +/// +public static void ModifyLine( + string logfile, + int line, + LogLevel level, + string message) {} +``` + +# Conclusion + +Voilà, c'est la fin ! +Félicitation à vous d'être arrivé au bout ! + +N'hésitez pas à regarder les autres sujets d'entrainement disponibles ! diff --git a/content/sup/tp/S2/generics.md b/content/sup/tp/S2/generics.md new file mode 100644 index 0000000..6de373a --- /dev/null +++ b/content/sup/tp/S2/generics.md @@ -0,0 +1,54 @@ +--- +title: "Generics partiel S2" +date: 2023-05-15T11:30:03+00:00 +weight: 13 +author: "Ilan Mayeux" +description: "Entraînements Generics pour le partiel des S2 à EPITA" +--- + +Voici un entraînement sur les Generics pour le partiel de programmation S2 + +Si vous avez le moindre problème n'hésitez pas à aller sur le serveur de l'asso et poser vos questions ou à envoyer un MP à `Taliayaka | イラヌ | 生嵐#3699` sur discord + +``` +/* + * Écrire une classe Element utilisant un Generic ayant deux attributs public: + * - T Content + * - Element? Next + * Son constructeur prend un content de type T et initialize Next à null. + */ + +public Element(T content); + +/* + * Écrire une classe List utilisant un Generic ayant un attribut privé: + * - Element? _head + * Son constructeur crée un nouvel _head avec l'élément donné en paramètre. + */ + +public List(); +public List(T element); + +/* + * Écrire une fonction Add qui ajoute le T element donné à la fin de la liste chaîné de _head. + * Si head n'existe pas, element devient la nouvelle head de la liste; + */ + +public void Add(T element); + +/* + * Écrire un indexeur qui permet d'accéder ou set le content de l'élement d'index donné. + * Une IndexOutOfRangeException est throw si l'index est invalide + * + * Hint: Une fonction auxiliaire renvoyant l'élément d'index donné peut être utile. + */ + +public T this[int index]; + +/* + * Écrire une fonction Pop qui supprime et renvoie l'élement à l'index donné. + * Si l'index est invalide, une InvalidIndexException est renvoyée. + */ + + public T Pop(int index = 0); +``` diff --git a/content/sup/tp/S2/ienumerable.md b/content/sup/tp/S2/ienumerable.md new file mode 100644 index 0000000..585df2b --- /dev/null +++ b/content/sup/tp/S2/ienumerable.md @@ -0,0 +1,114 @@ +--- +title: "IEnumerable" +date: 2023-06-25T14:21:49+02:00 +author: "Greg" +--- + +# Introduction + +Dans ce TP, nous allons manipuler l'interface `IEnumerable` afin de mieux +comprendre son fonctionnement. Pour ce faire, nous allons implémenter une classe +qui servira à lister les étudiants d'une école. + +# `StudentList.cs` + +Vous devez donc implémenter une classe `StudentList` qui héritera de l'interface +`IEnumerable`. Elle devra posséder les propriétés suivantes : + +```cs +/// La liste des identifiants etudiants +int[] ids; + +/// La liste des noms des etudiants +string[] names; + +/// La liste des prenoms des etudiants +string[] surname; +``` + +Voici les fonctions que vous devrez implémenter : + +```cs +/// +/// Renvoie un IEnumerator permettant d'acceder aux informations de l'etudiant +/// sous forme de Tuple (id, name, surname). +/// +public IEnumerator GetEnumerator() {} + +/// +/// Renvoie un IEnumerable permettant d'accéder aux informations des étudiants Tuple (id, name, surname) qui correspond au prédicat donné par rapport à son id, un deuxième par rapport à son nom, un troisième par rapport à son nom de famille et un dernier par rapport au tuple. +/// +public IEnumerable> GetByIdPredicate(Predicate predicate); +public IEnumerable> GetByNamePredicate(Predicate predicate); +public IEnumerable> GetBySurnamePredicate(Predicate predicate); +public IEnumerable> GetByPredicate(Predicate> predicate); +/// +/// Renvoie un tuple (id, name, surname) correspondant a l'etudiant numero +/// key +/// +/// +/// Une exception InvalidArgumentException est levee si key est +/// trop grand +/// +public Tuple this[int key] {} + +/// +/// Fonction que nous allons utiliser comme predicat personnalise dans la suite +/// +public delegate bool Predicate(T0 a, T1 b); +/// +/// Tri la liste des identifiants selon le predicat. +/// Pour la valeur par defaut de ce parametre, vous devrez creer une fonction +/// lambda qui tri la liste en ordre croissant. +/// +/// +/// Bien entendu, l'identifiant doit toujours correspondre au nom et prenom de +/// l'etudiant. Pour ce faire, vous pouvez implementer votre propre tri. +/// https://en.wikipedia.org/wiki/Quicksort#Algorithm +/// +public void Sort(Predicate p) {} + + +/// +/// Fonction de tri permettant de trier les identifiants dans l'ordre croissant +/// +public void Sort() {} + + +/// +/// Ajoute un element a la position i. Si i est +/// null, ajoute l'element a la fin de la liste. +/// +/// +/// Bien entendu, l'identifiant doit toujours correspondre au nom et prenom de +/// l'etudiant. +/// +public void Add(Tuple elt, int i = null) {} + + +/// +/// Ajoute un element selon le critere de tri donne par le predicat. +/// Pour la valeur par defaut de ce parametre, vous devrez creer une fonction +/// lambda qui tri la liste en ordre croissant. +/// +/// +/// Bien entendu, l'identifiant doit toujours correspondre au nom et prenom de +/// l'etudiant. +/// On considere la liste deja triee +/// +public void AddSorted(Tuple elt, Predicate p) {} + + +/// +/// Fonction d'ajout trie permettant de trier les identifiants dans l'ordre croissant +/// +// +/// On considere la liste deja triee +/// +public void AddSorted(Tuple elt) {} +``` + +# Conclusion + +Voilà ! C'était assez rapide, mais simplement un rappel quant à l'utilisation de +l'interface `IEnumerable`. diff --git a/content/sup/tp/S2/indexer.md b/content/sup/tp/S2/indexer.md new file mode 100644 index 0000000..0cab70c --- /dev/null +++ b/content/sup/tp/S2/indexer.md @@ -0,0 +1,73 @@ +--- +title: "Indexer" +date: 2023-06-21T12:00:00+02:00 +author: "Ilan Mayeux" +--- + +# Indexeur + +Les Indexeurs sont des méthodes utiles qui permettent de réutiliser la syntaxe des listes, tableaux et dictionnaires +pour des classes customisées. Elles se comportent similairement aux Propriétés + +Ce cours TP vous permettra d'acquérir ce savoir en un temps relativement court. + +Cf : [Documentation Microsoft](https://docs.microsoft.com/fr-fr/dotnet/csharp/programming-guide/indexers/) (RTFM) + +## Indexer.cs + +```csharp +/// +/// Ecrire une classe Indexer qui prend comme attributs privés un dictionnaire +/// _dicoSI avec une clé de type string et une valeur de type int, +/// un autre _dicoII de clé int et de valeur string. +/// et un _tree de type MyTree, classe définit plus bas +/// +public class Indexer {} +public class MyTree +{ + public object Key; + public MyTree Left; + public MyTree Right; +} +``` +```csharp +/// +/// Ecrire un indexeur pour le dictionnaire _dicoSI avec un getter +/// qui renvoie la valeur du dictionnaire +/// et un setter qui la met à jour +/// +public int this[string key] +``` + +```csharp +/// +/// Ecrire un indexeur pour le dictionnaire _dicoII avec un getter qui renvoie et +/// multiplie la valeur du dictionnaire par 86 puis ajoute 39 +/// et un setter qui la met à jour en effectuant l'opération inverse sur la valeur +/// du nombre entrant +/// +public int this[int key] +``` + +```csharp +/// +/// Ecrire un indexeur qui renvoie le n ième noeud de l'abre en parcours largeur. +/// S'il n'existe pas, une IndexOutOfRangeException est levée. +/// +public MyTree this[int n] +``` + +```csharp +/// +/// Ecrire un indexeur qui renvoie le premier noeud de l'abre en parcours largeur +/// qui a une clé égale à celle en paramètre. +/// Si aucun noued n'est trouvé, l'indexeur renvoie null., +/// +public MyTree? this[object key] +``` + +## Fin + +Merci d'avoir suivi ce court TP sur les indexeurs. +N'hésitez pas à remonter tout problème sur le serveur discord +de B2B. \ No newline at end of file diff --git a/content/sup/tp/S2/interfaces.md b/content/sup/tp/S2/interfaces.md new file mode 100644 index 0000000..59b1659 --- /dev/null +++ b/content/sup/tp/S2/interfaces.md @@ -0,0 +1,273 @@ +--- +title: "Marokanar" +description: "Maitriser les interfaces" +date: 2024-03-05T22:33:55+01:00 +author: ["Julie"] +--- + +# Introduction + +La *Marokanar* est le lieu réunissant le plus grand nombre de canards skaters au +monde ! Cette nuit, un concours est prévu, et l'heure est aux prédictions. + +Aide nous à simuler cette compétition afin de trouver quel canard va être le +gagnant ! + +Voici l'architecture que va suivre le TP : + +``` +. +├── README.md +├── Marokanar/ +│ ├── Marokanar.csproj +│   ├── Skate.cs +│   └── Canards/ +│   ├── ICanard.cs +│   ├── Caneton.cs +│   ├── CanardAdulte.cs +│   ├── Canaradormi.cs +│   ├── Canarcdc.cs +│   └── VieuxCrouton.cs +└── Marokanar.sln +``` + +# Faire un Skate + +Pour simuler une compétition de skate, il nous faut tout d'abord des skate. + +Voici les propriétés de ce fameux skate : + +```cs +public int Speed { get; set; } +``` + +## Constructeur + +Ajoute un constructeur à la classe `Skate`. + +```cs +public Skate(int speed) { } +``` + +## De la copie + +Un skate, ça peut se copier. Écris un constructeur qui initialise la vitesse +comme étant la même que le skate en paramètre. + +```cs +public Skate(Skate s) { } +``` + +## Combinaison de skates + +La légende raconte que l'un des meilleur skaters au monde avait conçu son skate +en combinant 2 existants. + +Écrit une méthode qui permet d'additionner 2 skates ensemble, et d'en renvoyer +un nouveau. + +La vitesse de ce nouveau skate correspond à la somme des skates précédents. + +```cs +public static Skate operator+(Skate skate1, Skate skate2) { } +``` + +# Nos canards + +Des skates c'est bien, mais il nous faut des canards pour les utiliser. + +Écris une interface `ICanard.cs`, avec les méthodes suivantes : + +```cs +// Fait quack tout seul +public string Quack(); +// Fait quack en considérant le canard en face +public string Quack(ICanard canard); +``` + +## Des petits canetons + +Il y a plein de canetons qui sont venus regarder la compétition. Étant trop +jeunes pour participer, ils restent sur le côté et font "Quack !" dans leur coin. +Quand ils sont en face de quelqu'un, un seul petit "quack" peut se faire entendre. + +```cs +public string Quack() { } +public string Quack(ICanard canard) { } +``` + +## Des canards adultes + +Écris une classe *abstraite* `CanardAdulte` qui implémente `ICanard` (hérite de +`ICanard`). +Cette classe va représenter tous les canards pouvant participer à la compétition. + +Voici les propriétés de ces fameux canards : + +```cs +public string Nom { get; set; } +public int Argent { get; } +public int Position { get; } +public Skate Skate { get; set; } +``` + +### C'est leur de la compet ! + +Tous les canards adultes peuvent faire du skate, ils ont donc besoin d'une +méthode pour se déplacer. Voici le prototype de cette méthode, elle sera +implémentée dans les classes filles. + +```cs +public abstract void Move(); +``` + +### Des paris, plein de paris + +Écris une méthode qui retire le montant de l'argent du canard. Renvoie `false` +si le canard n'a pas assez d'argent, sinon `true`. + +```cs +public bool Parier(int montant) { } +``` + +### Et c'est gagné ! + +Écris une méthode qui met à jour l'argent du canard et renvoie la réaction du +canard à l'annonce des gagnants. + +Si le montant en paramètre vaut 0, cela indique qu'il a perdu, et qu'il ne +récupère pas l'argent qu'il a parié. + +Dans le cas contraire, il faut ajouter ce montant à l'argent du canard. + +Pour ce qui est de la réaction, un canard a tendances à dire "Youpi!" après +avoir gagné, et "Mince..." quand il a perdu. + +```cs +public virtual string RecupererPari(int montantGagne) { } +``` + +## Un canard en forme ! + +L'un des premiers groupe de canards à la compétition sont très en forme ! +Sûrement car ils ont très bien dormi. + +Écris une classe `Canaradormi` qui hérite de `CanardAdulte`. + +### Constructeur + +Écris un constructeur pour ce canard très en forme. La position du canard +démarre toujours à 0. + +```cs +public Canaradormi(string nom, int argent, Skate skate) { } +``` + +### Enfin un canard qui skate ! + +Un `Canaradormi` est prêt pour faire du skate. Implémente la méthode abstraite +`Move` décrite dans le `CanardAdulte`. Étant en forme, à chaque déplacement, +la vitesse du skate actuel va être ajoutée à la position du canard. + +```cs +public override void Move() { } +``` + +### Vraiment très en forme + +Un *Canaradormi*, c'est toujours très enthousiaste. Ils font toujours "QUACK!", +peut-importe qu'ils soient seuls ou en face de quelqu'un. + +```cs +public string Quack() { } +public string Quack(ICanard canard) { } +``` + +## Canarcdc + +Un autre groupe de canard fait son entrée : les `Canarcdc`. Malheureusement, +ils ont passé toute la nuit à travailler pour leurs sups, et ne sont donc pas +très en forme. + +Écris une classe `Canarcdc` qui hérite de `CanardAdulte`. + +### Constructeur + +Écris un constructeur pour ces canards fatigués. La position du canard +démarre toujours à 0. + +```cs +public Canarcdc(string nom, int argent, Skate skate) { } +``` + +### Et mantenant il faut faire du skate + +Implémente la méthode abstraite `Move` décrite dans le `CanardAdulte`. +Étant très fatigués, à chaque déplacement, c'est seulement la `vitesse du skate - 2` +qui va être ajoutée à la position du canard. + +```cs +public override void Move() { } +``` + +### Des quacks fatigués + +Un *Canardcdc* répond un "Quack" poli à tous les gens qu'il croise. Quand +il est seul, un "quack..." soupiré peut se faire entendre. + +```cs +public string Quack() { } +public string Quack(ICanard canard) { } +``` + +## Et la limite d'age ? + +Étonnament, un groupe de Senior vient d'arriver à la compétition. Ils ont l'air +de vouloir participer à la compétition, mais ont très vite agacé tous les +participants, et obtenu le surnom de *Vieux Crouton*. + +Écris une classe `VieuxCrouton` qui hérite de `CanardAdulte`. + +### Constructeur + +Écris un constructeur pour ces canards. La position du canard +démarre toujours à 0. + +```cs +public VieuxCrouton(string nom, int argent, Skate skate) { } +``` + +### Et mantenant il faut faire du skate + +Implémente la méthode abstraite `Move` décrite dans le `CanardAdulte`. +À chaque déplacement, ces vieux crontons avance uniquement de la moitié de la +vitesse du skate. + +```cs +public override void Move() { } +``` + +### Un air supérieur dès les salutations + +Les vieux croutons ne sont polis qu'entre eux. Un "Quack." poli peut se faire +entendre entre croutons. En revanche, s'ils s'adressent à un autre canard, +aucun d'eux ne dira rien. Quand ils sont seuls, ils ne font que juger au loin, +pas de quack là non plus ! + +```cs +public string Quack() { } +public string Quack(ICanard canard) { } +``` + +### Perdre un pari ? Impossible ! + +Un vieux crouton, ça n'aime pas perdre. Écris la fonction `RecupererPari` +des croutons. Elle fonctionne exactement pareil qu'avant à *un* détail prêt : +dans le cas où le canard perd, un "C'est un complot !" peut se faire entendre +dans la salle. + +> Il faut utiliser le mot clé `base` dans cette méthode. + +```cs +public override string RecupererPari(int montant) { } +``` diff --git a/content/sup/tp/_index.md b/content/sup/tp/_index.md index edf7bd6..3d72c83 100644 --- a/content/sup/tp/_index.md +++ b/content/sup/tp/_index.md @@ -1,10 +1,10 @@ --- weight: 999 title: "TP" -description: "" +description: "Tp de programmation made in B2B" icon: "folder" date: "2024-08-20T12:30:18+02:00" lastmod: "2024-08-20T12:30:18+02:00" -draft: true +draft: false toc: true --- \ No newline at end of file diff --git a/themes/lotusdocs/data/landing.yaml b/themes/lotusdocs/data/landing.yaml index 480ab57..a9477ab 100644 --- a/themes/lotusdocs/data/landing.yaml +++ b/themes/lotusdocs/data/landing.yaml @@ -89,7 +89,7 @@ featureGrid: - title: Disponibilité sur Discord icon: forum - description: "Réponses aux questions en temps réel via notre **[serveur Discord dédié](discord.com/PtXWatnH4j)** pour un soutien immédiat." + description: "Réponses aux questions en temps réel via notre **[serveur Discord dédié](https://discord.com/PtXWatnH4j)** pour un soutien immédiat." - title: Accessibilité icon: public diff --git a/themes/lotusdocs/layouts/404.html b/themes/lotusdocs/layouts/404.html index 3333779..f18f418 100644 --- a/themes/lotusdocs/layouts/404.html +++ b/themes/lotusdocs/layouts/404.html @@ -1,12 +1,17 @@ {{ define "main"}} -
+
-

Page not found :(

-

The page you are looking for doesn't exist or has been moved.

+

Oups :(

+

La page est encore en travaux ! Revenez plus tard

-
- home + + + under construction
{{ end }} \ No newline at end of file diff --git a/themes/lotusdocs/layouts/cyb/_markup/render-codeblock-mermaid.html b/themes/lotusdocs/layouts/cyb/_markup/render-codeblock-mermaid.html new file mode 100644 index 0000000..3844cd7 --- /dev/null +++ b/themes/lotusdocs/layouts/cyb/_markup/render-codeblock-mermaid.html @@ -0,0 +1,4 @@ +
+    {{- .Inner }}
+
+{{ .Page.Store.Set "hasMermaid" true }} \ No newline at end of file diff --git a/themes/lotusdocs/layouts/cyb/_markup/render-codeblock.html b/themes/lotusdocs/layouts/cyb/_markup/render-codeblock.html new file mode 100644 index 0000000..4328638 --- /dev/null +++ b/themes/lotusdocs/layouts/cyb/_markup/render-codeblock.html @@ -0,0 +1,85 @@ + +{{ if eq .Page.Site.Params.docs.prism true }} + {{- $attributes := .Attributes }} + {{- $ordinal := .Ordinal }} + + + {{ $innerRemoveLB := replaceRE "\r\n?|\n" "" .Inner | string }} + {{ $innerHash := substr (sha1 (printf "%s%s" $innerRemoveLB $ordinal)) 0 7 }} + + {{- $classes := slice (printf "language-%s" .Type) .Attributes.class }} + + + {{- $options := .Options }} + {{ $optionslist := newScratch }} + {{ range $k, $v := $options }} + {{ $optionslist.Add "options" (printf " %s" $k) }} + {{ end }} + {{ $optionsclasslist := $optionslist.Get "options" }} + + + {{- if isset .Options "hl_lines" }} + {{ $lines := .Options.hl_lines }} + + {{ $offset := 0 }} + {{- if isset .Options "linenostart" }} + {{ $offset = .Options.linenostart }} + {{ else }} + {{ $offset = 1 }} + {{ end }} + + {{ $data := newScratch }} + {{ range $value := $lines }} + {{ $value = uniq $value }} + {{ if lt (len $value) 2 }} + {{ $value = slice (add $offset (index $value 0)) }} + {{ else }} + {{ $value = slice (delimit (slice (add $offset (index $value 0)) (add $offset (index $value 1))) "-") }} + {{ end }} + {{ $data.Add "lines" $value }} + {{ end }} + {{ $lines = delimit ($data.Get "lines") "," }} + + {{- $attributes = merge $attributes (dict "data-line" $lines) }} + + + {{- if and (isset .Options "linenos") (ne .Options.linenos false) }} + {{- $attributes = merge $attributes (dict "data-line-offset" (string $offset)) }} + {{ else }} + {{- $attributes = merge $attributes (dict "data-line-offset" (string (sub $offset 1))) }} + {{ end }} + + {{ end -}} + + + {{- if and (isset .Options "linenos") (ne .Options.linenos false) }} + {{- $classes = $classes | append "line-numbers" }} + {{ end -}} + + + {{- if isset .Options "linenostart" }} + {{- $attributes = merge $attributes (dict "data-start" (string .Options.linenostart)) }} + {{ end -}} + + + {{- if and (isset .Options "anchorlinenos") (ne .Options.anchorlinenos false) }} + {{- $classes = $classes | append "linkable-line-numbers" }} + {{ end -}} + + {{- $attributes = merge $attributes (dict "class" (delimit $classes " ")) }} + +
+
+  
+  {{- .Inner -}}
+  
+  
+
+{{ else }} + {{ $result := transform.HighlightCodeBlock . }} + {{ $result.Wrapped }} +{{ end }} \ No newline at end of file diff --git a/themes/lotusdocs/layouts/cyb/_markup/render-heading.html b/themes/lotusdocs/layouts/cyb/_markup/render-heading.html new file mode 100644 index 0000000..e4f1a21 --- /dev/null +++ b/themes/lotusdocs/layouts/cyb/_markup/render-heading.html @@ -0,0 +1 @@ +{{ .Text | safeHTML }} \ No newline at end of file diff --git a/themes/lotusdocs/layouts/cyb/_markup/render-image.html b/themes/lotusdocs/layouts/cyb/_markup/render-image.html new file mode 100644 index 0000000..8f46d6b --- /dev/null +++ b/themes/lotusdocs/layouts/cyb/_markup/render-image.html @@ -0,0 +1,33 @@ +{{ $dest := .Destination }} +{{ $text := .PlainText }} +{{ $url := urls.Parse $dest }} + +{{ $image := newScratch }} +{{ with $url.Scheme }} + {{ $image.Set "resource" (resources.GetRemote $dest) }} +{{ else }} + {{ $image.Set "resource" (resources.Get $dest) }} +{{ end }} + +{{ if .Title }} +
+ {{ with ($image.Get "resource") }} + {{ if eq .MediaType.SubType "svg" }} + {{ .Content | safeHTML }} + {{ else }} + {{ $text }} + {{ end }} + {{ else }} + {{ $text }} + {{ end }} +
{{ .Title | markdownify }}
+
+{{ else }} + {{ with ($image.Get "resource") }} + {{ if eq .MediaType.SubType "svg" }} + {{ .Content | safeHTML }} + {{ else }} + {{ $text }} + {{ end }} + {{ end }} +{{ end }} \ No newline at end of file diff --git a/themes/lotusdocs/layouts/cyb/_markup/render-link.html b/themes/lotusdocs/layouts/cyb/_markup/render-link.html new file mode 100644 index 0000000..8737c91 --- /dev/null +++ b/themes/lotusdocs/layouts/cyb/_markup/render-link.html @@ -0,0 +1,262 @@ +{{- /* Last modified: 2023-09-04T09:23:04-07:00 */}} + +{{- /* +Copyright 2023 Veriphor LLC + +Licensed under the Apache License, Version 2.0 (the "License"); you may not +use this file except in compliance with the License. You may obtain a copy of +the License at + +https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +License for the specific language governing permissions and limitations under +the License. +*/}} + +{{- /* +This render hook resolves internal destinations by looking for a matching: + + 1. Content page + 2. Page resource (a file in the current page bundle) + 3. Section resource (a file in the current section) + 4. Global resource (a file in the assets directory) + +It skips the section resource lookup if the current page is a leaf bundle. + +External destinations are not modified. + +You must place global resources in the assets directory. If you have placed +your resources in the static directory, and you are unable or unwilling to move +them, you must mount the static directory to the assets directory by including +both of these entries in your site configuration: + + [[module.mounts]] + source = 'assets' + target = 'assets' + + [[module.mounts]] + source = 'static' + target = 'assets' + +By default, if this render hook is unable to resolve a destination, including a +fragment if present, it passes the destination through without modification. To +emit a warning or error, set the error level in your site configuration: + + [params.render_hooks.link] + errorLevel = 'warning' # ignore (default), warning, or error (fails the build) + +When you set the error level to warning, and you are in a development +environment, you can visually highlight broken internal links: + + [params.render_hooks.link] + errorLevel = 'warning' # ignore (default), warning, or error (fails the build) + highlightBroken = true # true or false (default) + +This will add a "broken" class to anchor elements with invalid src attributes. +Add a rule to your CSS targeting the broken links: + + a.broken { + background: #ff0; + border: 2px solid #f00; + padding: 0.1em 0.2em; + } + +This render hook may be unable to resolve destinations created with the ref and +relref shortcodes. Unless you set the error level to ignore you should not use +either of these shortcodes in conjunction with this render hook. + +@context {string} Destination The link destination. +@context {page} Page A reference to the page containing the link. +@context {string} PlainText The link description as plain text. +@context {string} Text The link description. +@context {string} Title The link title. + +@returns {template.html} +*/}} + +{{- /* Initialize. */}} +{{- $renderHookName := "link" }} + +{{- /* Verify minimum required version. */}} +{{- $minHugoVersion := "0.114.0" }} +{{- if lt hugo.Version $minHugoVersion }} + {{- errorf "The %q render hook requires Hugo v%s or later." $renderHookName $minHugoVersion }} +{{- end }} + +{{- /* Error level when unable to resolve destination: ignore, warning, or error. */}} +{{- $errorLevel := or site.Params.render_hooks.link.errorLevel "ignore" | lower }} + +{{- /* If true, adds "broken" class to broken links. Applicable in development environment when errorLevel is warning. */}} +{{- $highlightBrokenLinks := or site.Params.render_hooks.link.highlightBroken false }} + +{{- /* Validate error level. */}} +{{- if not (in (slice "ignore" "warning" "error") $errorLevel) }} + {{- errorf "The %q render hook is misconfigured. The errorLevel %q is invalid. Please check your site configuration." $renderHookName $errorLevel }} +{{- end }} + +{{- /* Determine content path for warning and error messages. */}} +{{- $contentPath := "" }} +{{- with .Page.File }} + {{- $contentPath = .Path }} +{{- else }} + {{- $contentPath = .Path }} +{{- end }} + +{{- /* Parse destination. */}} +{{- $u := urls.Parse .Destination }} + +{{- /* Set common message. */}} +{{- $msg := printf "The %q render hook was unable to resolve the destination %q in %s" $renderHookName $u.String $contentPath }} + +{{- /* Set attributes for anchor element. */}} +{{- $attrs := dict "href" $u.String }} +{{- if $u.IsAbs }} + {{- /* Destination is a remote resource. */}} + {{- with .Page.Site.Params.docs.extLinkNewTab | default true }} + {{- $attrs = merge $attrs (dict "rel" "external" "target" "_blank") }} + {{- else }} + {{- $attrs = merge $attrs (dict "rel" "external") }} + {{- end -}} +{{- else }} + {{- with $u.Path }} + {{- with $p := or ($.Page.GetPage .) ($.Page.GetPage (strings.TrimRight "/" .)) }} + {{- /* Destination is a page. */}} + {{- $href := .RelPermalink }} + {{- $tooltipDelay := dict "show" 550 "hide" 300 | jsonify | htmlEscape }} + {{- $pathDesc := .Description }} + {{- $pathTitle := .Title }} + {{- $pathParentSection := .Parent.Title | upper }} + {{- $pathHTML := printf "

%s

%s
%s
" $href $pathParentSection $pathTitle $pathDesc }} + {{- with $u.RawQuery }} + {{- $href = printf "%s?%s" $href . }} + {{- end }} + {{- with $u.Fragment }} + {{- $ctx := dict + "contentPath" $contentPath + "errorLevel" $errorLevel + "page" $p + "parsedURL" $u + "renderHookName" $renderHookName + }} + {{- partial "inline/h-rh-l/validate-fragment.html" $ctx }} + {{- $href = printf "%s#%s" $href . }} + {{- end }} + {{- if eq .Page.Site.Params.docs.intLinkTooltip true }} + {{- $attrs = dict "href" $href "data-bs-toggle" "tooltip" "data-bs-delay" $tooltipDelay "data-bs-html" "true" "data-bs-title" $pathHTML }} + {{- else }} + {{- $attrs = dict "href" $href }} + {{- end -}} + {{- else }} + {{- with $.Page.Resources.Get $u.Path }} + {{- /* Destination is a page resource; drop query and fragment. */}} + {{- $attrs = dict "href" .RelPermalink }} + {{- else }} + {{- with (and (ne $.Page.BundleType "leaf") ($.Page.CurrentSection.Resources.Get $u.Path)) }} + {{- /* Destination is a section resource, and current page is not a leaf bundle. */}} + {{- $attrs = dict "href" .RelPermalink }} + {{- else }} + {{- with resources.Get $u.Path }} + {{- /* Destination is a global resource; drop query and fragment. */}} + {{- $attrs = dict "href" .RelPermalink }} + {{- else }} + {{- if eq $errorLevel "warning" }} + {{- warnf $msg }} + {{- if and $highlightBrokenLinks (eq hugo.Environment "development") }} + {{- $attrs = merge $attrs (dict "class" "broken") }} + {{- end }} + {{- else if eq $errorLevel "error" }} + {{- errorf $msg }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- else }} + {{- with $u.Fragment }} + {{- /* Destination is on the same page; prepend relative permalink. */}} + {{- $ctx := dict + "contentPath" $contentPath + "errorLevel" $errorLevel + "page" $.Page + "parsedURL" $u + "renderHookName" $renderHookName + }} + {{- partial "inline/h-rh-l/validate-fragment.html" $ctx }} + {{- $attrs = dict "href" (printf "%s#%s" $.Page.RelPermalink .) }} + {{- else }} + {{- if eq $errorLevel "warning" }} + {{- warnf $msg }} + {{- if and $highlightBrokenLinks (eq hugo.Environment "development") }} + {{- $attrs = merge $attrs (dict "class" "broken") }} + {{- end }} + {{- else if eq $errorLevel "error" }} + {{- errorf $msg }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +{{- with .Title }} + {{- $attrs = merge $attrs (dict "title" .) }} +{{- end -}} + +{{- /* Render anchor element. */ -}} +{{ .Text | safeHTML }}{{- if $u.IsAbs }}{{ with .Page.Site.Params.docs.extLinkNewTab | default true }}{{ end }}{{ end }} + +{{- define "partials/inline/h-rh-l/validate-fragment.html" }} + {{- /* + Validates the fragment portion of a link destination. + + @context {string} contentPath The page containing the link. + @context {srting} errorLevel The error level when unable to resolve destination; ignore (default), warning, or error. + @context {page} page The page corresponding to the link destination + @context {struct} parsedURL The link destination parsed by urls.Parse. + @context {string} renderHookName The name of the render hook. + */}} + + {{- /* Initialize. */}} + {{- $contentPath := .contentPath }} + {{- $errorLevel := .errorLevel }} + {{- $p := .page }} + {{- $u := .parsedURL }} + {{- $renderHookName := .renderHookName }} + + {{- /* Validate. */}} + {{- with $u.Fragment }} + {{- if $p.Fragments.Identifiers.Contains . }} + {{- if gt ($p.Fragments.Identifiers.Count .) 1 }} + {{- $msg := printf "The %q render hook detected duplicate heading IDs %q in %s" $renderHookName . $contentPath }} + {{- if eq $errorLevel "warning" }} + {{- warnf $msg }} + {{- else if eq $errorLevel "error" }} + {{- errorf $msg }} + {{- end }} + {{- end }} + {{- else }} + {{- /* Determine target path for warning and error message. */}} + {{- $targetPath := "" }} + {{- with $p.File }} + {{- $targetPath = .Path }} + {{- else }} + {{- $targetPath = .Path }} + {{- end }} + {{- /* Set common message. */}} + {{- $msg := printf "The %q render hook was unable to find heading ID %q in %s. See %s" $renderHookName . $targetPath $contentPath }} + {{- if eq $targetPath $contentPath }} + {{- $msg = printf "The %q render hook was unable to find heading ID %q in %s" $renderHookName . $targetPath }} + {{- end }} + {{- /* Throw warning or error. */}} + {{- if eq $errorLevel "warning" }} + {{- warnf $msg }} + {{- else if eq $errorLevel "error" }} + {{- errorf $msg }} + {{- end }} + {{- end }} + {{- end }} +{{- end -}} \ No newline at end of file diff --git a/themes/lotusdocs/layouts/cyb/baseof.html b/themes/lotusdocs/layouts/cyb/baseof.html new file mode 100644 index 0000000..53ced3d --- /dev/null +++ b/themes/lotusdocs/layouts/cyb/baseof.html @@ -0,0 +1,124 @@ + +{{ $.Scratch.Delete "social_list" }} +{{ $.Scratch.Set "pathName" (printf "%s" (.Site.Params.docs.pathName | default "docs")) }} + +{{ $social_params := slice "github" "twitter" "instagram" "rss" "discord" "twitch"}} +{{ range $social_params }} + {{ if isset site.Params.social . }} + {{ $.Scratch.Add "social_list" (slice .) }} + {{ end }} +{{ end }} + + {{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "head.html") . -}} + +
+
+ {{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "sidebar.html") . -}} + +
+ {{ if .Site.IsMultiLingual }} + {{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "top-header.html") . -}} + {{ else }} + {{- partialCached (printf "%s/%s" ($.Scratch.Get "pathName") "top-header.html") . -}} + {{ end }} +
+
+ {{ $currentPage := . -}} + {{ if site.Params.docs.breadcrumbs | default true }} +
+ {{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "breadcrumbs.html") . -}} +
+ {{ end }} +
+ {{ if site.Params.docs.toc | default true }} +
") }}{{ else }}visually-hidden{{ end }} {{ if site.Params.docs.toc | default true }}{{ else }}visually-hidden{{ end }} d-xl-block"> + {{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "toc.html") . -}} +
+ {{ end }} + {{ if site.Params.docs.tocMobile | default true }} +
") }}{{ else }}visually-hidden{{ end }} {{ if site.Params.docs.tocMobile | default true }}{{ else }}visually-hidden{{ end }} d-print-none d-xl-none"> + + {{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "toc-mobile.html") . -}} +
+ {{ end -}} +
") }}col-xl-9{{else}}{{end}}{{ else }}{{ end }}{{ end }} mt-0"> +
+ {{ if site.Params.docs.titleIcon | default false }} + {{- .Params.icon | default "article" }} + {{ end }} +

+ {{ $currentPage.Title }} + {{ if .Draft }} + DRAFT + {{ end }} +

+ +
+ + {{ if site.Params.docs.descriptions | default false }} +

{{ $currentPage.Description | markdownify }}

+ {{ end }} + + +

+ {{ if .Date }} + {{ .Date | time.Format ":date_medium" }} + {{ end }} + + {{ if and .Date (isset .Params "author") }} +  ·  + {{ end }} + + {{ if isset .Params "author" }} + {{ with .Params.author }} + {{ . }} + {{ end }} + {{ end }} + +

+
+ {{ block "main" . }}{{ end }} +
+
+ {{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "doc-nav.html") . -}} +
+
+
+
+
+ {{- partialCached (printf "%s/%s" ($.Scratch.Get "pathName") "footer.html") . -}} + +
+
+
+ + {{ if site.Params.docs.backToTop | default true }} + + + + {{ end }} + + + {{ if eq .Site.Params.docs.darkMode true -}} + {{ $darkModeSwitch := resources.Get (printf "/%s/%s" ($.Scratch.Get "pathName") "js/darkmode-switch.js") | js.Build | minify }} + + {{ end -}} + + {{- partialCached (printf "%s/%s" ($.Scratch.Get "pathName") "footer/footer-scripts.html") . -}} + + + {{ if and (.Site.Params.docsearch.appID) (.Site.Params.docsearch.apiKey) -}} + {{- partialCached (printf "%s/%s" ($.Scratch.Get "pathName") "footer/docsearch.html") . -}} + {{ end }} + + + {{ if or (not (isset .Site.Params.flexsearch "enabled")) (eq .Site.Params.flexsearch.enabled true) -}} + {{ if and (.Site.Params.docsearch.appID) (.Site.Params.docsearch.apiKey) -}} + {{ else }} + {{- partialCached (printf "%s/%s" ($.Scratch.Get "pathName") "footer/flexsearch.html") . -}} + {{ end }} + {{ end }} + + \ No newline at end of file diff --git a/themes/lotusdocs/layouts/cyb/list.html b/themes/lotusdocs/layouts/cyb/list.html new file mode 100644 index 0000000..82ceb34 --- /dev/null +++ b/themes/lotusdocs/layouts/cyb/list.html @@ -0,0 +1,56 @@ +{{ define "main" }} + + + +
+ {{ range .Pages.ByWeight }} +
+ {{ $redifUrl := .Params.redif_url }} + {{ $coverImageUrl := "" }} + {{ if $redifUrl }} + {{ $videoId := (replaceRE `.*(?:v=|youtu\.be/)([^&]+).*` "$1" $redifUrl) }} + {{ $coverImageUrl = printf "https://img.youtube.com/vi/%s/maxresdefault.jpg" $videoId }} + {{ end }} + + + {{ $hasRessource := .Params.ressource }} + + +
+ + {{- .Params.icon | default "article" }} + {{ if .Draft }}DRAFT{{ end }} + {{ if .IsSection }}folder{{ end }} + +
+

{{ .Title }}

+

{{ if $coverImageUrl }} {{ else }} {{ .Description | truncate (.Site.Params.docs.listDescTrunc | default 100) | markdownify }} {{ end }}

+
+ {{ if $redifUrl }} +
+

{{ .Title }}

+ launch +
+ {{ end }} + {{ if $hasRessource }} +
+ launch +
+ {{ end }} + +
+
+
+ + + {{ end }} +
+{{ end }} \ No newline at end of file diff --git a/themes/lotusdocs/layouts/cyb/single.html b/themes/lotusdocs/layouts/cyb/single.html new file mode 100644 index 0000000..69659d9 --- /dev/null +++ b/themes/lotusdocs/layouts/cyb/single.html @@ -0,0 +1,70 @@ +{{ define "main" }} + + {{ with .Params.redif_url }} + + {{ end }} + + {{ with .Params.ressource }} + +{{ end }} + + +
+ {{ .Content }} +
+ + {{ if and .GitInfo .Site.Params.docs.repoURL -}} + {{ partial (printf "%s/%s" ($.Scratch.Get "pathName") "gitinfo") . }} + {{ end -}} + + {{ if .Page.Store.Get "hasMermaid" }} + {{ $mermaid := resources.Get (printf "%s/%s" ($.Scratch.Get "pathName") "js/mermaid.min.js") }} + {{ if hugo.IsProduction }} + {{ $mermaid = $mermaid | fingerprint "sha384" }} + {{ end }} + + + {{ end }} + + {{ if .Site.Params.feedback.enabled | default false -}} + {{ if or (.Site.Params.plausible.dataDomain) (.Site.GoogleAnalytics) }} + {{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "footer/feedback.html") . -}} + {{ else }} + {{ errorf "Either Google Analytics or Plausible Analytics must be configured before enabling the Feedback Widget." }} + {{ end }} + {{ end -}} + +{{ end }} \ No newline at end of file diff --git a/themes/lotusdocs/layouts/ing/_markup/render-codeblock-mermaid.html b/themes/lotusdocs/layouts/ing/_markup/render-codeblock-mermaid.html new file mode 100644 index 0000000..3844cd7 --- /dev/null +++ b/themes/lotusdocs/layouts/ing/_markup/render-codeblock-mermaid.html @@ -0,0 +1,4 @@ +
+    {{- .Inner }}
+
+{{ .Page.Store.Set "hasMermaid" true }} \ No newline at end of file diff --git a/themes/lotusdocs/layouts/ing/_markup/render-codeblock.html b/themes/lotusdocs/layouts/ing/_markup/render-codeblock.html new file mode 100644 index 0000000..4328638 --- /dev/null +++ b/themes/lotusdocs/layouts/ing/_markup/render-codeblock.html @@ -0,0 +1,85 @@ + +{{ if eq .Page.Site.Params.docs.prism true }} + {{- $attributes := .Attributes }} + {{- $ordinal := .Ordinal }} + + + {{ $innerRemoveLB := replaceRE "\r\n?|\n" "" .Inner | string }} + {{ $innerHash := substr (sha1 (printf "%s%s" $innerRemoveLB $ordinal)) 0 7 }} + + {{- $classes := slice (printf "language-%s" .Type) .Attributes.class }} + + + {{- $options := .Options }} + {{ $optionslist := newScratch }} + {{ range $k, $v := $options }} + {{ $optionslist.Add "options" (printf " %s" $k) }} + {{ end }} + {{ $optionsclasslist := $optionslist.Get "options" }} + + + {{- if isset .Options "hl_lines" }} + {{ $lines := .Options.hl_lines }} + + {{ $offset := 0 }} + {{- if isset .Options "linenostart" }} + {{ $offset = .Options.linenostart }} + {{ else }} + {{ $offset = 1 }} + {{ end }} + + {{ $data := newScratch }} + {{ range $value := $lines }} + {{ $value = uniq $value }} + {{ if lt (len $value) 2 }} + {{ $value = slice (add $offset (index $value 0)) }} + {{ else }} + {{ $value = slice (delimit (slice (add $offset (index $value 0)) (add $offset (index $value 1))) "-") }} + {{ end }} + {{ $data.Add "lines" $value }} + {{ end }} + {{ $lines = delimit ($data.Get "lines") "," }} + + {{- $attributes = merge $attributes (dict "data-line" $lines) }} + + + {{- if and (isset .Options "linenos") (ne .Options.linenos false) }} + {{- $attributes = merge $attributes (dict "data-line-offset" (string $offset)) }} + {{ else }} + {{- $attributes = merge $attributes (dict "data-line-offset" (string (sub $offset 1))) }} + {{ end }} + + {{ end -}} + + + {{- if and (isset .Options "linenos") (ne .Options.linenos false) }} + {{- $classes = $classes | append "line-numbers" }} + {{ end -}} + + + {{- if isset .Options "linenostart" }} + {{- $attributes = merge $attributes (dict "data-start" (string .Options.linenostart)) }} + {{ end -}} + + + {{- if and (isset .Options "anchorlinenos") (ne .Options.anchorlinenos false) }} + {{- $classes = $classes | append "linkable-line-numbers" }} + {{ end -}} + + {{- $attributes = merge $attributes (dict "class" (delimit $classes " ")) }} + +
+
+  
+  {{- .Inner -}}
+  
+  
+
+{{ else }} + {{ $result := transform.HighlightCodeBlock . }} + {{ $result.Wrapped }} +{{ end }} \ No newline at end of file diff --git a/themes/lotusdocs/layouts/ing/_markup/render-heading.html b/themes/lotusdocs/layouts/ing/_markup/render-heading.html new file mode 100644 index 0000000..e4f1a21 --- /dev/null +++ b/themes/lotusdocs/layouts/ing/_markup/render-heading.html @@ -0,0 +1 @@ +{{ .Text | safeHTML }} \ No newline at end of file diff --git a/themes/lotusdocs/layouts/ing/_markup/render-image.html b/themes/lotusdocs/layouts/ing/_markup/render-image.html new file mode 100644 index 0000000..8f46d6b --- /dev/null +++ b/themes/lotusdocs/layouts/ing/_markup/render-image.html @@ -0,0 +1,33 @@ +{{ $dest := .Destination }} +{{ $text := .PlainText }} +{{ $url := urls.Parse $dest }} + +{{ $image := newScratch }} +{{ with $url.Scheme }} + {{ $image.Set "resource" (resources.GetRemote $dest) }} +{{ else }} + {{ $image.Set "resource" (resources.Get $dest) }} +{{ end }} + +{{ if .Title }} +
+ {{ with ($image.Get "resource") }} + {{ if eq .MediaType.SubType "svg" }} + {{ .Content | safeHTML }} + {{ else }} + {{ $text }} + {{ end }} + {{ else }} + {{ $text }} + {{ end }} +
{{ .Title | markdownify }}
+
+{{ else }} + {{ with ($image.Get "resource") }} + {{ if eq .MediaType.SubType "svg" }} + {{ .Content | safeHTML }} + {{ else }} + {{ $text }} + {{ end }} + {{ end }} +{{ end }} \ No newline at end of file diff --git a/themes/lotusdocs/layouts/ing/_markup/render-link.html b/themes/lotusdocs/layouts/ing/_markup/render-link.html new file mode 100644 index 0000000..8737c91 --- /dev/null +++ b/themes/lotusdocs/layouts/ing/_markup/render-link.html @@ -0,0 +1,262 @@ +{{- /* Last modified: 2023-09-04T09:23:04-07:00 */}} + +{{- /* +Copyright 2023 Veriphor LLC + +Licensed under the Apache License, Version 2.0 (the "License"); you may not +use this file except in compliance with the License. You may obtain a copy of +the License at + +https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +License for the specific language governing permissions and limitations under +the License. +*/}} + +{{- /* +This render hook resolves internal destinations by looking for a matching: + + 1. Content page + 2. Page resource (a file in the current page bundle) + 3. Section resource (a file in the current section) + 4. Global resource (a file in the assets directory) + +It skips the section resource lookup if the current page is a leaf bundle. + +External destinations are not modified. + +You must place global resources in the assets directory. If you have placed +your resources in the static directory, and you are unable or unwilling to move +them, you must mount the static directory to the assets directory by including +both of these entries in your site configuration: + + [[module.mounts]] + source = 'assets' + target = 'assets' + + [[module.mounts]] + source = 'static' + target = 'assets' + +By default, if this render hook is unable to resolve a destination, including a +fragment if present, it passes the destination through without modification. To +emit a warning or error, set the error level in your site configuration: + + [params.render_hooks.link] + errorLevel = 'warning' # ignore (default), warning, or error (fails the build) + +When you set the error level to warning, and you are in a development +environment, you can visually highlight broken internal links: + + [params.render_hooks.link] + errorLevel = 'warning' # ignore (default), warning, or error (fails the build) + highlightBroken = true # true or false (default) + +This will add a "broken" class to anchor elements with invalid src attributes. +Add a rule to your CSS targeting the broken links: + + a.broken { + background: #ff0; + border: 2px solid #f00; + padding: 0.1em 0.2em; + } + +This render hook may be unable to resolve destinations created with the ref and +relref shortcodes. Unless you set the error level to ignore you should not use +either of these shortcodes in conjunction with this render hook. + +@context {string} Destination The link destination. +@context {page} Page A reference to the page containing the link. +@context {string} PlainText The link description as plain text. +@context {string} Text The link description. +@context {string} Title The link title. + +@returns {template.html} +*/}} + +{{- /* Initialize. */}} +{{- $renderHookName := "link" }} + +{{- /* Verify minimum required version. */}} +{{- $minHugoVersion := "0.114.0" }} +{{- if lt hugo.Version $minHugoVersion }} + {{- errorf "The %q render hook requires Hugo v%s or later." $renderHookName $minHugoVersion }} +{{- end }} + +{{- /* Error level when unable to resolve destination: ignore, warning, or error. */}} +{{- $errorLevel := or site.Params.render_hooks.link.errorLevel "ignore" | lower }} + +{{- /* If true, adds "broken" class to broken links. Applicable in development environment when errorLevel is warning. */}} +{{- $highlightBrokenLinks := or site.Params.render_hooks.link.highlightBroken false }} + +{{- /* Validate error level. */}} +{{- if not (in (slice "ignore" "warning" "error") $errorLevel) }} + {{- errorf "The %q render hook is misconfigured. The errorLevel %q is invalid. Please check your site configuration." $renderHookName $errorLevel }} +{{- end }} + +{{- /* Determine content path for warning and error messages. */}} +{{- $contentPath := "" }} +{{- with .Page.File }} + {{- $contentPath = .Path }} +{{- else }} + {{- $contentPath = .Path }} +{{- end }} + +{{- /* Parse destination. */}} +{{- $u := urls.Parse .Destination }} + +{{- /* Set common message. */}} +{{- $msg := printf "The %q render hook was unable to resolve the destination %q in %s" $renderHookName $u.String $contentPath }} + +{{- /* Set attributes for anchor element. */}} +{{- $attrs := dict "href" $u.String }} +{{- if $u.IsAbs }} + {{- /* Destination is a remote resource. */}} + {{- with .Page.Site.Params.docs.extLinkNewTab | default true }} + {{- $attrs = merge $attrs (dict "rel" "external" "target" "_blank") }} + {{- else }} + {{- $attrs = merge $attrs (dict "rel" "external") }} + {{- end -}} +{{- else }} + {{- with $u.Path }} + {{- with $p := or ($.Page.GetPage .) ($.Page.GetPage (strings.TrimRight "/" .)) }} + {{- /* Destination is a page. */}} + {{- $href := .RelPermalink }} + {{- $tooltipDelay := dict "show" 550 "hide" 300 | jsonify | htmlEscape }} + {{- $pathDesc := .Description }} + {{- $pathTitle := .Title }} + {{- $pathParentSection := .Parent.Title | upper }} + {{- $pathHTML := printf "

%s

%s
%s
" $href $pathParentSection $pathTitle $pathDesc }} + {{- with $u.RawQuery }} + {{- $href = printf "%s?%s" $href . }} + {{- end }} + {{- with $u.Fragment }} + {{- $ctx := dict + "contentPath" $contentPath + "errorLevel" $errorLevel + "page" $p + "parsedURL" $u + "renderHookName" $renderHookName + }} + {{- partial "inline/h-rh-l/validate-fragment.html" $ctx }} + {{- $href = printf "%s#%s" $href . }} + {{- end }} + {{- if eq .Page.Site.Params.docs.intLinkTooltip true }} + {{- $attrs = dict "href" $href "data-bs-toggle" "tooltip" "data-bs-delay" $tooltipDelay "data-bs-html" "true" "data-bs-title" $pathHTML }} + {{- else }} + {{- $attrs = dict "href" $href }} + {{- end -}} + {{- else }} + {{- with $.Page.Resources.Get $u.Path }} + {{- /* Destination is a page resource; drop query and fragment. */}} + {{- $attrs = dict "href" .RelPermalink }} + {{- else }} + {{- with (and (ne $.Page.BundleType "leaf") ($.Page.CurrentSection.Resources.Get $u.Path)) }} + {{- /* Destination is a section resource, and current page is not a leaf bundle. */}} + {{- $attrs = dict "href" .RelPermalink }} + {{- else }} + {{- with resources.Get $u.Path }} + {{- /* Destination is a global resource; drop query and fragment. */}} + {{- $attrs = dict "href" .RelPermalink }} + {{- else }} + {{- if eq $errorLevel "warning" }} + {{- warnf $msg }} + {{- if and $highlightBrokenLinks (eq hugo.Environment "development") }} + {{- $attrs = merge $attrs (dict "class" "broken") }} + {{- end }} + {{- else if eq $errorLevel "error" }} + {{- errorf $msg }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- else }} + {{- with $u.Fragment }} + {{- /* Destination is on the same page; prepend relative permalink. */}} + {{- $ctx := dict + "contentPath" $contentPath + "errorLevel" $errorLevel + "page" $.Page + "parsedURL" $u + "renderHookName" $renderHookName + }} + {{- partial "inline/h-rh-l/validate-fragment.html" $ctx }} + {{- $attrs = dict "href" (printf "%s#%s" $.Page.RelPermalink .) }} + {{- else }} + {{- if eq $errorLevel "warning" }} + {{- warnf $msg }} + {{- if and $highlightBrokenLinks (eq hugo.Environment "development") }} + {{- $attrs = merge $attrs (dict "class" "broken") }} + {{- end }} + {{- else if eq $errorLevel "error" }} + {{- errorf $msg }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +{{- with .Title }} + {{- $attrs = merge $attrs (dict "title" .) }} +{{- end -}} + +{{- /* Render anchor element. */ -}} +{{ .Text | safeHTML }}{{- if $u.IsAbs }}{{ with .Page.Site.Params.docs.extLinkNewTab | default true }}{{ end }}{{ end }} + +{{- define "partials/inline/h-rh-l/validate-fragment.html" }} + {{- /* + Validates the fragment portion of a link destination. + + @context {string} contentPath The page containing the link. + @context {srting} errorLevel The error level when unable to resolve destination; ignore (default), warning, or error. + @context {page} page The page corresponding to the link destination + @context {struct} parsedURL The link destination parsed by urls.Parse. + @context {string} renderHookName The name of the render hook. + */}} + + {{- /* Initialize. */}} + {{- $contentPath := .contentPath }} + {{- $errorLevel := .errorLevel }} + {{- $p := .page }} + {{- $u := .parsedURL }} + {{- $renderHookName := .renderHookName }} + + {{- /* Validate. */}} + {{- with $u.Fragment }} + {{- if $p.Fragments.Identifiers.Contains . }} + {{- if gt ($p.Fragments.Identifiers.Count .) 1 }} + {{- $msg := printf "The %q render hook detected duplicate heading IDs %q in %s" $renderHookName . $contentPath }} + {{- if eq $errorLevel "warning" }} + {{- warnf $msg }} + {{- else if eq $errorLevel "error" }} + {{- errorf $msg }} + {{- end }} + {{- end }} + {{- else }} + {{- /* Determine target path for warning and error message. */}} + {{- $targetPath := "" }} + {{- with $p.File }} + {{- $targetPath = .Path }} + {{- else }} + {{- $targetPath = .Path }} + {{- end }} + {{- /* Set common message. */}} + {{- $msg := printf "The %q render hook was unable to find heading ID %q in %s. See %s" $renderHookName . $targetPath $contentPath }} + {{- if eq $targetPath $contentPath }} + {{- $msg = printf "The %q render hook was unable to find heading ID %q in %s" $renderHookName . $targetPath }} + {{- end }} + {{- /* Throw warning or error. */}} + {{- if eq $errorLevel "warning" }} + {{- warnf $msg }} + {{- else if eq $errorLevel "error" }} + {{- errorf $msg }} + {{- end }} + {{- end }} + {{- end }} +{{- end -}} \ No newline at end of file diff --git a/themes/lotusdocs/layouts/ing/baseof.html b/themes/lotusdocs/layouts/ing/baseof.html new file mode 100644 index 0000000..53ced3d --- /dev/null +++ b/themes/lotusdocs/layouts/ing/baseof.html @@ -0,0 +1,124 @@ + +{{ $.Scratch.Delete "social_list" }} +{{ $.Scratch.Set "pathName" (printf "%s" (.Site.Params.docs.pathName | default "docs")) }} + +{{ $social_params := slice "github" "twitter" "instagram" "rss" "discord" "twitch"}} +{{ range $social_params }} + {{ if isset site.Params.social . }} + {{ $.Scratch.Add "social_list" (slice .) }} + {{ end }} +{{ end }} + + {{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "head.html") . -}} + +
+
+ {{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "sidebar.html") . -}} + +
+ {{ if .Site.IsMultiLingual }} + {{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "top-header.html") . -}} + {{ else }} + {{- partialCached (printf "%s/%s" ($.Scratch.Get "pathName") "top-header.html") . -}} + {{ end }} +
+
+ {{ $currentPage := . -}} + {{ if site.Params.docs.breadcrumbs | default true }} +
+ {{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "breadcrumbs.html") . -}} +
+ {{ end }} +
+ {{ if site.Params.docs.toc | default true }} +
") }}{{ else }}visually-hidden{{ end }} {{ if site.Params.docs.toc | default true }}{{ else }}visually-hidden{{ end }} d-xl-block"> + {{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "toc.html") . -}} +
+ {{ end }} + {{ if site.Params.docs.tocMobile | default true }} +
") }}{{ else }}visually-hidden{{ end }} {{ if site.Params.docs.tocMobile | default true }}{{ else }}visually-hidden{{ end }} d-print-none d-xl-none"> + + {{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "toc-mobile.html") . -}} +
+ {{ end -}} +
") }}col-xl-9{{else}}{{end}}{{ else }}{{ end }}{{ end }} mt-0"> +
+ {{ if site.Params.docs.titleIcon | default false }} + {{- .Params.icon | default "article" }} + {{ end }} +

+ {{ $currentPage.Title }} + {{ if .Draft }} + DRAFT + {{ end }} +

+ +
+ + {{ if site.Params.docs.descriptions | default false }} +

{{ $currentPage.Description | markdownify }}

+ {{ end }} + + +

+ {{ if .Date }} + {{ .Date | time.Format ":date_medium" }} + {{ end }} + + {{ if and .Date (isset .Params "author") }} +  ·  + {{ end }} + + {{ if isset .Params "author" }} + {{ with .Params.author }} + {{ . }} + {{ end }} + {{ end }} + +

+
+ {{ block "main" . }}{{ end }} +
+
+ {{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "doc-nav.html") . -}} +
+
+
+
+
+ {{- partialCached (printf "%s/%s" ($.Scratch.Get "pathName") "footer.html") . -}} + +
+
+
+ + {{ if site.Params.docs.backToTop | default true }} + + + + {{ end }} + + + {{ if eq .Site.Params.docs.darkMode true -}} + {{ $darkModeSwitch := resources.Get (printf "/%s/%s" ($.Scratch.Get "pathName") "js/darkmode-switch.js") | js.Build | minify }} + + {{ end -}} + + {{- partialCached (printf "%s/%s" ($.Scratch.Get "pathName") "footer/footer-scripts.html") . -}} + + + {{ if and (.Site.Params.docsearch.appID) (.Site.Params.docsearch.apiKey) -}} + {{- partialCached (printf "%s/%s" ($.Scratch.Get "pathName") "footer/docsearch.html") . -}} + {{ end }} + + + {{ if or (not (isset .Site.Params.flexsearch "enabled")) (eq .Site.Params.flexsearch.enabled true) -}} + {{ if and (.Site.Params.docsearch.appID) (.Site.Params.docsearch.apiKey) -}} + {{ else }} + {{- partialCached (printf "%s/%s" ($.Scratch.Get "pathName") "footer/flexsearch.html") . -}} + {{ end }} + {{ end }} + + \ No newline at end of file diff --git a/themes/lotusdocs/layouts/ing/list.html b/themes/lotusdocs/layouts/ing/list.html new file mode 100644 index 0000000..82ceb34 --- /dev/null +++ b/themes/lotusdocs/layouts/ing/list.html @@ -0,0 +1,56 @@ +{{ define "main" }} + + + +
+ {{ range .Pages.ByWeight }} +
+ {{ $redifUrl := .Params.redif_url }} + {{ $coverImageUrl := "" }} + {{ if $redifUrl }} + {{ $videoId := (replaceRE `.*(?:v=|youtu\.be/)([^&]+).*` "$1" $redifUrl) }} + {{ $coverImageUrl = printf "https://img.youtube.com/vi/%s/maxresdefault.jpg" $videoId }} + {{ end }} + + + {{ $hasRessource := .Params.ressource }} + + +
+ + {{- .Params.icon | default "article" }} + {{ if .Draft }}DRAFT{{ end }} + {{ if .IsSection }}folder{{ end }} + +
+

{{ .Title }}

+

{{ if $coverImageUrl }} {{ else }} {{ .Description | truncate (.Site.Params.docs.listDescTrunc | default 100) | markdownify }} {{ end }}

+
+ {{ if $redifUrl }} +
+

{{ .Title }}

+ launch +
+ {{ end }} + {{ if $hasRessource }} +
+ launch +
+ {{ end }} + +
+
+
+ + + {{ end }} +
+{{ end }} \ No newline at end of file diff --git a/themes/lotusdocs/layouts/ing/single.html b/themes/lotusdocs/layouts/ing/single.html new file mode 100644 index 0000000..69659d9 --- /dev/null +++ b/themes/lotusdocs/layouts/ing/single.html @@ -0,0 +1,70 @@ +{{ define "main" }} + + {{ with .Params.redif_url }} + + {{ end }} + + {{ with .Params.ressource }} + +{{ end }} + + +
+ {{ .Content }} +
+ + {{ if and .GitInfo .Site.Params.docs.repoURL -}} + {{ partial (printf "%s/%s" ($.Scratch.Get "pathName") "gitinfo") . }} + {{ end -}} + + {{ if .Page.Store.Get "hasMermaid" }} + {{ $mermaid := resources.Get (printf "%s/%s" ($.Scratch.Get "pathName") "js/mermaid.min.js") }} + {{ if hugo.IsProduction }} + {{ $mermaid = $mermaid | fingerprint "sha384" }} + {{ end }} + + + {{ end }} + + {{ if .Site.Params.feedback.enabled | default false -}} + {{ if or (.Site.Params.plausible.dataDomain) (.Site.GoogleAnalytics) }} + {{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "footer/feedback.html") . -}} + {{ else }} + {{ errorf "Either Google Analytics or Plausible Analytics must be configured before enabling the Feedback Widget." }} + {{ end }} + {{ end -}} + +{{ end }} \ No newline at end of file diff --git a/themes/lotusdocs/layouts/partials/landing/hero.html b/themes/lotusdocs/layouts/partials/landing/hero.html index 666f7cd..242029c 100644 --- a/themes/lotusdocs/layouts/partials/landing/hero.html +++ b/themes/lotusdocs/layouts/partials/landing/hero.html @@ -24,6 +24,19 @@ } {{ end }} + + +