diff --git a/R4.01_R4.A.10/README.md b/R4.01_R4.A.10/README.md
new file mode 100644
index 0000000..088660f
--- /dev/null
+++ b/R4.01_R4.A.10/README.md
@@ -0,0 +1,5 @@
+## Ressources R4.01 + R4.A.10
+
+#### Semaine 1
+[Compléments de javascript](cours/jscomp.pdf) javascript, [tp1](./td_tp/tp1)
+
diff --git a/R4.01_R4.A.10/cours/jscomp.pdf b/R4.01_R4.A.10/cours/jscomp.pdf
new file mode 100644
index 0000000..91c06d8
Binary files /dev/null and b/R4.01_R4.A.10/cours/jscomp.pdf differ
diff --git a/R4.01_R4.A.10/td_tp/tp1/README.md b/R4.01_R4.A.10/td_tp/tp1/README.md
new file mode 100644
index 0000000..acbcbf2
--- /dev/null
+++ b/R4.01_R4.A.10/td_tp/tp1/README.md
@@ -0,0 +1,168 @@
+# TP javascript : bases du langages.
+Un peu [d'aide](./aide.md).
+> - seance 1 : [révisions](#p1)
+> - seance 2 : [forEach, filter, map, reduce, etc.](#p2)
+
+### Séance 1
+#### Ex1 : fourmi de Langton
+Une fourmi, assimilable à un petit automate, se promène sur une grille de points colorés;
+pour commencer, tous les points sont blancs.
+- la fourmi est initialement placée au centre de la grille. Elle se déplace dans les quatre directions cardinales. Initialement, elle va vers l'est.
+- A chaque pas, elle se déplace d'une case dans sa direction. Son parcours est dicté par les deux règles suivantes :
+ - Si la case atteinte est noire, elle la repeint en blanc, et tourne de 90° à gauche.
+ - Si la case est blanche, elle la repeint en noire, et tourne de 90° à droite.
+- Elle continue son chemin en suivant ces règles.
+
+
+
+_Les 9 premiers pas de la fourmi_
+
+
+
+Vous disposez de [sources](./src/langton) que vous allez compléter. En particulier, il y a 2 modules :
+
+>- une classe **Ant** qui représente l'univers : la fourmi, et les tuiles sur lesquelles elle se déplace.
+>- une fonction **render** qui gére l'affichage graphique.
+
+
+- La fourmi a une position sur la grille, ainsi qu'une direction. La direction sera codée par un entier (angle 0,90,180 ou 270).
+- Les tuiles sont repréntées par un tableau à 2 dimensions. Chaque tuile a 2 valeurs possibles (0 ou 1).
+
+
+1. Complétez le code de la classe `Ant`.
+2. Complétez le code de `app.js`.
+3. Ajoutez un bouton/lien qui permet de réinitialiser la simulation.
+4. Dissociez, en terme de classe/structure, la fourmi de la grille sur laquelle elle évolue, et modifiez le
+ code en conséquence.
+
+
+
+
+
+
+#### Ex2 : fourmi de Langton
+On peut complexifier et généraliser la fourmi précédente, et les règles d'évolution de l'automate correspondant : la fourmi, et les tuiles peuvent avoir
+un nombre quelconque d'états. Les règles de l'automate sont alors décrites par une table de transition.
+
+Exemple 1 : on donne la table de transition suivante (T désigne la tuile, a la fourmi) à 2 états pour la fourmi, et 2 états pour les tuiles.
+
+
+| | T: 0 | T: 1 |
+|------|-----------|-----------|
+| a: 0 | (1,0,1) | (0,90,1) |
+| a: 1 | (0,-90,1) | (1,0,1) |
+
+
+
+Chaque triplet représente (Ant State Change, Ant Direction Change, Tile State Change). Ainsi,
+
+- (1,90,0) => on incrémente 1 à l'état de la fourmi, 90 à sa direction, et 0 à l'état de la tuile.
+- (0,-90,1) => on incrémente 0 à l'état de la fourmi, -90 à sa direction, et 1 à l'état de la tuile.
+
+Les incrémentations se font modulo le nombre d'états possibles.
+
+Avec cet automate, on obtient la figure :
+
+
+
+
+
+Par commodité, on note la table de transition précédente simplement :
+
+```
+ (1,0,1) (0,90,1)
+ (0,-90,1) (1,0,1)
+```
+
+1. Modifiez le code de l'exercice 1 de manière à pouvoir simuler l'automate ci-dessus. Votre solution doit pouvoir permettre une simulation quelconque.
+ Quelle est la table correspondante à la fourmi de la première partie du tp ?
+2. Testez avec
+ ```
+ (1,90,0) (0,-90,1)
+ (0,-90,1) (1,90,1)
+ ```
+
+
+
+3. Testez avec
+
+ ```
+ (1, 0, 1) (0, 90, 0)
+ (0, -90, 1) (1, 0, 1)
+ ```
+
+### Séance 2
+Soit le tableau d'objets suivant :
+```js
+let customers = [
+ {
+ 'id': 1,
+ 'f_name': 'Abby',
+ 'l_name': 'Thomas',
+ 'gender': 'M',
+ 'married': true,
+ 'age': 32,
+ 'expense': 500,
+ 'purchased': ['Shampoo', 'Toys', 'Book']
+ },
+ {
+ 'id': 2,
+ 'f_name': 'Jerry',
+ 'l_name': 'Tom',
+ 'gender': 'M',
+ 'married': true,
+ 'age': 64,
+ 'expense': 100,
+ 'purchased': ['Stick', 'Blade']
+ },
+ {
+ 'id': 3,
+ 'f_name': 'Dianna',
+ 'l_name': 'Cherry',
+ 'gender': 'F',
+ 'married': true,
+ 'age': 22,
+ 'expense': 1500,
+ 'purchased': ['Lipstik', 'Nail Polish', 'Bag', 'Book']
+ },
+ {
+ 'id': 4,
+ 'f_name': 'Dev',
+ 'l_name': 'Currian',
+ 'gender': 'M',
+ 'married': true,
+ 'age': 82,
+ 'expense': 90,
+ 'purchased': ['Book']
+ },
+ {
+ 'id': 5,
+ 'f_name': 'Maria',
+ 'l_name': 'Gomes',
+ 'gender': 'F',
+ 'married': false,
+ 'age': 7,
+ 'expense': 300,
+ 'purchased': ['Toys']
+ },
+ {
+ 'id': 6,
+ 'f_name': 'Homer',
+ 'l_name': 'Simpson',
+ 'gender': 'M',
+ 'married': true,
+ 'age': 39,
+ 'expense': 500,
+ 'purchased': ['Book']
+ }
+];
+```
+
+En utilisant les fonctions/méthodes `forEach, filter, map, reduce, some`, donnez ou calculez :
+1. un tableau des client séniors (dont l'âge est plus de 60 ans).
+2. un tableau où chaque client possède un nouvel attribut `full_name`.
+3. s'il y a un client de moins de 10 ans.
+4. le nombre d'acheteurs de livres.
+5. la somme totale d'argent dépensé par les clients marriés.
+6. Pour chaque produit, la liste (`id`) des acheteurs.
+
diff --git a/R4.01_R4.A.10/td_tp/tp1/aide.md b/R4.01_R4.A.10/td_tp/tp1/aide.md
new file mode 100644
index 0000000..432dba1
--- /dev/null
+++ b/R4.01_R4.A.10/td_tp/tp1/aide.md
@@ -0,0 +1,115 @@
+#### Élement d'un document
+
+```js
+
+let x = document.getElementById(MOVE_VAL_ID)
+let images = document.querySelectorAll('img')
+```
+
+#### Changer le contenu texte d'un élément
+```js
+document.getElementById('message').textContent = "hello world !"
+```
+
+#### Nombre aléatoire
+
+```js
+let r=Math.random();
+if (r<0.5)
+ console.log("Face");
+else
+ console.log("Pile");
+```
+#### Timers
+
+```js
+setTimeout(()=>console.log("3 secondes écoulées"),3000);
+
+let i = setInterval(
+ () => {
+ let d = (new Date()).toLocaleTimeString();
+ document.getElementById("time").innerText = d;
+ },
+ 1000)
+
+setTimeout(()=>clearInterval(i),10000);
+```
+
+#### Réponse à un événement
+```js
+// inline DOM 0
+img.onclick = function(){ console.log("clicked !")}
+
+// DOM >= 2
+img.addEventListener("click",()=>console.log("clicked"));
+
+```
+
+
+#### Itération d'un tableau
+
+```js
+let a = [1,2,3];
+
+// forEach
+a.forEach( elem => console.log(elem));
+
+// for ... of
+// valable pour tous les itérables
+// Array, Map, Set, String, etc.
+
+for (let elem of a){
+ console.log(elem);
+}
+```
+
+
+#### Tri d'un tableau
+
+```js
+const activities = [
+ { title: 'Hiking', date: new Date('2019-06-28') },
+ { title: 'Shopping', date: new Date('2019-06-10') },
+ { title: 'Trekking', date: new Date('2019-06-22') }
+]
+
+const sortedActivities = activities.sort((a, b) => b.date - a.date);
+
+```
+
+#### Itération d'un tableau avec map, filter, reduce et find.
+
+```js
+// map
+const items = ['a', 'b', 'c']
+const newArray = items.map((item) => performSomething(item))
+const newArray = items.map(performSomething)
+
+// find
+const items = [
+ { name: 'a', content: { /* ... */ }},
+ { name: 'b', content: { /* ... */ }},
+ { name: 'c', content: { /* ... */ }}
+]
+const b = items.find((item) => item.name === 'b')
+
+//reduce
+const items = [
+ { name: 'a', content: { value: 1 }},
+ { name: 'b', content: { value: 2 }},
+ { name: 'c', content: { value: 3 }}
+]
+
+const count = items.reduce((result, elem ) => result + elem.content.value, 0)
+// en decomposant l'objet !
+const count = items.reduce((result, { content: { value } }) => result + value, 0)
+
+```
+
+#### Division d'une chaîne de caractères avec split
+```js
+const str = 'a,b,c,d,e'
+const l = str.split(',')
+
+// l = [ "a","b","c","d","e"]
+```
diff --git a/R4.01_R4.A.10/td_tp/tp1/img/fourmi.png b/R4.01_R4.A.10/td_tp/tp1/img/fourmi.png
new file mode 100644
index 0000000..dea6730
Binary files /dev/null and b/R4.01_R4.A.10/td_tp/tp1/img/fourmi.png differ
diff --git a/R4.01_R4.A.10/td_tp/tp1/img/langton.png b/R4.01_R4.A.10/td_tp/tp1/img/langton.png
new file mode 100644
index 0000000..7405835
Binary files /dev/null and b/R4.01_R4.A.10/td_tp/tp1/img/langton.png differ
diff --git a/R4.01_R4.A.10/td_tp/tp1/img/langton1.png b/R4.01_R4.A.10/td_tp/tp1/img/langton1.png
new file mode 100644
index 0000000..2136539
Binary files /dev/null and b/R4.01_R4.A.10/td_tp/tp1/img/langton1.png differ
diff --git a/R4.01_R4.A.10/td_tp/tp1/img/langton2.png b/R4.01_R4.A.10/td_tp/tp1/img/langton2.png
new file mode 100644
index 0000000..0e59504
Binary files /dev/null and b/R4.01_R4.A.10/td_tp/tp1/img/langton2.png differ
diff --git a/R4.01_R4.A.10/td_tp/tp1/img/vie.png b/R4.01_R4.A.10/td_tp/tp1/img/vie.png
new file mode 100644
index 0000000..93d90a3
Binary files /dev/null and b/R4.01_R4.A.10/td_tp/tp1/img/vie.png differ
diff --git a/R4.01_R4.A.10/td_tp/tp1/src/langton/app.js b/R4.01_R4.A.10/td_tp/tp1/src/langton/app.js
new file mode 100644
index 0000000..8871d05
--- /dev/null
+++ b/R4.01_R4.A.10/td_tp/tp1/src/langton/app.js
@@ -0,0 +1,65 @@
+import render from "./modules/langton-renderer-canvas2d";
+import Ant from "./modules/Ant.js";
+
+
+const options = {
+ antStateColors : ['red','yellow'],
+ tileStateColors : ['white','black'],
+ tileSize : 5
+};
+
+
+// For the view
+
+const STEP_INTERVAL = 5;
+const BTN_AUTOPLAY_ID = 'autoplay';
+const BTN_NEXT_MOVE_ID = 'next-move';
+const MOVE_VAL_ID = 'move-value';
+const BTN_PLUS_100_ID = 'plus-100';
+
+
+
+
+let autoplayInterval;
+let canvas = document.querySelector("canvas");
+
+
+canvas.width = window.innerWidth ;
+canvas.height = window.innerHeight;
+
+let ant = new Ant(Math.floor(canvas.width / options.tileSize),Math.floor(canvas.height/options.tileSize));
+
+document.getElementById(BTN_AUTOPLAY_ID).addEventListener('click', () => {
+ if (autoplayInterval) {
+ return
+ }
+ // TODO
+});
+
+
+document.getElementById(BTN_PLUS_100_ID).addEventListener('click', () => {
+ if (autoplayInterval) {
+ clearInterval(autoplayInterval);
+ autoplayInterval = null;
+ }
+ // TODO
+});
+
+document.getElementById(BTN_NEXT_MOVE_ID).addEventListener('click', () => {
+ if (autoplayInterval) {
+ clearInterval(autoplayInterval);
+ autoplayInterval = null;
+ }
+ ant.moveForward();
+ updateView(ant,canvas,options)
+})
+
+
+function updateView(ant,canvas,options)
+{
+ document.getElementById(MOVE_VAL_ID).textContent = `${ant.move}`;
+ render(ant,canvas,options);
+}
+
+
+updateView(ant,canvas,options);
diff --git a/R4.01_R4.A.10/td_tp/tp1/src/langton/css/style.css b/R4.01_R4.A.10/td_tp/tp1/src/langton/css/style.css
new file mode 100644
index 0000000..192272f
--- /dev/null
+++ b/R4.01_R4.A.10/td_tp/tp1/src/langton/css/style.css
@@ -0,0 +1,8 @@
+canvas {
+ position : absolute ;
+ top : 0;
+ left : 0;
+ z-index : -1;
+}
+
+
diff --git a/R4.01_R4.A.10/td_tp/tp1/src/langton/index.html b/R4.01_R4.A.10/td_tp/tp1/src/langton/index.html
new file mode 100644
index 0000000..3b09a8a
--- /dev/null
+++ b/R4.01_R4.A.10/td_tp/tp1/src/langton/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+ Fourmi de Langton
+
+
+
+
+
+
+
+
+
+ Fourmi de Langton
+
+
+
+
+
+
+
+
diff --git a/R4.01_R4.A.10/td_tp/tp1/src/langton/modules/Ant.js b/R4.01_R4.A.10/td_tp/tp1/src/langton/modules/Ant.js
new file mode 100644
index 0000000..923e3fc
--- /dev/null
+++ b/R4.01_R4.A.10/td_tp/tp1/src/langton/modules/Ant.js
@@ -0,0 +1,56 @@
+class Ant {
+ x = 0; // position
+ y = 0;
+ move = 0;
+
+ w = 0; // universe dimensions
+ h = 0;
+
+ direction = 0; // 0 90 180 270
+ state = 0;
+ tiles = null;
+
+ constructor (w,h)
+ {
+ this.tiles = new Array(w).fill(null);
+ this.tiles.forEach((el,i) => this.tiles[i] = new Array(h).fill(0));
+ this.w = w;
+ this.h = h;
+ this.x = Math.floor(w/2);
+ this.y = Math.floor(h/2);
+ }
+
+ moveForward()
+ {
+ switch (this.direction) {
+ case 0:
+ this.x = ((this.x + 1) + this.w) % this.w;
+ break
+ case 90:
+ this.y = ((this.y + 1) + this.h) % this.h;
+ break
+ case 180:
+ this.x = ((this.x - 1) + this.w) % this.w;
+ break
+ case 270:
+ this.y = ((this.y - 1) + this.h) % this.h;
+ break
+ }
+ this.move ++;
+ this.computeNextState();
+ }
+ rotateRight() {
+ // TODO
+ }
+
+ rotateLeft() {
+ // TODO
+ }
+
+ computeNextState()
+ {
+ // TODO
+ }
+}
+
+export default Ant;
diff --git a/R4.01_R4.A.10/td_tp/tp1/src/langton/modules/langton-renderer-canvas2d.js b/R4.01_R4.A.10/td_tp/tp1/src/langton/modules/langton-renderer-canvas2d.js
new file mode 100644
index 0000000..c5fdf60
--- /dev/null
+++ b/R4.01_R4.A.10/td_tp/tp1/src/langton/modules/langton-renderer-canvas2d.js
@@ -0,0 +1,99 @@
+/**
+ * render - renders the universe to a 2D canvas.
+ *
+ * @param langtonsAnt - the universe.
+ * @param canvas - The 2D canvas.
+ * @param options - The rendering options (all optional).
+ * @returns {undefined} - Nothing is returned.
+ */
+
+function render(langtonsAnt, canvas, options) {
+
+ // Grab our options.
+ const {
+ tileStateColors,
+ antStateColors,
+ tileSize
+ } = options;
+
+
+ // Drawing style.
+ const backgroundColor = '#FFFFFF';
+
+ // Size constants.
+ const w = canvas.width;
+ const h = canvas.height;
+
+ // Bounds constants.
+ const gridSizeW = langtonsAnt.tiles.length;
+ const gridSizeH = langtonsAnt.tiles[0].length;
+
+ // We're going to draw each square with a given edge size
+
+ const tileSizeW = tileSize;//w / gridSizeW ;
+ const tileSizeH = tileSize; //h / gridSizeH ;
+
+ // Get the drawing context.
+ var ctx = canvas.getContext('2d');
+
+ // Clear the background.
+ ctx.fillStyle = backgroundColor;
+ ctx.fillRect(0, 0, w, h);
+
+ // Draw the grid.
+ ctx.strokeStyle='#00000011';
+ for (let x = 0; x <= gridSizeW; x++) {
+ ctx.beginPath();
+ ctx.moveTo(x * tileSizeW , 0);
+ ctx.lineTo(x * tileSizeW , h);
+ ctx.closePath();
+ ctx.stroke();
+ }
+ for (let y = 0 ; y <= gridSizeH; y++) {
+ ctx.beginPath();
+ ctx.moveTo(0, y * tileSizeH);
+ ctx.lineTo(w, y * tileSizeH);
+ ctx.closePath();
+ ctx.stroke();
+ }
+
+
+ // Start drawing those tiles.
+ langtonsAnt.tiles.forEach((tileRow,i) => {
+ tileRow.forEach((tile,j)=>{
+
+ // Get the tile state index.
+
+ // Skip state zero tiles (i.e. white tiles)
+ if (tile !== 0) {
+ // Set the tile colour, defaulting to grey if it is not set.
+ ctx.fillStyle = tileStateColors[tile] || '#CCCCCC';
+ ctx.fillRect(i * tileSizeW + 1, j * tileSizeH +1, tileSizeW - 1, tileSizeH - 1);
+ }
+
+ })
+ })
+
+
+ // Draw the ant.
+ var antX = langtonsAnt.x * tileSizeW,
+ antY = langtonsAnt.y * tileSizeH;
+ const antState = langtonsAnt.state;
+
+ ctx.fillStyle = antStateColors[antState];
+ // Tranform before we draw the ant, it makes it easier.
+ //
+ ctx.save();
+ ctx.translate(antX + tileSizeW/2, antY+tileSizeH/2);
+ ctx.rotate((langtonsAnt.direction / 180) * Math.PI);
+ ctx.beginPath();
+ ctx.moveTo(-tileSizeW/2, -tileSizeH/2);
+ ctx.lineTo(tileSizeW/2, 0);
+ ctx.lineTo(-tileSizeW/2, tileSizeH/2);
+ ctx.fill();
+ ctx.closePath();
+ ctx.restore();
+}
+
+
+export default render;
diff --git a/README.md b/README.md
index 5d072a3..4dce82d 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,7 @@
| Ressource | Code | Semestre | Notes |
| --------------------------------------------- | ------------- | --------- | -------------- |
| [Développement d'interfaces web](./R1.02) | R1.02 | S1 | ds | |
+| [Complément Web - Architecture logicielle](./R4.01_R4.A.10) | R4.01 + R4.A.10 | S4 | projet (1) |