diff --git a/bp_tree.h b/bp_tree.h
index 9190756da8b4caa074657e62510e83be5a8d84eb..085998876e70111bd4e6c9b027825702eff741c1 100644
--- a/bp_tree.h
+++ b/bp_tree.h
@@ -10,7 +10,7 @@
 
 typedef struct date {
     uint8_t day;
-    uint8_t month; // 1 = January, 12 = December
+    uint8_t month; // 1 = January, 12 = December, 0 = Error
     uint8_t year;  // value stored is year - 1900
 } date;
 
@@ -37,10 +37,26 @@ typedef struct node {
  */
 void bp_print(node *root, int depth);
 
+/**
+ * @brief Factored way to print a single entry
+ *
+ * @param person entry to print
+ */
 void bp_print_entry(entry person);
 
+/**
+ * @brief Prints every entries in the tree
+ *
+ * @param tree Tree to look into
+ */
 void bp_print_everything(node *tree);
 
+/**
+ * @brief Search an entry from a phone number
+ *
+ * @param tree Tree to look into
+ * @param phone search parameter
+ */
 void bp_search(node *tree, char phone[11]);
 
 /**
diff --git a/hash.h b/hash.h
index 6496822328a20983758865e069bf85fab28f11f7..6f49ec1574340606f0ae7d9cbc622b4791d7e91c 100644
--- a/hash.h
+++ b/hash.h
@@ -4,5 +4,11 @@
 #include <stdint.h>
 #include <stdio.h>
 
+/**
+ * @brief Generate a 64-bits hash from a string
+ *
+ * @param string In this project, send the phone number
+ * @return uint64_t key
+ */
 uint64_t generate_key(char *string);
 #endif
\ No newline at end of file
diff --git a/main.c b/main.c
index 4a4220c64afe124100e4b418723bbc91c9baef87..845cb114d5c4281cbabc03b5999eeb59d4cbefe0 100644
--- a/main.c
+++ b/main.c
@@ -87,14 +87,14 @@ int main() {
             test.year = val - 1900;
 
             person.birth = test;
-            /*
+
             printf("Est-ce valide ? ('y' pour oui)\n");
             bp_print_entry(person);
 
-            scanf("%c", &select);
-            if (select != 'y') {
+            scanf("%s", select);
+            if (select[0] != 'y') {
                 goto START;
-            }*/
+            }
 
             tree = bp_insert_val(tree, person);
             break;
diff --git a/showcase/makefile b/showcase/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..959275c392e111ca5fe5d389ecc160962a60b84d
--- /dev/null
+++ b/showcase/makefile
@@ -0,0 +1,13 @@
+CC=gcc
+FLAGS= -Werror
+CFLAGS= -g -std=c99 
+LDFLAGS= -fsanitize=address -fsanitize=leak
+
+exe: showcase
+	./$^
+
+showcase: showcase.o
+	$(CC) $^ -o $@ $(CFLAGS) $(LDFLAGS) -lm
+
+showcase.o: showcase.c
+	$(CC) $(FLAGS) $(CFLAGS) $(LDFLAGS) -c $^
\ No newline at end of file
diff --git a/showcase/showcase b/showcase/showcase
new file mode 100755
index 0000000000000000000000000000000000000000..1764eaf4b94576facef276da61225d822be59fbd
Binary files /dev/null and b/showcase/showcase differ
diff --git a/showcase/showcase.c b/showcase/showcase.c
new file mode 100644
index 0000000000000000000000000000000000000000..a0b401cc27a5cb58d94baf35bc6333afc3cf0aa8
--- /dev/null
+++ b/showcase/showcase.c
@@ -0,0 +1,419 @@
+#include <math.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+// UTILS ----------------------------------------------------------
+
+#define M 4
+#include <stdlib.h>
+
+typedef struct node {
+    struct node *childs[M + 1];
+    int data[M];
+    int count;
+    struct node *next;
+} node;
+
+typedef struct control {
+    int value;
+    node *lhs;
+    node *rhs;
+} control;
+
+const control CONST_CONTR = {.value = 0, .lhs = NULL, .rhs = NULL};
+
+node *bp_create_node() {
+    node *nd = malloc(sizeof(node));
+
+    for (int i = 0; i < M + 1; i++)
+        nd->childs[i] = NULL;
+    for (int i = 0; i < M; i++)
+        nd->data[i] = 0;
+    nd->count = 0;
+    nd->next = NULL;
+    return nd;
+}
+
+control value_to_insert(int val) {
+    control c;
+    c.value = val;
+    c.lhs = c.rhs = NULL;
+    return c;
+}
+
+bool bp_is_leaf(node *nd) { return nd->childs[0] == NULL; }
+
+void bp_node_shift(node *nd, int index) {
+    // as there is one more child than values, we must do one more iteration
+    // outside of the for
+    nd->childs[M] = nd->childs[M - 1];
+
+    for (int i = M - 1; i > index; i--) {
+        nd->data[i] = nd->data[i - 1];
+        nd->childs[i + 1] = nd->childs[i];
+    }
+}
+
+node *bp_split(node *nd) {
+    node *new = bp_create_node();
+    /*
+        this weird thing is for the for loop
+        up to how many loop do we want to do
+        we need it outside because if the order of the tree is odd, we must do
+       one more loop
+    */
+    int upto = (int)floor(M / 2);
+    int index = upto;
+
+    // update the new counts
+    nd->count = (int)floor(nd->count / 2);
+    new->count = upto;
+
+    // as explained, do shit if the order is odd
+    if (M % 2 == 1) {
+        upto++;
+        new->count++;
+    }
+    // no need in this situation to reassign child pointers as there is no
+    // childs for leaves
+    for (int i = 0; i < upto; i++) {
+        new->data[i] = nd->data[index + i];
+        nd->data[index + i] = 0;
+    }
+
+    return new;
+}
+
+node *bp_split_root(node *root) {
+    node *new = bp_create_node(); // will be the new root
+    node *rhs = bp_create_node(); // second child of the new root
+
+    int index = (int)floor(M / 2); // index to the pivot
+    int looper = index; /* How many runs of our for loops we'll need to do
+    (different to index in the case our tree order is even)*/
+
+    new->count = 1;
+    root->count = index;
+    rhs->count = index;
+
+    if (M % 2 == 0) {
+        looper--;
+        rhs->count--;
+    }
+
+    // first assing the child pointers
+    for (int i = 0; i <= looper; i++) {
+        rhs->childs[i] = root->childs[index + i + 1];
+        root->childs[index + i + 1] = NULL;
+    }
+
+    // then assing the datas
+    for (int i = 0; i < looper; i++) {
+        rhs->data[i] = root->data[index + i + 1];
+        root->data[index + i + 1] = 0;
+    }
+
+    new->childs[0] = root;
+    new->childs[1] = rhs;
+    new->data[0] = root->data[index];
+
+    root->data[index] = 0;
+
+    return new;
+}
+
+control bp_split_unleaf(node *nd) {
+    // This one is used to split a node that is neither a leaf or a root
+    // it works exactly like the split of a root except it doesn't return a node
+    // that becomes the new root
+    // it instead returns a control value to send to the parent
+    control new;
+    node *rhs = bp_create_node();
+
+    int index = (int)floor(M / 2);
+    int looper = index;
+
+    nd->count = index;
+    rhs->count = index;
+
+    if (M % 2 == 0) {
+        looper--;
+        rhs->count--;
+    }
+
+    for (int i = 0; i <= looper; i++) {
+        rhs->childs[i] = nd->childs[index + i + 1];
+        nd->childs[index + i + 1] = NULL;
+    }
+
+    for (int i = 0; i < looper; i++) {
+        rhs->data[i] = nd->data[index + i + 1];
+        nd->data[index + i + 1] = 0;
+    }
+
+    new.lhs = nd;
+    new.rhs = rhs;
+    new.value = nd->data[index];
+
+    nd->data[index] = 0;
+
+    return new;
+}
+
+void bp_do_the_insert(node *nd, control val) {
+    // look for a 0 in the node (it is guarenteed to exist in this version of
+    // the algorithm)
+    for (int i = 0; i < M; i++) {
+        // if we plainly find a 0
+        if (nd->data[i] == 0) {
+            nd->data[i] = val.value;
+            nd->childs[i + 1] = val.rhs;
+            break;
+        }
+
+        // if we need to insert the value between two values, we need to
+        // shift everything greater than our value one case further
+        if (nd->data[i] > val.value) {
+            bp_node_shift(nd, i);
+            nd->data[i] = val.value;
+            nd->childs[i + 1] = val.rhs;
+            break;
+        }
+    }
+    nd->count++;
+}
+
+// INSERT ----------------------------------------------------------
+
+control bp_insert_into(node *nd, control val) {
+    bp_do_the_insert(nd, val);
+    // if the node is now full, we split
+    if (nd->count == M) {
+        control v;
+        node *new = bp_split(nd);
+        v.lhs = nd;
+        v.rhs = new;
+        v.value = new->data[0];
+
+        // if the new node we created is a leaf, we must add it to the
+        // linked list
+        if (bp_is_leaf(new)) {
+            if (nd->next != NULL)
+                new->next = nd->next;
+
+            nd->next = new;
+        }
+        return v;
+    }
+    return CONST_CONTR;
+}
+
+control bp_insert(node *nd, control val, int depth) {
+    control c; // will help us to return the pivot, and the two pointers of the
+               // childs-to-be
+
+    // if we are in a leaf, we found where to insert the value, so let's do it
+    if (bp_is_leaf(nd))
+        c = bp_insert_into(nd, val);
+    else // otherwise let's keep looking
+    {
+        for (int i = 0; i < M; i++) {
+            if (nd->data[i] > val.value || nd->data[i] == 0) {
+                c = bp_insert(nd->childs[i], val, depth + 1);
+                break;
+            }
+        }
+        // treat the control return here
+        // if a split happened and we are not the root
+        if (c.value != 0 && depth != 0) {
+            bp_do_the_insert(nd, c);
+
+            // if after the child split, the node is full, split the node
+            if (nd->count == M)
+                return bp_split_unleaf(nd);
+
+            return CONST_CONTR;
+        }
+    }
+
+    // if a split happened
+    if (c.value != 0) {
+        return c;
+    }
+    return CONST_CONTR;
+}
+
+node *bp_insert_val(node *tree, int val) {
+    // Parse the val into a control struct then insert it in the tree
+    control test = bp_insert(tree, value_to_insert(val), 0);
+    /*
+        depending on the control item, we act differently
+        if the control has pointers to node, then we had a split in the direct
+        childs of the root. We must add the values upringed to the root
+    */
+    if (test.rhs != NULL) {
+
+        // if the root isn't a leaf, first we add the value into the node
+        if (!bp_is_leaf(tree)) {
+            bp_do_the_insert(tree, test);
+            // If the root is full, we must split it
+            if (tree->count == M) {
+                return bp_split_root(tree);
+            }
+
+            // if not, we can simply return the root
+            return tree;
+        }
+
+        // if, after a split, the root was a leaf, we must create a new
+        // node which will contain the values from the control
+        tree = bp_create_node();
+        tree->childs[0] = test.lhs;
+        tree->childs[1] = test.rhs;
+        tree->data[0] = test.value;
+        tree->count = 1;
+    }
+    return tree;
+}
+
+// MEMORY ----------------------------------------------------------
+
+void bp_destroy(node *root) {
+    if (root == NULL)
+        return;
+
+    // free the childs first
+    if (!bp_is_leaf(root)) {
+        for (int i = 0; i < M; i++) {
+            bp_destroy(root->childs[i]);
+        }
+    }
+
+    // then free the root
+    free(root);
+}
+
+// PRINTING ----------------------------------------------------------
+
+void bp_print_as_ll(node *root) {
+    // if we reached the end of the list
+    if (root == NULL) {
+        printf("NULL\n");
+        return;
+    }
+
+    // search for the first leaf on the tree
+    if (!bp_is_leaf(root)) {
+        return bp_print_as_ll(root->childs[0]);
+    }
+
+    printf("|");
+    // print every values in the node until hitting 0, then we can get on the
+    // next node
+    for (int i = 0; i < M; i++) {
+        printf(" %d |", root->data[i]);
+        if (root->data[i + 1] == 0) {
+            printf(" -> ");
+            return bp_print_as_ll(root->next);
+        }
+    }
+}
+
+void bp_print(node *root, int depth) {
+    // if we are on a leaf, we can print the values directly next to each other
+    if (bp_is_leaf(root)) {
+        for (int i = 0; i < depth; i++)
+            printf("     ");
+        for (int i = 0; i < M; i++) {
+            printf(" %d |", root->data[i]);
+            // if we reach a 0, we have seen every values in the node
+            if (root->data[i + 1] == 0)
+                break;
+        }
+        return;
+    }
+
+    for (int i = 0; i < M; i++) {
+        bp_print(root->childs[i], depth + 1);
+        printf("\n");
+
+        for (int i = 0; i < depth; i++)
+            printf("     ");
+
+        printf(" %d |\n", root->data[i]);
+
+        if (root->data[i + 1] == 0)
+            return bp_print(root->childs[i + 1], depth + 1);
+    }
+}
+int main() {
+    node *tree = bp_create_node();
+
+    tree = bp_insert_val(tree, 3);
+    bp_print(tree, 0);
+
+    printf("\n|||||||||\n");
+    tree = bp_insert_val(tree, 6);
+    bp_print(tree, 0);
+
+    printf("\n|||||||||\n");
+    tree = bp_insert_val(tree, 5);
+    bp_print(tree, 0);
+
+    printf("\n|||||||||\n");
+    tree = bp_insert_val(tree, 4);
+    bp_print(tree, 0);
+
+    printf("\n|||||||||\n");
+    tree = bp_insert_val(tree, 8);
+    bp_print(tree, 0);
+
+    printf("\n|||||||||\n");
+    tree = bp_insert_val(tree, 13);
+    bp_print(tree, 0);
+
+    printf("\n|||||||||\n");
+    tree = bp_insert_val(tree, 9);
+    bp_print(tree, 0);
+
+    printf("\n|||||||||\n");
+    tree = bp_insert_val(tree, 15);
+    bp_print(tree, 0);
+
+    printf("\n|||||||||\n");
+    tree = bp_insert_val(tree, 11);
+    bp_print(tree, 0);
+
+    printf("\n|||||||||\n");
+    tree = bp_insert_val(tree, 12);
+    bp_print(tree, 0);
+
+    printf("\n|||||||||\n");
+    tree = bp_insert_val(tree, 7);
+    bp_print(tree, 0);
+
+    printf("\n|||||||||\n");
+    tree = bp_insert_val(tree, 14);
+    bp_print(tree, 0);
+
+    printf("\n|||||||||\n");
+    tree = bp_insert_val(tree, 10);
+    bp_print(tree, 0);
+
+    printf("\n|||||||||\n");
+    tree = bp_insert_val(tree, 16);
+    bp_print(tree, 0);
+
+    printf("\n|||||||||\n");
+    tree = bp_insert_val(tree, 17);
+    bp_print(tree, 0);
+
+    printf("\n|||||||||\n");
+    tree = bp_insert_val(tree, 18);
+    bp_print(tree, 0);
+    printf("\n|||||||||\n");
+    bp_print_as_ll(tree);
+    bp_destroy(tree);
+    return 0;
+}