diff --git a/.gitignore b/.gitignore
index a0935e1..20d3eb2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
**/out
**/a.out
.cache/*
-.test-cache/*
\ No newline at end of file
+.test-cache/*
+**/__pycache__
\ No newline at end of file
diff --git a/src/webserver/app.py b/src/webserver/app.py
new file mode 100644
index 0000000..1736aa8
--- /dev/null
+++ b/src/webserver/app.py
@@ -0,0 +1,71 @@
+#!/usr/bin/python3
+from flask import Flask, render_template, request
+import subprocess
+import json
+
+MAGIC_NUMBER = 2051
+
+app = Flask(__name__)
+
+@app.route("/")
+def index():
+ return render_template("index.html")
+
+@app.route("/mnist")
+def mnist():
+ return render_template("mnist.html")
+
+@app.route("/post", methods=["POST"])
+def post_json_handler():
+ """
+ Gère les requêtes POST
+ """
+ if request.is_json:
+ content = request.get_json()
+ req_type = content["type"]
+ if req_type == "prediction":
+ dataset = content["dataset"]
+ image = content["data"]
+ if dataset == "mnist":
+ return recognize_mnist(image)
+ return {"status": "404"}
+
+
+def recognize_mnist(image):
+ """Appelle le programme C reconnaissant les images"""
+ # Créer le fichier binaire
+ write_image_to_binary(image, ".cache/image.bin")
+
+ try:
+ return {"status": 200, "data":
+ json.loads(subprocess.check_output([
+ 'out/main',
+ 'recognize',
+ '--modele', '.cache/reseau.bin',
+ '--in', '.cache/image.bin',
+ '--out', 'json'
+ ]))["0"]}
+ except subprocess.CalledProcessError:
+ return {
+ "status": 500,
+ "data": "Internal Server Error"
+ }
+
+def write_image_to_binary(image, filepath):
+ byteorder = "big"
+
+ bytes_ = MAGIC_NUMBER.to_bytes(4, byteorder=byteorder)
+ bytes_ += (1).to_bytes(4, byteorder=byteorder)
+ bytes_ += len(image).to_bytes(4, byteorder=byteorder)
+ bytes_ += len(image[0]).to_bytes(4, byteorder=byteorder)
+ for row in image:
+ for nb in row:
+ bytes_ += int(nb).to_bytes(1, byteorder=byteorder)
+
+ with open(filepath, "wb") as f:
+ f.write(bytes_)
+
+
+
+if __name__ == '__main__':
+ app.run(debug=True, host='0.0.0.0')
\ No newline at end of file
diff --git a/src/webserver/static/script.js b/src/webserver/static/script.js
new file mode 100644
index 0000000..2b92c6d
--- /dev/null
+++ b/src/webserver/static/script.js
@@ -0,0 +1,169 @@
+/*
+Le code concernant l'entrée par l'utilisateur d'un nombre a été adapté depuis le code suivant: (License MIT)
+https://github.com/maneprajakta/Digit_Recognition_Web_App/blob/master/js/main.js
+
+On été rajoutées les fonctions permettant de communiquer avec le serveur
+*/
+// Variables globales
+var canvas;
+var ctx;
+var touchX;
+var touchY;
+var mouseX;
+var mouseY;
+var mouseDown = 0;
+
+function init() {
+ canvas = document.getElementById('digit-canvas');
+ ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = "black";
+ // Créer une zone de dessin
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+
+ if(ctx)
+ {
+ canvas.addEventListener('mousedown', s_mouseDown, false);
+ canvas.addEventListener('mousemove', s_mouseMove, false);
+ window.addEventListener('mouseup', s_mouseUp, false);
+ document.getElementById('clear').addEventListener("click", clear);
+ }
+}
+
+
+function draw(ctx, x, y, isDown) {
+ // isDown représente le fait que le chemin ait déjà commencé ou non
+ // On ne dessine donc ue si le "stylo" est déjà posé
+ if (isDown) {
+ ctx.beginPath();
+ // On choisit les options suivantes:
+ ctx.strokeStyle = "white";
+ ctx.lineWidth = "10";
+ ctx.lineJoin = "round";
+ ctx.lineCap = "round";
+ ctx.moveTo(lastX, lastY);
+ ctx.lineTo(x, y);
+ ctx.closePath();
+ ctx.stroke();
+ }
+ lastX = x;
+ lastY = y;
+}
+
+// Mouse moves
+function s_mouseDown() {
+ mouseDown = 1;
+ draw(ctx, mouseX, mouseY, false);
+}
+
+function s_mouseUp() {
+ mouseDown = 0;
+}
+
+function s_mouseMove(e) {
+ // Si la souris bouge et est cliquée, on souhaite dessiner un trait
+ getMousePos(e);
+ if (mouseDown == 1) {
+ draw(ctx, mouseX, mouseY, true);
+ }
+}
+
+function getMousePos(e) {
+ if (e.offsetX) {
+ mouseX = e.offsetX;
+ mouseY = e.offsetY;
+ } else if (e.layerX) {
+ mouseX = e.layerX;
+ mouseY = e.layerY;
+ }
+}
+
+
+function clear() {
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+ ctx.fillStyle = "black";
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+}
+
+
+
+function sendJSON(data,callback){
+ // Creating a XHR object
+ let xhr = new XMLHttpRequest();
+ let url = "post";
+
+ // open a connection
+ xhr.open("POST", url, true);
+
+ // Set the request header i.e. which type of content you are sending
+ xhr.setRequestHeader("Content-Type", "application/json");
+
+ // Create a state change callback
+ xhr.onreadystatechange = function () {
+ if (xhr.readyState === 4 && xhr.status === 200) {
+
+ // Print received data from server
+ callback(this.responseText);
+
+ }
+ };
+
+ // Converting JSON data to string
+ var data = JSON.stringify(data);
+
+ // Sending data with the request
+ xhr.send(data);
+}
+
+
+function getPrediction() {
+ let totalWidth = 280;
+ let totalHeight = 280;
+ let curWidth = 0;
+ let curHeight = 0;
+ let stepSize = 10;
+
+ let tableau = [];
+ let tmp_tableau = [];
+
+ while (curWidth < totalWidth) {
+ curHeight = 0;
+ tmp_tableau = [];
+ while (curHeight < totalHeight) {
+ data = ctx.getImageData(curWidth, curHeight, stepSize, stepSize);
+ size = data.width * data.height;
+ density = 0;
+
+ for (let i=0;i < size;i++) {
+ density += (data.data[i*4]+data.data[i*4+1]+data.data[i*4+2])/3;
+ }
+ density = density*1.0 / size;
+
+ tmp_tableau.push(density);
+ curHeight += stepSize;
+ }
+ curWidth += stepSize;
+ tableau.push(tmp_tableau);
+ }
+
+ return sendJSON({
+ "type": "prediction",
+ "dataset": "mnist",
+ "data": tableau
+ }, (data) => {
+ data = JSON.parse(data);
+ if (data["status"] != 200) {
+ document.getElementById("result").innerHTML = "500 Internal Server Error";
+ } else {
+ let resultat = document.getElementById("result");
+ resultat.innerHTML = "Résultat:";
+ let dict = {};
+ let i = 0;
+ data["data"].map((e) => { dict[e] = i; i++; });
+ let res = Object.keys(dict).sort().reverse();
+ for (let j=0; j < res.length; j++) {
+ resultat.innerHTML += "
"+dict[res[j]]+" : "+res[j];
+ }
+ }
+ })
+}
\ No newline at end of file
diff --git a/src/webserver/static/style.css b/src/webserver/static/style.css
new file mode 100644
index 0000000..4794e71
--- /dev/null
+++ b/src/webserver/static/style.css
@@ -0,0 +1,4 @@
+#digit-canvas {
+ border: 2px solid #e0e0e0;
+ border-radius: 5px;
+}
\ No newline at end of file
diff --git a/src/webserver/templates/index.html b/src/webserver/templates/index.html
new file mode 100644
index 0000000..d27f8b5
--- /dev/null
+++ b/src/webserver/templates/index.html
@@ -0,0 +1,12 @@
+
+
+