diff --git a/.classpath b/.classpath
deleted file mode 100644
index bcec4dcca820f56eff32d824b1f264a7633a8ba2..0000000000000000000000000000000000000000
--- a/.classpath
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
-		<attributes>
-			<attribute name="module" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="lib" path="lib/tp03_res.jar"/>
-	<classpathentry kind="lib" path="lib/tp04-res.jar"/>
-	<classpathentry kind="output" path="bin"/>
-</classpath>
diff --git a/.gitignore b/.gitignore
index d7ac7438697e1c35822d770cb93978c34a7d995e..c04377a439c0aa8063416f6cecb59c404ea36ae2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
 bin/
 */*.class
-*/*.jar
\ No newline at end of file
+*/*.jar
+.vscode/
\ No newline at end of file
diff --git a/.project b/.project
deleted file mode 100644
index b5f449cf8ce8213eff3f4e43179d9a47b01e0c22..0000000000000000000000000000000000000000
--- a/.project
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>dev_OO</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.jdt.core.javabuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.jdt.core.javanature</nature>
-	</natures>
-	<filteredResources>
-		<filter>
-			<id>1710490098766</id>
-			<name></name>
-			<type>30</type>
-			<matcher>
-				<id>org.eclipse.core.resources.regexFilterMatcher</id>
-				<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
-			</matcher>
-		</filter>
-	</filteredResources>
-</projectDescription>
diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs
deleted file mode 100644
index 99f26c0203a7844de00dbfc56e6a35d8ed3c022c..0000000000000000000000000000000000000000
--- a/.settings/org.eclipse.core.resources.prefs
+++ /dev/null
@@ -1,2 +0,0 @@
-eclipse.preferences.version=1
-encoding/<project>=UTF-8
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 8c9943d50cc1ad01b880ef4e85e8724e6cc19fd2..0000000000000000000000000000000000000000
--- a/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,14 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
-org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=17
-org.eclipse.jdt.core.compiler.debug.lineNumber=generate
-org.eclipse.jdt.core.compiler.debug.localVariable=generate
-org.eclipse.jdt.core.compiler.debug.sourceFile=generate
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
-org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=17
diff --git a/lib/tp04-doc.zip b/lib/tp04-doc.zip
deleted file mode 100644
index 92e8777c9014fedcc0e73cdd42db854e99b2af4a..0000000000000000000000000000000000000000
Binary files a/lib/tp04-doc.zip and /dev/null differ
diff --git a/src/qdev4/Ex1.java b/src/qdev4/Ex1.java
index 21fba00eaa5b35abeda66f5ddf5125a763d8fb06..c55daa3fbaad80533d0b36fe95034afc8ce15a20 100644
--- a/src/qdev4/Ex1.java
+++ b/src/qdev4/Ex1.java
@@ -53,5 +53,5 @@ public class Ex1
                 catch(ArithmeticException e) {System.err.println("Arithmetic " + "");}
                 catch(RuntimeException e) {System.err.println("Runtime " + e);}
                 }
-                
+    
 }
diff --git a/src/qdev4/Ex2.java b/src/qdev4/Ex2.java
new file mode 100644
index 0000000000000000000000000000000000000000..e59799ec1bfff55d06784dfaf4bfb99b19420666
--- /dev/null
+++ b/src/qdev4/Ex2.java
@@ -0,0 +1,18 @@
+package qdev4;
+
+public class Ex2
+{
+    public static int[] tab = {17, 12, 15, 38, 29, 157, 89, -22, 0, 5};
+    
+    public static int division(int index, int divisor) {
+        return tab[index]/divisor;
+    }
+   
+    public static void statement() {
+        int x, y;
+        x = LocalKeyboard.readInt("Write the index of the integer to divide: ");
+        y = LocalKeyboard.readInt("Write the divisor: ");
+        System.out.println("The result is: " + division(x,y));
+    }
+        
+}
diff --git a/test/BreedingGroundTest.java b/test/BreedingGroundTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..7c4ab87d94fc2c71f8c8640481f2bc167995166b
--- /dev/null
+++ b/test/BreedingGroundTest.java
@@ -0,0 +1,139 @@
+package tpOO.tp08;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class BreedingGroundTest {
+	public Participant p1,p2,p3,p4,p5,p6,p7,p8,p9,p10;
+	public BreedingGround v1,v2,v3;
+	public List<Participant> partList;
+	public Set<Participant> partSet;
+	
+	@BeforeEach
+	public void initTest() {
+		partList = new ArrayList<Participant>();
+		partSet = new HashSet<Participant>();
+		
+		p1 = new Participant("alice");
+		p2 = new Participant("bruno"); // the cheater registered in v1 and v3
+		p3 = new Participant("clement");
+		p4 = new Participant("dominique");
+		p5 = new Participant("elia");
+		p6 = new Participant("flore");
+		p7 = new Participant("gudul");
+		p8 = new Participant("hercule");
+		p9 = new Participant("isidor");
+		p10 = new Participant("jules");
+		// appariement des participants
+		p1.matchWith(p2);
+		p5.matchWith(p6);
+		p8.matchWith(p9);
+
+		v1 = new BreedingGround();
+		v1.registration(p1);
+		v1.registration(p2);
+		v1.registration(p3);
+		v1.registration(p4);
+		v2 = new BreedingGround();
+		v2.registration(p5);
+		v2.registration(p6);
+		v3 = new BreedingGround();
+		v3.registration(p8);
+		v3.registration(p9);
+		v3.registration(p10);
+		v3.registration(p2);
+	}
+	
+	@Test
+	public void testRegistration() {
+		assertEquals(4, v1.getApplicants().size());
+		assertTrue(v1.getApplicants().contains(p1) && v1.getApplicants().contains(p2) 
+				&& v1.getApplicants().contains(p3) && v1.getApplicants().contains(p4));
+		v1.clear();
+		assertEquals(Collections.emptySet(), v1.getApplicants());
+		assertTrue(v1.registration(p1));
+		assertEquals(1, v1.getApplicants().size());
+		assertTrue(v1.getApplicants().contains(p1));
+		assertFalse(v1.registration(p1));
+	}
+	@Test
+	public void testLoners() {
+		assertEquals(0, v2.loners().size());
+		assertEquals(Collections.emptyList(), v2.loners());
+		partList = v1.loners();
+		assertEquals(2, partList.size());
+		assertTrue(partList.contains(p3) && partList.contains(p4));
+	}
+	@Test
+	public void testLonersCleansing() {
+		v1.lonersCleansing();
+		assertEquals(2, v1.getApplicants().size());
+		assertTrue(v1.getApplicants().contains(p1) && v1.getApplicants().contains(p2));
+		v2.lonersCleansing();
+		assertEquals(2, v2.getApplicants().size());
+		assertTrue(v2.getApplicants().contains(p5) && v2.getApplicants().contains(p6));
+	}
+	@Test
+	public void testCheaters() {
+		assertEquals(Collections.emptyList(), v1.cheaters(v2));
+		partList.add(p2);
+		assertEquals(partList, v1.cheaters(v3));
+	}
+	@Test
+	public void testCheatersBan() {
+		assertTrue(p1.isMatchedWith(p2));
+		assertTrue(p2.isMatchedWith(p1));
+		v1.isolateCheater(p2);
+		assertFalse(p1.isMatchedWith(p2));
+		assertFalse(p2.isMatchedWith(p1));
+	}
+	@Test
+	public void testCheatersCleansing() {
+		partSet = v1.getApplicants();
+		v1.cheatersCleansing(v2);
+		assertEquals(partSet, v1.getApplicants());
+		partSet.clear();
+		partSet.add(p1); partSet.add(p3); partSet.add(p4);
+		v1.cheatersCleansing(v3);
+		assertEquals(partSet, v1.getApplicants());
+	}
+	@Test
+	public void testPossibleMerging() {
+		assertFalse(v1.possibleMerging(v1));
+		assertTrue(v1.possibleMerging(v2));
+		assertFalse(v1.possibleMerging(v3));
+	}
+	@Test
+	public void testMerge() {
+		partSet = v1.getApplicants();
+		partSet.addAll(v2.getApplicants());
+		v1.merging(v2);
+		assertEquals(partSet, v1.getApplicants());
+		partSet.clear();
+		partSet.addAll(v1.getApplicants());
+		partSet.addAll(v2.getApplicants());
+		partSet.addAll(v3.getApplicants());
+		v1.merging(v3);
+		assertEquals(partSet, v1.getApplicants());
+	}
+	@Test
+	public void testSecuredMerging() {
+		partSet = v1.getApplicants();
+		partSet.add(p8); partSet.add(p9); partSet.add(p10);
+		v1.securedMerging(v3);
+		assertEquals(partSet, v1.getApplicants());
+		partSet.addAll(v2.getApplicants());
+		v1.securedMerging(v2);
+		assertEquals(partSet, v1.getApplicants());
+	}
+}
diff --git a/test/CompanyTest.java b/test/CompanyTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..5d639ba9255e30e91b356264a90b9afd2bc69028
--- /dev/null
+++ b/test/CompanyTest.java
@@ -0,0 +1,127 @@
+package tp06;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.time.LocalDate;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class CompanyTest {
+    private Employee ts1, ts2, v1, w1, w2;
+    private Company society;
+
+    @BeforeEach
+    public void initialization() {
+        ts1 = new TravellingSalesperson("ts-A", LocalDate.now().minusDays(20), 20000);
+        ts2 = new TravellingSalesperson("ts-B", LocalDate.now().minusDays(5), 2);
+        v1 = new Vendor("v-A", LocalDate.now().minusDays(20), 20000);
+        w1 = new Worker("w-A", LocalDate.now().minusDays(20), 2000);
+        w2 = new Worker("w-B", LocalDate.now().minusDays(5), 2);
+        society = new Company();
+    }
+
+    @Test
+    public void hiringSalesPersonTest() {
+        assertEquals(0, society.getNbEmployee());
+        society.addEmployee(ts1);
+        assertEquals(1, society.getNbEmployee());
+        assertEquals(0, society.getNbWorker());
+        assertEquals(1, society.getNbSalesPerson());
+        society.addEmployee(ts2);
+        assertEquals(2, society.getNbEmployee());
+        assertEquals(0, society.getNbWorker());
+        assertEquals(2, society.getNbSalesPerson());
+        society.addEmployee(v1);
+        assertEquals(3, society.getNbEmployee());
+        assertEquals(0, society.getNbWorker());
+        assertEquals(3, society.getNbSalesPerson());
+    }
+
+    @Test
+    public void hiringWorkerTest() {
+        assertEquals(0, society.getNbEmployee());
+        society.addEmployee(w1);
+        assertEquals(1, society.getNbEmployee());
+        assertEquals(1, society.getNbWorker());
+        assertEquals(0, society.getNbSalesPerson());
+        society.addEmployee(w2);
+        assertEquals(2, society.getNbEmployee());
+        assertEquals(2, society.getNbWorker());
+        assertEquals(0, society.getNbSalesPerson());
+    }
+
+    private void hiring() {
+        society.addEmployee(ts1);
+        society.addEmployee(ts2);
+        society.addEmployee(v1);
+        society.addEmployee(w1);
+        society.addEmployee(w2);
+    }
+    private void hiring_alternative() {
+        society.addEmployee(ts1);
+        society.addEmployee(v1);
+        society.addEmployee(w1);
+    }
+
+    @Test
+    public void firingDate_none() {
+        hiring();
+        assertEquals(5, society.getNbEmployee());
+        assertEquals(3, society.getNbSalesPerson());
+        assertEquals(2, society.getNbWorker());
+        society.firing(LocalDate.now());
+        assertEquals(5, society.getNbEmployee());
+        assertEquals(3, society.getNbSalesPerson());
+        assertEquals(2, society.getNbWorker());
+    }
+
+    @Test
+    public void firingDate_all() {
+        hiring();
+        assertEquals(5, society.getNbEmployee());
+        assertEquals(3, society.getNbSalesPerson());
+        assertEquals(2, society.getNbWorker());
+        society.firing(LocalDate.now().minusDays(50));
+        assertEquals(0, society.getNbEmployee());
+        assertEquals(0, society.getNbSalesPerson());
+        assertEquals(0, society.getNbWorker());
+    }
+
+    @Test
+    public void firingDate_some() {
+        hiring();
+        assertEquals(5, society.getNbEmployee());
+        assertEquals(3, society.getNbSalesPerson());
+        assertEquals(2, society.getNbWorker());
+        society.firing(LocalDate.now().minusDays(10));
+        assertEquals(3, society.getNbEmployee());
+        assertEquals(2, society.getNbSalesPerson());
+        assertEquals(1, society.getNbWorker());
+    }
+
+    @Test
+    public void firingObjective_none() {
+        hiring_alternative();
+        assertEquals(3, society.getNbEmployee());
+        assertEquals(2, society.getNbSalesPerson());
+        assertEquals(1, society.getNbWorker());
+        society.firing();
+        assertEquals(3, society.getNbEmployee());
+        assertEquals(2, society.getNbSalesPerson());
+        assertEquals(1, society.getNbWorker());
+    }
+
+    @Test
+    public void firingObjective_some() {
+        hiring();
+        assertEquals(5, society.getNbEmployee());
+        assertEquals(3, society.getNbSalesPerson());
+        assertEquals(2, society.getNbWorker());
+        society.firing();
+        assertEquals(3, society.getNbEmployee());
+        assertEquals(2, society.getNbSalesPerson());
+        assertEquals(1, society.getNbWorker());
+    }
+}
+
diff --git a/test/ShopTest.java b/test/ShopTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..f86d050b0a41366600962bb41ea19ae7dbf0e2df
--- /dev/null
+++ b/test/ShopTest.java
@@ -0,0 +1,77 @@
+package tpOO.tp08;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class ShopTest {
+    public IProduct p1, p2, p3, p4, p5;
+    public ArrayList<IProduct> aStock;
+    public Shelf e1, e2, e3, e4;
+    public ArrayList<Shelf> shelves;
+    public Shop m;
+
+    @BeforeEach
+    public void initialization() {
+        this.p1 = new Food("pasta", 3.25, LocalDate.of(2019, 1, 1));
+		this.p2 = new Furniture("chair", 50.0);
+		this.p3 = new Furniture("table", 100.0);
+		this.p4 = new Food("fish", 10.0);
+		this.p5 = new Food("meat", 15.0, LocalDate.of(2019, 1, 1));
+		this.aStock = new ArrayList<IProduct>();
+		this.aStock.add(p1); this.aStock.add(p2); this.aStock.add(p3); this.aStock.add(p4); this.aStock.add(p5);
+		
+		this.e1 = new Shelf(false, 1);
+		this.e2 = new Shelf(false, 2);
+		this.e3 = new Shelf(true, 2);
+		this.e4 = new Shelf(true, 2);
+		this.shelves = new ArrayList<Shelf>();
+		this.shelves.add(e1); this.shelves.add(e2); this.shelves.add(e3); this.shelves.add(e4);
+
+        this.m = new Shop(shelves);
+    }
+
+    @Test
+    public void initTest() {
+        ArrayList<Shelf> tmp = m.getShelving();
+        assertEquals(4, tmp.size());
+        assertTrue(tmp.get(0).isEmpty());
+        assertFalse(tmp.get(0).isRefrigerated());
+        assertTrue(tmp.get(1).isEmpty());
+        assertFalse(tmp.get(1).isRefrigerated());
+        assertTrue(tmp.get(2).isEmpty());
+        assertTrue(tmp.get(2).isRefrigerated());
+        assertTrue(tmp.get(3).isEmpty());
+        assertTrue(tmp.get(3).isRefrigerated());
+    }
+    @Test
+    public void tidyTest() {
+        ArrayList<Shelf> tmp = m.getShelving();
+        m.tidy(this.aStock);
+        assertTrue(tmp.get(0).isFull());
+        assertEquals(this.p2, tmp.get(0).getShelves().get(0));
+        assertFalse(tmp.get(1).isFull());
+        assertFalse(tmp.get(1).isEmpty());
+        assertEquals(this.p3, tmp.get(1).getShelves().get(0));
+        assertTrue(tmp.get(2).isFull());
+        assertEquals(this.p1, tmp.get(2).getShelves().get(0));
+        assertEquals(this.p4, tmp.get(2).getShelves().get(1));
+        assertFalse(tmp.get(3).isFull());
+        assertFalse(tmp.get(3).isEmpty());
+        assertEquals(this.p5, tmp.get(3).getShelves().get(0));
+    }
+    @Test
+    public void closeBeforeDateTest() {
+        m.tidy(this.aStock);
+        ArrayList<IProduct> res = m.closeBestBeforeDate(-3);
+        assertEquals(2, res.size());
+        assertEquals(this.p1, res.get(0));
+        assertEquals(this.p5, res.get(1));
+    }
+}
diff --git a/test/qdev/CompetitorTest.java b/test/qdev/CompetitorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..d372b2edc1c8c775ed9b6dedacaec9575c726f6a
--- /dev/null
+++ b/test/qdev/CompetitorTest.java
@@ -0,0 +1,50 @@
+package tpQU.tp04;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class CompetitorTest {
+	public Competitor c1, c2, c3, c4, c5;
+
+	@BeforeEach
+	public void beforeATest() {
+		Competitor.resetCpt();
+		this.c1 = new Competitor("Alice", Country.FRANCE, Team.TEAM_1);
+		this.c2 = new Competitor("Bruno", Country.RUSSIA, Team.TEAM_2);
+		this.c3 = new Competitor("Clément", Country.FRANCE, Team.TEAM_1);
+		this.c4 = new Competitor("Dora", Country.ITALY, Team.TEAM_3);
+		this.c5 = new Competitor("Éloïse", Country.ITALY, Team.TEAM_2);
+	}
+
+	@Test
+	public void test_getID() {
+		assertEquals(0, this.c1.getID());
+		assertEquals(1, this.c2.getID());
+		assertEquals(2, this.c3.getID());
+		assertEquals(3, this.c4.getID());
+		assertEquals(4, this.c5.getID());
+	}
+
+	@Test
+	public void test_toString() {
+		assertEquals("0-Alice(FR) -> TEAM_1", this.c1.toString());
+		assertEquals("1-Bruno(RS) -> TEAM_2", this.c2.toString());
+		assertEquals("2-Clément(FR) -> TEAM_1", this.c3.toString());
+		assertEquals("3-Dora(IT) -> TEAM_3", this.c4.toString());
+		assertEquals("4-Éloïse(IT) -> TEAM_2", this.c5.toString());
+	}
+
+	@Test
+	public void test_isFrom() {
+		// using a country
+		assertTrue(this.c1.isFrom(Country.FRANCE));
+		assertFalse(this.c1.isFrom(Country.RUSSIA));
+		// using a team
+		assertTrue(this.c1.isFrom(Team.TEAM_1));
+		assertFalse(this.c1.isFrom(Team.TEAM_2));
+	}
+}
\ No newline at end of file
diff --git a/test/qdev/RaceTest.java b/test/qdev/RaceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..7dd164fd1c426e184f95319c40cf75ba898c3b66
--- /dev/null
+++ b/test/qdev/RaceTest.java
@@ -0,0 +1,336 @@
+package tpQU.tp04;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class RaceTest {
+	private Competitor c0, c1, c2, c3, c4;
+	private Stage s0, s1, s2, s3, s4;
+	private Race r0, r1;
+
+	@BeforeEach
+	public void beforeATest() {
+		Competitor.resetCpt();
+		this.c0 = new Competitor("Alice", Country.FRANCE, Team.TEAM_1);
+		this.c1 = new Competitor("Bruno", Country.RUSSIA, Team.TEAM_2);
+		this.c2 = new Competitor("Clément", Country.FRANCE, Team.TEAM_1);
+		this.c3 = new Competitor("Dora", Country.ITALY, Team.TEAM_3);
+		this.c4 = new Competitor("Éloïse", Country.ITALY, Team.TEAM_2);
+
+		Stage.resetCpt();
+		this.s0 = new SkiingStage(1000);
+		this.s1 = new ShootingStage(5);
+		this.s2 = new SkiingStage(2000);
+		this.s3 = new ShootingStage(10);
+		this.s4 = new SkiingStage(500);
+
+		this.r0 = new Race("xxx");
+		this.r0.addCompetitor(this.c0);
+		this.r0.addCompetitor(this.c1);
+		this.r0.addCompetitor(this.c2);
+		this.r0.addCompetitor(this.c3);
+		this.r0.addStage(this.s0);
+		this.r0.addStage(this.s1);
+		this.r0.addStage(this.s2);
+		this.r0.addStage(this.s3);
+
+		this.r1 = new Race("zzz");
+
+		try {
+			this.r0.record(this.c0, this.s0, 100);
+			this.r0.record(this.c1, this.s0, 100);
+			this.r0.record(this.c2, this.s0, 110);
+			this.r0.record(this.c3, this.s0, 120);
+			this.r0.record(this.c0, this.s1, 0);
+			this.r0.record(this.c1, this.s1, 3);
+			this.r0.record(this.c2, this.s1, 1);
+			this.r0.record(this.c3, this.s1, 4);
+			this.r0.record(this.c0, this.s2, 200);
+			this.r0.record(this.c1, this.s2, 220);
+			this.r0.record(this.c2, this.s2, 180);
+			this.r0.record(this.c3, this.s2, 240);
+			this.r0.record(this.c0, this.s3, 1);
+			this.r0.record(this.c1, this.s3, 2);
+			this.r0.record(this.c2, this.s3, 0);
+			this.r0.record(this.c3, this.s3, 1);
+		} catch(Exception e) {}
+	}
+
+	@Test
+	public void test_getCompetitor() {
+		// without exception
+		boolean result = false;
+		try {
+			assertEquals(this.c0, this.r0.getCompetitor(0));
+			assertEquals(this.c1, this.r0.getCompetitor(1));
+		} catch(Exception e) {
+			result = true;
+		}
+		assertFalse(result);
+		// with Exception_UnknownCompetitor
+		result = false;
+		try {
+			this.r0.getCompetitor(4);
+		} catch(Exception_UnknownCompetitor e) {
+			result = true;
+		}
+		assertTrue(result);
+	}
+
+	@Test
+	public void test_getNbCompetitors() {
+		assertEquals(4, this.r0.getNbCompetitors());
+		this.r0.addCompetitor(this.c4);
+		assertEquals(5, this.r0.getNbCompetitors());
+	}
+
+	@Test
+	public void test_getNbTeams() {
+		assertEquals(3, this.r0.getNbTeams());
+		assertEquals(0, this.r1.getNbTeams());
+		this.r1.addCompetitor(this.c0);
+		assertEquals(1, this.r1.getNbTeams());
+	}
+
+	@Test
+	public void test_getNbCountries() {
+		assertEquals(3, this.r0.getNbCountries());
+		assertEquals(0, this.r1.getNbCountries());
+		this.r1.addCompetitor(this.c0);
+		assertEquals(1, this.r1.getNbCountries());
+	}
+
+	@Test
+	public void test_getTotalNbShots() {
+		assertEquals(15, this.r0.getTotalNbShots());
+		assertEquals(0, this.r1.getTotalNbShots());
+		this.r1.addStage(this.s1);
+		assertEquals(5, this.r1.getTotalNbShots());
+	}
+
+	@Test
+	public void test_getTotalLength() {
+		assertEquals(3000, this.r0.getTotalLength());
+		assertEquals(0, this.r1.getTotalLength());
+		this.r1.addStage(this.s0);
+		assertEquals(1000, this.r1.getTotalLength());
+	}
+
+	@Test
+	public void test_isValid() {
+		boolean result = false;
+		// -- without exception
+		try {
+			this.r0.isValid(this.c0);
+			this.r0.isValid(0);
+		} catch(Exception_UnknownCompetitor e) {
+			result = true;
+		}
+		assertFalse(result);
+		// -- with exception using Competitor
+		try {
+			this.r0.isValid(this.c4);
+		} catch(Exception_UnknownCompetitor e) {
+			result = true;
+		}
+		assertTrue(result);
+		// -- with exception using id number
+		result = false;
+		try {
+			this.r0.isValid(4);
+		} catch(Exception_UnknownCompetitor e) {
+			result = true;
+		}
+		assertTrue(result);
+	}
+
+	@Test
+	public void test_record() {
+		boolean result = false;
+		// without exception
+		try {
+			this.r1.addCompetitor(this.c0);
+			this.r1.addStage(this.s4);
+			this.r1.record(this.c0, this.s4, 10);
+		} catch(Exception_UnknownCompetitor | Exception_InvalidRecord e) {
+			result = true;
+		}
+		assertFalse(result);
+		// with Exception_InvalidRecord
+		try {
+			this.r1.record(this.c0, this.s0, 100);
+		} catch(Exception_UnknownCompetitor e) {
+		} catch(Exception_InvalidRecord e) {
+			result = true;
+		}
+		assertTrue(result);
+		result = false;
+		// with Exception_UnknownCompetitor
+		try {
+			this.r0.record(this.c4, this.s0, 50);
+		} catch(Exception_InvalidRecord e) {
+		} catch(Exception_UnknownCompetitor e) {
+			result = true;
+		}
+		assertTrue(result);
+	}
+
+	@Test
+	public void test_getScore() {
+		boolean result = false;
+		// without exception
+		try {
+			assertEquals(100, this.r0.getScore(this.c0, this.s0));
+			assertEquals(100, this.r0.getScore(0, 0));
+		} catch(Exception_UnknownCompetitor | Exception_NoResult e) {
+			result = true;
+		}
+		assertFalse(result);
+		// with Exception_NoResult -- using Competitor, not ID
+		this.r1.addCompetitor(this.c4);
+		this.r1.addStage(this.s0);
+		result = false;
+		try {
+			this.r1.getScore(this.c4, this.s0);
+		} catch(Exception_UnknownCompetitor e) {
+		} catch(Exception_NoResult e) {
+			result = true;
+		}
+		assertTrue(result);
+		// with Exception_NoResult -- using ID, not Competitor
+		result = false;
+		try {
+			this.r1.getScore(4, 0);
+		} catch(Exception_UnknownCompetitor e) {
+		} catch(Exception_NoResult e) {
+			result = true;
+		}
+		assertTrue(result);
+		// with Exception_UnknownCompetitor -- using Competitor, not ID
+		result = false;
+		try {
+			this.r0.getScore(this.c4, this.s0);
+		} catch(Exception_NoResult e) {
+		} catch(Exception_UnknownCompetitor e) {
+			result = true;
+		}
+		assertTrue(result);
+		// with Exception_UnknownCompetitor -- using ID, not Competitor
+		result = false;
+		try {
+			this.r0.getScore(4, 0);
+		} catch(Exception_NoResult e) {
+		} catch(Exception_UnknownCompetitor e) {
+			result = true;
+		}
+		assertTrue(result);
+	}
+
+	@Test
+	public void test_getCompetitorScore() {
+		assertEquals(310, this.r0.getCompetitorScore(this.c0));
+		assertEquals(370, this.r0.getCompetitorScore(this.c1));
+		assertEquals(300, this.r0.getCompetitorScore(this.c2));
+		assertEquals(410, this.r0.getCompetitorScore(this.c3));
+		assertEquals(0, this.r0.getCompetitorScore(this.c4));
+	}
+
+	@Test
+	public void test_getCountryScore() {
+		assertEquals(610.0/2, this.r0.getCountryScore(Country.FRANCE), 0.001);
+		assertEquals(370.0/1, this.r0.getCountryScore(Country.RUSSIA), 0.001);
+		assertEquals(410.0/1, this.r0.getCountryScore(Country.ITALY), 0.001);
+		assertEquals(Double.MAX_VALUE, this.r0.getCountryScore(Country.AUSTRIA), 0.001);
+	}
+
+	@Test
+	public void test_getTeamScore() {
+		assertEquals(610.0/2, this.r0.getTeamScore(Team.TEAM_1), 0.001);
+		assertEquals(370.0/1, this.r0.getTeamScore(Team.TEAM_2), 0.001);
+		assertEquals(410.0/1, this.r0.getTeamScore(Team.TEAM_3), 0.001);
+	}
+
+	@Test
+	public void test_competitorRanking() {
+		List<Competitor> expected = new ArrayList<Competitor>();
+		expected.add(this.c2);
+		expected.add(this.c0);
+		expected.add(this.c1);
+		expected.add(this.c3);
+		List<Competitor> result = this.r0.competitorRanking();
+		assertEquals(expected, result);
+	}
+
+	@Test
+	public void test_countryRanking() {
+		List<Country> expected = new ArrayList<Country>();
+		expected.add(Country.FRANCE);
+		expected.add(Country.RUSSIA);
+		expected.add(Country.ITALY);
+		expected.add(Country.AUSTRIA);
+		expected.add(Country.SWEDEN);
+		expected.add(Country.GERMANY);
+		List<Country> result = this.r0.countryRanking();
+		assertEquals(expected, result);
+	}
+
+	@Test
+	public void test_teamRanking() {
+		List<Team> expected = new ArrayList<Team>();
+		expected.add(Team.TEAM_1);
+		expected.add(Team.TEAM_2);
+		expected.add(Team.TEAM_3);
+		List<Team> result = this.r0.teamRanking();
+		assertEquals(expected, result);
+	}
+
+	@Test
+	public void test_deserterSet() {
+		this.r1.clearResult();
+		// empty deserterSet -- no competitor
+		Set<Competitor> expected = new HashSet<Competitor>();
+		this.r1.addStage(this.s0);
+		this.r1.addStage(this.s1);
+		this.r1.clearResult();
+		Set<Competitor> result = this.r1.deserterSet();
+		assertEquals(expected, result);
+		// empty deserterSet -- one competitor
+		this.r1.addCompetitor(this.c0);
+		try {
+			this.r1.record(this.c0, this.s0, 10);
+			this.r1.record(this.c0, this.s1, 10);
+		} catch(Exception e) {}
+		result = this.r1.deserterSet();
+		assertEquals(expected, result);
+		// one deserter -- all stages missing
+		expected.add(this.c1);
+		this.r1.addCompetitor(this.c1);
+		result = this.r1.deserterSet();
+		assertEquals(expected, result);
+		// two deserter -- the first stage missing
+		expected.add(this.c2);
+		this.r1.addCompetitor(this.c2);
+		try {
+			this.r1.record(this.c2, this.s1, 10);
+		} catch(Exception e) {}
+		result = this.r1.deserterSet();
+		assertEquals(expected, result);
+		// three deserter -- a stage missing (anywhere else)
+		expected.add(this.c3);
+		this.r1.addCompetitor(this.c3);
+		try {
+			this.r1.record(this.c3, this.s0, 10);
+		} catch(Exception e) {}
+		result = this.r1.deserterSet();
+		assertEquals(expected, result);
+	}
+}
diff --git a/test/qdev/StageTest.java b/test/qdev/StageTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..d1898607a28e872c93537804f4833ad4bb1ed486
--- /dev/null
+++ b/test/qdev/StageTest.java
@@ -0,0 +1,155 @@
+package tpQU.tp04;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class StageTest {
+	private Competitor c0, c1, c2, c3, c4;
+	private Stage s0, s1, s2, s3, s4;
+
+	@BeforeEach
+	public void beforeATest() {
+		Competitor.resetCpt();
+		this.c0 = new Competitor("Alice", Country.FRANCE, Team.TEAM_1);
+		this.c1 = new Competitor("Bruno", Country.RUSSIA, Team.TEAM_2);
+		this.c2 = new Competitor("Clément", Country.FRANCE, Team.TEAM_1);
+		this.c3 = new Competitor("Dora", Country.ITALY, Team.TEAM_3);
+		this.c4 = new Competitor("Éloïse", Country.ITALY, Team.TEAM_2);
+
+		Stage.resetCpt();
+		this.s0 = new SkiingStage(1000);
+		this.s1 = new ShootingStage(5);
+		this.s2 = new SkiingStage(2000);
+		this.s3 = new ShootingStage(10);
+		this.s4 = new SkiingStage(500);
+
+		boolean result = false;
+		try {
+			this.s0.record(this.c0, 100); this.s0.record(this.c1, 100);
+			this.s1.record(this.c0, 0); this.s1.record(this.c1, 3);
+			this.s2.record(this.c0, 200);
+			this.s3.record(this.c0, 1);
+			this.s4.record(this.c0, 50);
+		} catch(Exception_InvalidRecord e) {
+			result = true;
+		}
+		assertFalse(result);
+	}
+
+	@Test
+	public void test_getID() {
+		assertEquals(0, this.s0.getID());
+		assertEquals(1, this.s1.getID());
+		assertEquals(2, this.s2.getID());
+		assertEquals(3, this.s3.getID());
+		assertEquals(4, this.s4.getID());
+	}
+
+	@Test
+	public void test_getType() {
+		assertEquals("Skiing", this.s0.getType());
+		assertEquals("Shooting", this.s1.getType());
+		assertEquals("Skiing", this.s2.getType());
+		assertEquals("Shooting", this.s3.getType());
+		assertEquals("Skiing", this.s4.getType());
+	}
+
+	@Test
+	public void test_getNbShots() {
+		assertEquals(0, this.s0.getNbShots());
+		assertEquals(5, this.s1.getNbShots());
+		assertEquals(0, this.s2.getNbShots());
+		assertEquals(10, this.s3.getNbShots());
+		assertEquals(0, this.s4.getNbShots());
+	}
+
+	@Test
+	public void test_getLength() {
+		assertEquals(1000, this.s0.getLength());
+		assertEquals(0, this.s1.getLength());
+		assertEquals(2000, this.s2.getLength());
+		assertEquals(0, this.s3.getLength());
+		assertEquals(500, this.s4.getLength());
+	}
+
+	@Test
+	public void test_clear() {
+		assertFalse(this.s0.results.size()==0);
+		this.s0.clear();
+		assertTrue(this.s0.results.size()==0);
+	}
+
+	@Test
+	public void test_record() {
+		// without exception
+		assertEquals(2, this.s0.getNbRecord());
+		assertEquals(2, this.s1.getNbRecord());
+		assertEquals(1, this.s2.getNbRecord());
+		assertEquals(1, this.s3.getNbRecord());
+		assertEquals(1, this.s4.getNbRecord());
+		// with Exception_InvalidRecord
+		boolean result = false;
+		try {
+			this.s0.record(this.c0, 100);
+		} catch(Exception_InvalidRecord e) {
+			result = true;
+		}
+		assertTrue(result);
+	}
+
+	@Test
+	public void test_getScore() {
+		// without exception
+		boolean result = false;
+		try {
+			assertEquals(100, this.s0.getScore(this.c0));
+			assertEquals(0, this.s1.getScore(this.c0));
+			assertEquals(100, this.s0.getScore(this.c1));
+			assertEquals(3*10, this.s1.getScore(this.c1));
+			List<Competitor> tmp = new ArrayList<Competitor>();
+			tmp.add(this.c0); tmp.add(this.c1);
+			assertEquals(200, this.s0.getScore(tmp));
+		} catch(Exception_NoResult e) {
+			result = true;
+		}
+		assertFalse(result);
+		// with Exception_NoResult
+		// a competitor alone
+		result = false;
+		try {
+			this.s0.getScore(this.c4);
+		} catch(Exception_NoResult e) {
+			result = true;
+		}
+		assertTrue(result);
+		// with Exception_NoResult
+		// a list of non-existant competitor only
+		result = false;
+		List<Competitor> tmp = new ArrayList<Competitor>();
+		tmp.add(this.c2); tmp.add(this.c3);
+		try {
+			this.s0.getScore(tmp);
+		} catch(Exception_NoResult e) {
+			result = true;
+		}
+		assertTrue(result);
+		// with Exception_NoResult
+		// a mixed list
+		result = false;
+		tmp = new ArrayList<Competitor>();
+		tmp.add(this.c0); tmp.add(this.c1); tmp.add(this.c3);
+		try {
+			this.s0.getScore(tmp);
+		} catch(Exception_NoResult e) {
+			result = true;
+		}
+		assertTrue(result);
+	}
+}