From bba5d3b75aefe857d966178ad6bdc51372eea6fc Mon Sep 17 00:00:00 2001
From: Lucas Philippe <lucasphilippe@MacBook-Air-de-Lucas.local>
Date: Thu, 1 Feb 2024 13:34:24 +0100
Subject: [PATCH] Ajout TP2 fonctionnel

---
 TP1/BubbleCursor.py                           |   3 +-
 TP1/BubbleWidget.py                           |  52 ++++---
 TP1/MainBubble.py                             |   6 +-
 TP1/MainNormal.py                             |   8 +-
 TP1/MainRope.py                               |   4 +-
 TP1/NormalCursor.py                           |  21 +--
 TP1/NormalWidget.py                           |  58 +++++---
 TP1/README.md                                 |   2 +
 TP1/RopeWidget.py                             |  43 +++---
 TP1/__init__.py                               |   0
 TP1/__pycache__/BubbleCursor.cpython-39.pyc   | Bin 1374 -> 1248 bytes
 TP1/__pycache__/BubbleWidget.cpython-39.pyc   | Bin 1630 -> 2226 bytes
 TP1/__pycache__/Target.cpython-39.pyc         | Bin 930 -> 1169 bytes
 TP1/experience/ExpSetup.py                    | 127 ++++++++++++++++++
 TP1/experience/Experience.py                  |  22 +++
 TP1/experience/FileDisplayWidget.py           |  15 +++
 TP1/experience/Generate_targets.py            |  52 +++++++
 TP1/experience/MainExp.py                     |  15 +++
 TP1/experience/data/__init__.py               |   0
 TP1/experience/data/response.csv              |  15 +++
 .../generated_exp/src_d_30_s_12.csv           |  30 +++++
 .../generated_exp/src_d_30_s_18.csv           |  30 +++++
 TP1/experience/generated_exp/src_d_30_s_9.csv |  30 +++++
 .../generated_exp/src_d_60_s_12.csv           |  60 +++++++++
 .../generated_exp/src_d_60_s_18.csv           |  60 +++++++++
 TP1/experience/generated_exp/src_d_60_s_9.csv |  60 +++++++++
 .../generated_exp/src_d_90_s_12.csv           |  88 ++++++++++++
 .../generated_exp/src_d_90_s_18.csv           |  88 ++++++++++++
 TP1/experience/generated_exp/src_d_90_s_9.csv |  88 ++++++++++++
 29 files changed, 913 insertions(+), 64 deletions(-)
 create mode 100644 TP1/__init__.py
 create mode 100644 TP1/experience/ExpSetup.py
 create mode 100644 TP1/experience/Experience.py
 create mode 100644 TP1/experience/FileDisplayWidget.py
 create mode 100644 TP1/experience/Generate_targets.py
 create mode 100644 TP1/experience/MainExp.py
 create mode 100644 TP1/experience/data/__init__.py
 create mode 100644 TP1/experience/data/response.csv
 create mode 100644 TP1/experience/generated_exp/src_d_30_s_12.csv
 create mode 100644 TP1/experience/generated_exp/src_d_30_s_18.csv
 create mode 100644 TP1/experience/generated_exp/src_d_30_s_9.csv
 create mode 100644 TP1/experience/generated_exp/src_d_60_s_12.csv
 create mode 100644 TP1/experience/generated_exp/src_d_60_s_18.csv
 create mode 100644 TP1/experience/generated_exp/src_d_60_s_9.csv
 create mode 100644 TP1/experience/generated_exp/src_d_90_s_12.csv
 create mode 100644 TP1/experience/generated_exp/src_d_90_s_18.csv
 create mode 100644 TP1/experience/generated_exp/src_d_90_s_9.csv

diff --git a/TP1/BubbleCursor.py b/TP1/BubbleCursor.py
index 49d54c0..d4eed38 100644
--- a/TP1/BubbleCursor.py
+++ b/TP1/BubbleCursor.py
@@ -30,5 +30,4 @@ class BubbleCursor:
         if previous_closest != self.closest:
             if previous_closest:
                 previous_closest.highlighted = False
-            self.closest.highlighted = True
-
+            self.closest.highlighted = True
\ No newline at end of file
diff --git a/TP1/BubbleWidget.py b/TP1/BubbleWidget.py
index 4b20faf..22f8a86 100644
--- a/TP1/BubbleWidget.py
+++ b/TP1/BubbleWidget.py
@@ -1,26 +1,36 @@
-import csv, random, time
+import csv
+import random
+
+import time
 from PyQt5.QtGui import QPainter
 from PyQt5.QtWidgets import QWidget
-from Target import Target
+
 from BubbleCursor import BubbleCursor
+from Target import Target
+
 
 class BubbleWidget(QWidget):
-    def __init__(self):
+    def __init__(self, file_name, exp_setup, number_of_targets):
         super().__init__()
+        self.exp_setup = exp_setup
         self.targets = []
-        self.loadTargets()
-        self.cursor = BubbleCursor(self.targets)
         self.setMouseTracking(True)
         self.start_time = None
-        self.selectRandomTarget()
+        self.errors = 0
 
-    def loadTargets(self):
-        with open('src_tp_bubble.csv', newline='') as csvfile:
+        # Chargement du fichier csv
+        with open(file_name) as csvfile:
             reader = csv.reader(csvfile)
             for row in reader:
-                if len(row) >= 3:
-                    x, y, size = map(int, row[:3])
-                    self.targets.append(Target(x,y,size))
+                x = int(row[0])
+                y = int(row[1])
+                size = int(row[2])
+                target = Target(x, y, size)
+                self.targets.append(target)
+
+        self.target_to_select = self.targets[:number_of_targets]
+        self.cursor = BubbleCursor(self.targets)
+        self.selectRandomTarget()
 
     def paintEvent(self, event):
         painter = QPainter(self)
@@ -35,15 +45,23 @@ class BubbleWidget(QWidget):
     def selectRandomTarget(self):
         if self.start_time == None:
             self.start_time = time.time()
-        target = random.choice(self.targets)
+        target = self.target_to_select.pop()
         target.toSelect = True
         self.update()
 
-    def printTime(self):
-        print((time.time() - self.start_time)*1000)
+    def printLog(self):
+        current_time = (time.time() - self.start_time)*1000
+        self.exp_setup.add_line_to_response(current_time, self.errors)
+        self.errors = 0
         self.start_time = None
 
     def mousePressEvent(self, event):
-        if self.cursor.closest.click_cible():
-            self.printTime()
-            self.selectRandomTarget()
\ No newline at end of file
+        if self.cursor.closest is not None:
+            if self.cursor.closest.click_cible():
+                self.printLog()
+                if len(self.target_to_select) > 0:
+                    self.selectRandomTarget()
+                else:
+                    self.exp_setup.next_experience()
+            else:
+                self.errors += 1
diff --git a/TP1/MainBubble.py b/TP1/MainBubble.py
index 22990ba..bbfdcf3 100644
--- a/TP1/MainBubble.py
+++ b/TP1/MainBubble.py
@@ -3,14 +3,18 @@ import sys
 from PyQt5.QtGui import QPainter
 from PyQt5.QtWidgets import QApplication, QMainWindow
 from BubbleWidget import BubbleWidget
+
+file_name = "data/src_tp_bubble.csv"
 def main():
     app = QApplication(sys.argv)
     main_window = QMainWindow()
     main_window.resize(1024, 800)
-    bubble_widget = BubbleWidget()
+    bubble_widget = BubbleWidget(file_name)
     main_window.setCentralWidget(bubble_widget)
     main_window.show()
     sys.exit(app.exec_())
 
 if __name__ == "__main__":
+    if len(sys.argv) == 2:
+        file_name = sys.argv[1]
     main()
diff --git a/TP1/MainNormal.py b/TP1/MainNormal.py
index 73a04e5..d932cb9 100644
--- a/TP1/MainNormal.py
+++ b/TP1/MainNormal.py
@@ -1,13 +1,19 @@
+import sys
+
 from PyQt5.QtWidgets import QApplication, QMainWindow
 from NormalWidget import NormalWidget
+
+file_name = "data/src_tp_bubble.csv"
 def main():
     app = QApplication([])
     window = QMainWindow()
     window.resize(1024, 800)
-    normalWidget = NormalWidget()
+    normalWidget = NormalWidget(file_name)
     window.setCentralWidget(normalWidget)
     window.show()
     app.exec_()
 
 if __name__ == "__main__":
+    if len(sys.argv) == 2:
+        file_name = sys.argv[1]
     main()
diff --git a/TP1/MainRope.py b/TP1/MainRope.py
index e9519fb..dd1c364 100644
--- a/TP1/MainRope.py
+++ b/TP1/MainRope.py
@@ -1,10 +1,12 @@
 from PyQt5.QtWidgets import QApplication, QMainWindow
 from RopeWidget import RopeWidget
+
+file_name = "data/src_tp_bubble.csv"
 def main():
     app = QApplication([])
     window = QMainWindow()
     window.resize(1024, 800)
-    bubble_widget = RopeWidget()
+    bubble_widget = RopeWidget(file_name)
     window.setCentralWidget(bubble_widget)
     window.show()
     app.exec_()
diff --git a/TP1/NormalCursor.py b/TP1/NormalCursor.py
index a2339e2..bc38c2d 100644
--- a/TP1/NormalCursor.py
+++ b/TP1/NormalCursor.py
@@ -11,16 +11,19 @@ class NormalCursor:
     def move(self, x, y):
         self.x = x
         self.y = y
-        previous_closest = self.closest
+        closest_target = None
+        min_distance = float('inf')
 
         for target in self.targets:
-            distance = ((self.x - target.x) ** 2 + (self.y - target.y) ** 2) ** 0.5  # cf. Theoreme de Pythagore
+            distance = ((self.x - target.x) ** 2 + (self.y - target.y) ** 2) ** 0.5
+            if distance < min_distance:
+                min_distance = distance
+                closest_target = target
 
-            if distance < target.size/2:
-                self.closest = target
-                self.closest.highlighted = True
+        if closest_target and min_distance < closest_target.size / 2:
+            closest_target.highlighted = True
+        else:
+            if self.closest and self.closest != closest_target:
+                self.closest.highlighted = False
 
-        if previous_closest is not None:
-            distance = ((self.x - previous_closest.x) ** 2 + (self.y - previous_closest.y) ** 2) ** 0.5  # cf. Theoreme de Pythagore
-            if distance > previous_closest.size / 2:
-                previous_closest.highlighted = False
\ No newline at end of file
+        self.closest = closest_target
\ No newline at end of file
diff --git a/TP1/NormalWidget.py b/TP1/NormalWidget.py
index 9f34fb9..2cbcbe7 100644
--- a/TP1/NormalWidget.py
+++ b/TP1/NormalWidget.py
@@ -1,26 +1,35 @@
-import csv, random, time
+import csv
+import random
+
+import time
 from PyQt5.QtGui import QPainter
 from PyQt5.QtWidgets import QWidget
+
+from NormalCursor import NormalCursor
 from Target import Target
-from TP1.NormalCursor import NormalCursor
 
 class NormalWidget(QWidget):
-    def __init__(self):
+    def __init__(self, file_name, exp_setup, number_of_targets):
         super().__init__()
         self.targets = []
-        self.loadTargets()
-        self.cursor = NormalCursor(self.targets)
         self.setMouseTracking(True)
         self.start_time = None
-        self.selectRandomTarget()
+        self.exp_setup = exp_setup
+        self.errors = 0
 
-    def loadTargets(self):
-        with open('src_tp_bubble.csv', newline='') as csvfile:
+        # Chargement du fichier csv
+        with open(file_name) as csvfile:
             reader = csv.reader(csvfile)
             for row in reader:
-                if len(row) >= 3:
-                    x, y, size = map(int, row[:3])
-                    self.targets.append(Target(x,y,size))
+                x = int(row[0])
+                y = int(row[1])
+                size = int(row[2])
+                target = Target(x, y, size)
+                self.targets.append(target)
+
+        self.target_to_select = self.targets[:number_of_targets]
+        self.cursor = NormalCursor(self.targets)
+        self.selectRandomTarget()
 
     def paintEvent(self, event):
         painter = QPainter(self)
@@ -32,17 +41,30 @@ class NormalWidget(QWidget):
         self.update()
 
     def selectRandomTarget(self):
-        if self.start_time == None:
+        if self.start_time is None:
             self.start_time = time.time()
-        target = random.choice(self.targets)
+
+        target = self.target_to_select.pop()
         target.toSelect = True
         self.update()
 
-    def printTime(self):
-        print((time.time() - self.start_time)*1000)
+    def printLog(self):
+        current_time = (time.time() - self.start_time)*1000
+        self.exp_setup.add_line_to_response(current_time, self.errors)
+        self.errors = 0
         self.start_time = None
 
     def mousePressEvent(self, event):
-        if self.cursor.closest.click_cible():
-            self.printTime()
-            self.selectRandomTarget()
+        if self.cursor.closest is not None and self.cursor.closest.toSelect:
+            distance = ((event.x() - self.cursor.closest.x) ** 2 + (event.y() - self.cursor.closest.y) ** 2) ** 0.5
+            if distance <= self.cursor.closest.size / 2:
+                if self.cursor.closest.click_cible():
+                    self.printLog()
+                    if len(self.target_to_select) > 0:
+                        self.selectRandomTarget()
+                    else:
+                        self.exp_setup.next_experience()
+                else:
+                    self.errors += 1
+            else:
+                self.errors += 1
\ No newline at end of file
diff --git a/TP1/README.md b/TP1/README.md
index e69de29..1087c3c 100644
--- a/TP1/README.md
+++ b/TP1/README.md
@@ -0,0 +1,2 @@
+# Programmation d'une technique d'interaction : le Bubble Cursor
+
diff --git a/TP1/RopeWidget.py b/TP1/RopeWidget.py
index 2aafc7a..93bb765 100644
--- a/TP1/RopeWidget.py
+++ b/TP1/RopeWidget.py
@@ -5,22 +5,27 @@ from Target import Target
 from RopeCursor import RopeCursor
 
 class RopeWidget(QWidget):
-    def __init__(self):
+    def __init__(self, file_name, exp_setup, number_of_targets):
         super().__init__()
+        self.exp_setup = exp_setup
         self.targets = []
-        self.loadTargets()
-        self.cursor = RopeCursor(self.targets)
         self.setMouseTracking(True)
         self.start_time = None
-        self.selectRandomTarget()
+        self.errors = 0
 
-    def loadTargets(self):
-        with open('src_tp_bubble.csv', newline='') as csvfile:
+        # Chargement du fichier csv
+        with open(file_name) as csvfile:
             reader = csv.reader(csvfile)
             for row in reader:
-                if len(row) >= 3:
-                    x, y, size = map(int, row[:3])
-                    self.targets.append(Target(x,y,size))
+                x = int(row[0])
+                y = int(row[1])
+                size = int(row[2])
+                target = Target(x, y, size)
+                self.targets.append(target)
+
+        self.target_to_select = self.targets[:number_of_targets]
+        self.cursor = RopeCursor(self.targets)
+        self.selectRandomTarget()
 
     def paintEvent(self, event):
         painter = QPainter(self)
@@ -35,15 +40,23 @@ class RopeWidget(QWidget):
     def selectRandomTarget(self):
         if self.start_time == None:
             self.start_time = time.time()
-        target = random.choice(self.targets)
+        target = self.target_to_select.pop()
         target.toSelect = True
         self.update()
 
-    def printTime(self):
-        print((time.time() - self.start_time)*1000)
+    def printLog(self):
+        current_time = (time.time() - self.start_time)*1000
+        self.exp_setup.add_line_to_response(current_time, self.errors)
+        self.errors = 0
         self.start_time = None
 
     def mousePressEvent(self, event):
-        if self.cursor.closest.click_cible():
-            self.printTime()
-            self.selectRandomTarget()
+        if self.cursor.closest is not None:
+            if self.cursor.closest.click_cible():
+                self.printLog()
+                if len(self.target_to_select) > 0:
+                    self.selectRandomTarget()
+                else:
+                    self.exp_setup.next_experience()
+            else:
+                self.errors += 1
diff --git a/TP1/__init__.py b/TP1/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/TP1/__pycache__/BubbleCursor.cpython-39.pyc b/TP1/__pycache__/BubbleCursor.cpython-39.pyc
index 4d49281a3a479273257899a9b740c614c215d99e..e3cc227bd4c22cca27fc49eff4e11c2714483ea4 100644
GIT binary patch
delta 586
zcmY*W%W4!s6s=pY>3L*~MB`vU6a*PCu5_tFMkNcGjjjUH^rUJsoph$Psyd3+FpFfF
zg`t1I?6S>I#DD08WGAi#*WPLq(Q59kbGq*1+^TP_^JX_$SZEPkKYyL*ul%T+!u_KU
ztG!pG->f=o#b}i2L1AoeDn7~zeR|e}d4%x;H2V^rhcCpFZ8!!9m^y}xqlq5bhnmU%
zm{4%-^5g;^b0CUfPdfZTv1Y$fMOM2tQ`kw>QhJ;enH%I;)mA2XUp}D?QL%LD%IEYE
zbjnY3b>6@<j#lgXT<h{ACZ3`PM-}YDEGT2Mpp8ExZ-z60h<LG0dPLEsdJ1Ilhut8G
zEs>e@68{NBS1_t(Y=@YMmskz+W9G4HEavZS`%sweFmvd+IZ)j5SgO#1;U0#Q!ytNW
zuAsUtG+gITU%c)&j6`U{1eF+PdE!iX64MMW+;!ESq+62=&1r?<?QrlnXQQ*5PFG@;
zT9-^W^~T~`qxaIhu<>S=TWwuguzQaeF~{CQM?m5ifut?C3tdD!aAaZsc=g{mf3TbH
f>0v)APxwQ5J#@WUe&=^OK~#h}k&Jk`EY^Pm1;U0d

delta 684
zcmY*VPiqrF6n}4KcC))_QcH`eijbmE_E15no&>@4;AugULk-BX$xK7ibQfngB4tAk
z6+D-{c(eHk-n{q``~rKB9=!Mwy!mEhYn|b}`Mo#q@9)z6;WeX1!vi`$zkXJ~`FV4U
z`{(cXcBK0O`i}Iv;MdEw7qh`&syZ{BCc3mnTB-QUHy67#O6-uN&q(EX0Xa-?iD)n*
z%t^$y@mkkNNZc}>>Rk#13DkrIzZli<?ZRgdidXCjHj0mIZ();DkW^g`t1dZ&kW=*#
zCDjR8#wDKNyy|rTZ`yN_!-bWLCC;tf%K0(qc5cx>`9t=$O}&|f8S0)iGqTXGCg4HI
z$MI3muW8d%o85F^xGAlpX%c1HHTaesr&$yaRWIp9dZe<_$&#*`s$u5ax=tZ|>m+%n
z4p-0Xe*I(|AN<WJzVqG12F0YeNdel`b(n`9Iw;Vf(~X;KKQgt3hMKFx30yPslnmN|
z_@2NvNZd3Ql7%a)1(I#ToMns{!wE5UZ$W`)NR;zHuT%PHRrvC`Fa9lF@@SB1hrWDX
zEv4@e?l-TN@2EJ_O0SV~r5XmcNVQ2)GaukXJiY(lE>(8(26ut)7LUb#eT%~NU87pX
VvDj%E)*WKQsX4+~FFuKve*htAl2`x$

diff --git a/TP1/__pycache__/BubbleWidget.cpython-39.pyc b/TP1/__pycache__/BubbleWidget.cpython-39.pyc
index 3e9ebd96cf92dcab43c8065bb5482a9f7eccc59e..3f7d594363ce5f597ab00b02311700104235408b 100644
GIT binary patch
literal 2226
zcmZ`)OK%)S5bo}I?yg?}6P#cv5${FBiz9K1P#~ZX30rn-6frUyji=l8*s~9J_d0kr
zds?HM5PxBP^k3>L7xEW4AgX$HogGKaXsWAU(^X%6Rh`Vw*9koTvMXUcLjJ<e?Bhb`
zF??zd1Sg#4Br01PQQKz`gO=q^+l^d`b58EH{m8evn+NS63aswsVLOaMN}dw#^WcK;
zK=>mks&TqQn&E3WfowLZ3AeYBtfPelJ=lJc@k60O^>-6lYIEQ9_xE%0q%T!hrnqhP
zaV8!06DWe9nGt(M4k)LbU4)Ut9qwL`$mJgQq4jvcLuh?o<8^2Q-r#f4hJ2ncKwEo7
zToTp6#6>eXxwI*zGsmKiC*!9cgV1C|#`Ka<a!3jivx1Br>}j_k$81Dl%!4tX(@To*
zKtF(fh-*06Ay;g3w^=iu>i2{+VH{_jOvkYaw1q*LM&3<$iHVXBJ7WCQA`&erp*OmH
zC3a<!o@AXvQ&+G{$2w~Z^Ntd^NcHoi!@KQr{}nYZj2=K+i{ms;l#1gk^3S)epOuiR
zmG{#`^^USU>-9uyW4*QWu=VWOj~lJ&*n=!PYPWW`)>~z0N`TgS=duQdh485b5QNsL
zPeVFq+rfL4#ZwO}um+RuPw*E72n`(Mj5~j@Klg@I(=jUmz#%Kx_vF_{Lq|J>Gosu*
z@#Ly@wO2U6NcVSkhm6>sGjxaE(1!r{<3NXnTX+R95Cd?!`T}5g;T<`Ybe7hM>U;&E
z!1tF)NSfZ};FgkUtb6gkrQlks&I|!^1|9J-&pP5Y#vj7wc6*{@9Gv#0NH~Ph$#JBe
z^o#@SmY8?OPXN#kmzZYFKrTTO1+eKL%Z0p)Jx6w58v2`|=MbW7AmqC+T8d@V8X#`L
zr{+Kqx&X)`zAJRFQbBiyEGfgKlLt@6&jP##iUuZ*5KwZA;4%aUbO+#F7y`J{vD3Sj
zrF66DO8lWj10t`7scW5sarDP{;!JdO6xbQS!7mAX!x2-r^FQF)JFrb5X~={tgZC@G
zyjfXs1+Bn5u&#Uv3YZNkSb!Us1SF*2B|~S%?lj3HE^B(F?QXk!CgeRBk@rCuzu)7D
z7FW#rAwR;2D*9%jjcK+4`>f%(S0S2&-ll^ODn?gVR!EM9BX6wX4?#i0IXPi+83+zF
z1Zo4(Z0x|e3uK2%R?xC~Tswk^0t}jm#<(`meQ7g1^3$VkmI@n_DAe5@oBr}s+%R$N
zW6*E7CNW>pWo0i2pj91c<<r5vidS#fl8R^3s%SmC4}a5S>d`S<fmB`wu1%^RTq96p
z*=F`PV9|7p*ON%4ChW3q$wky|1fXUY?LuAq0%qS}f4gGk^`f`<g3w<Zhp;2*FNs{8
zmh1mzOOWPWC6taDX`ZDgahk!EB)>!(5jy!9iW}B0S`utYp_Jtd=9}_C5WqI1gVl=F
zHx@S=cnfrrwt!op9>?u2@8_t`#qnuB$;%mAaBWqPpP&Vwqp${9(;h(A%ui~3D)Kyz
zXN<%`B5hegqmWXzY(qh*g<<H2ZWx5F#JOf&VwOro-G<0Cw$8Wp*K6DQX+N_C!7NTk
m%G*Fmh%2$B&R$pcKQo70tnhFXJ}Q0t2I*t@w*vUsm;DF5{_&jv

delta 797
zcmZ8f!EO^V5cPPy>rF_~f<zRF3L+su%cUFw7b?U7R1Sd)MZiiZTE#93+D(GJ2~cg-
zLlB&!{Q$BYkhpMwPe6iy@S)$r*lkt7E6>innXzZy`1{$zMk{GH>jc;5U!P=$En6G?
zK3akZNJ(t}G=+@D6s+#0UdCePbe8&=ANx-C(;y4t0LV5Gf#C0n;F2x8m@hv(h2HXT
zv;L7V67$C-s+F5?sZQ|@54Y}>&)`~Hkb(>X0Vug37)2lLL}6LM&2~-aiOP3InT%_@
zBc=0)levt_kjCv053pM|P!Om?03kGf>`{Pz4G|M0)2SQ_#n6bjvSBeF>iO;{m8xwm
zPfgw!cx&LDVS2PD)f%ElV%=(%n)ULx_u$|bYB{p903bOQx`2IJkXQ5`dC}VU3UB2V
zv_jwOHlpmrI&Nlm4zs7pXq?}l%W>Ydb)`SQM!xZ<3Q=YGP_Aa*g{d<LM9h_Jd^wkQ
z$GPFoC6x(~l9w|7uUJz*y`h8Y+RYUy36Yvc`Gxfkt|NTX1eOUaTENPy2ufCw3Wr>f
zm0uA%R5yj0WhtA?w6wJUTYR7{qSIAsScYzO!P*-rOfZ{@B$p9&9jLB#tPyPRnA>v8
z@9+Ro0%7^w?^2xhH-6=b9j7B*UAEd)6s9>C4AVsGp-j`k;IF2eHpGp|p2Tr$_avYZ
m;^NApQK-(B+u`jSr-OBxO*7$EHW9N_-T|9y>B9GO^wB@;_@=c0

diff --git a/TP1/__pycache__/Target.cpython-39.pyc b/TP1/__pycache__/Target.cpython-39.pyc
index 23ca47c2f5451c35bafb6733925f0380401c87fa..947e9a63a4839aed0cd1353eae11b904ae83af75 100644
GIT binary patch
literal 1169
zcmZWoO>fgc5ZzsW#EG3ys)CT<fH)xeK&>KiqCyoFEj=_!lydRKa=qKe#ra_Eh$c!;
z?GI^h@Rxk$)IY$16K|ZPieRmMvpX}Ioq02ko6QEpy8Qh^bqvOS(Pe!>$M&%E*8s^R
z&)9&6d>}$GFhYZ~LnehZZkRN#MQBR1$9(G^zRWjDySqQiMjG;?p5*<~>~_>JA>;ZI
zxa?u)y8y*PE?Fp)A^9~AO-KQ0K^l;@G^KUJ!kV;Y4bqX0tV7mi0}s2UeG=<)RfN{L
zR%#d;TFKBn%_b@_5q!1iOt0=^=dS>BK4%e|3m~5xKp{zk9Dt@|h%MR&zE$$el21!B
zPiLxhicwExDk)00pPu(K>_SQ3gjr>0+D2SmBX9senf4(5ybr$QO6Nf~N#cCmPqTD9
zR>AR3(0dyk9eq9yR=PK7+8+cbot<D&()M^-I#HAk(;|xM2$ffj<M#5KJzDy$d=jc~
zwWy7hOI7h4hdH}oSE%=b>n)(T5<?Ht&@X`|Ed16g>^Zo<;~f0l)(U6sRxcXxbFn?i
zpR;G|npc|Ue;RLTfxI(0MyTTQo|5xhWkag7c#;*E6HP^x?ut~>P=%%UKrU3FldGZ{
zCQT)UHm;Z{O&twgspIdTGEkbU(nyEJq6b8O)d=6vE=8=3V;GeVt%Sz2YRm$fWVR~v
z297xa<F>H5Lo|yPZ}FM8Y6wM1IJqnroge0E3m34#^hPyB_)U8FeNes8J~;7tRW1Z&
z^lt`klBLPlC`nH<^#b;sN<bd?Og`IOzQ5+w_8T-D!+4;gsBA>hU?e9QoxLdfHi@%^
zMN@K`iqe||j|o}?PY9k8(3GwLF`_L1F`Sdp0T=j$Q**q^(#C(`cBb9p-FCM)oTQ6a
cs6AC%DxbB8)dLmL&h8@355!wexosJL0Wc-^hX4Qo

delta 575
zcmZutJxc>Y5Z&2Ja(Bs@K(G)Lv9R!(XrY~m7$jg33`up}kzJF><%78kq6AWCVIe}u
z5AdV&AK2O3*xx_!UpTV{RB(^?cHY~Wxt*Q4&vr3fTFMJrt+xk#D`&;E`Z_5k6hxvA
z0f49pC6#p}lyxlwsWMIBXFs{bhcwry4x=HqS^i#<#33Qxo!#$og**GWD`&{TEK`o?
zMPPp3hZAt-udp-a61J;^SP@OcxxnQKJOV}XiEc93pvc0lg_kj&w@_JD6z3?%CO8UK
z#R_+E|0svmQwC^8x|ghf@{j%e6m8lAC)UXkj^l1xNQO-v>2^XBqC;n?*X?z>5rM5V
zuk=|sjyMhq3d4)zDC&)3jb=)o#Ej}obh+3bg}p(d5&5;hsla~L_$9GPQ+s3x$U%`I
zJ-G5(A$D|9F*$YLoxfY#(-Jo*GI2hZnSPp@h&!W2#E98)z<koNjbHbzv~YUaNcJj?
dq&Ds$KY}^=uT|>o_lIg6=>wonBIaaIegVMjaJ>Kk

diff --git a/TP1/experience/ExpSetup.py b/TP1/experience/ExpSetup.py
new file mode 100644
index 0000000..0ea14e7
--- /dev/null
+++ b/TP1/experience/ExpSetup.py
@@ -0,0 +1,127 @@
+import os
+import sys
+
+from PyQt5.QtGui import QIntValidator
+from PyQt5.QtWidgets import QDialog, QLabel, QLineEdit, QComboBox, QGridLayout, QPushButton, QHBoxLayout, QVBoxLayout
+
+from Experience import Experience
+from FileDisplayWidget import FileDisplayWidget
+
+DIR_PATH = "experience/generated_exp/"
+TARGETS_PER_EXPERIENCE = 15
+
+class ExpSetup(QDialog):
+    def __init__(self, window):
+        super().__init__()
+
+        self.file_name = 'experience/data/response.csv'
+        self.current_ordonnance = None
+        self.ordonnance = None
+        self.window = window
+
+        self.user_number = None
+        self.technique = None
+        self.repeats = None
+
+        self.current_repeat_series = 0
+        self.current_target_number = 1
+
+        user_label = QLabel("Numéro d'utilisateur :")
+        self.user_edit = QLineEdit()
+        self.user_edit.setValidator(QIntValidator())
+
+        tech_label = QLabel("Technique :")
+        self.tech_combo = QComboBox()
+        self.tech_combo.addItems(["Bubble", "Rope", "Normal"])
+        repeats_label = QLabel("Nombre de répétitions :")
+        self.repeats_edit = QLineEdit()
+        self.repeats_edit.setValidator(QIntValidator())
+
+        layout = QGridLayout()
+        layout.addWidget(user_label, 0, 0)
+        layout.addWidget(self.user_edit, 0, 1)
+        layout.addWidget(tech_label, 1, 0)
+        layout.addWidget(self.tech_combo, 1, 1)
+        layout.addWidget(repeats_label, 4, 0)
+        layout.addWidget(self.repeats_edit, 4, 1)
+
+        self.validate_button = QPushButton("Valider")
+        self.validate_button.clicked.connect(self.verify_entry)
+
+        h_layout = QHBoxLayout()
+        h_layout.addStretch()
+        h_layout.addWidget(self.validate_button)
+        h_layout.addStretch()
+        v_layout = QVBoxLayout()
+        v_layout.addLayout(layout)
+        v_layout.addLayout(h_layout)
+
+        self.setLayout(v_layout)
+
+    def verify_entry(self):
+        self.user_number = self.user_edit.text()
+        self.technique = self.tech_combo.currentIndex()
+        self.repeats = int(self.repeats_edit.text())
+        if self.repeats <= 1:
+            print('Répétition doit être strictement supérieur à 1')
+        else:
+            self.init_ordonnance()
+            self.next_experience()
+
+    def create_experience(self, experience, density, target_size):
+        if experience not in Experience:
+            # Error
+            print('Aucune expérience selectionné')
+            return None
+
+        density = str(density)
+        target_size = str(target_size)
+        file_name = "src_d_" + density + "_s_" + target_size + ".csv"
+
+        file_path = DIR_PATH + file_name
+        return experience.create_widget(file_path, self, TARGETS_PER_EXPERIENCE)
+
+    def start_experience(self, widget):
+        if widget is not None:
+            self.window.resize(1024, 800)
+            self.window.setCentralWidget(widget)
+            self.window.show()
+
+    def init_ordonnance(self):
+        self.ordonnance = []
+        self.current_ordonnance = -1
+        experience_list = [Experience.BUBBLE, Experience.ROPE, Experience.NORMAL]
+        experience_ordered = experience_list[self.technique:] + experience_list[:self.technique]
+        density_list = [30, 60, 90]
+        size_list = [9, 12, 18]
+
+        # Répéter la création des widgets pour chaque expérience en fonction du nombre de répétitions
+        for _ in range(self.repeats):  # Répéter pour le nombre total de répétitions
+            for experience in experience_ordered:
+                for density in density_list:
+                    for size in size_list:
+                        widget = self.create_experience(experience, density, size)
+                        self.ordonnance.append((widget, experience, density, size))
+
+    def next_experience(self):
+        self.current_target_number = 1
+        self.current_ordonnance += 1
+        if self.current_ordonnance >= len(self.ordonnance):
+            self.display_data()
+            return
+
+        if self.current_ordonnance % (len(self.ordonnance) / self.repeats) == 0:
+            self.current_repeat_series += 1
+
+        widget = self.ordonnance[self.current_ordonnance][0]
+        self.start_experience(widget)
+
+    def add_line_to_response(self, time, error):
+        line = f"{self.user_number}, {self.current_repeat_series}, {self.current_target_number}, {self.ordonnance[self.current_ordonnance][2]}, {self.ordonnance[self.current_ordonnance][3]}, {self.ordonnance[self.current_ordonnance][1].name}, {time}, {error}"
+        with open(self.file_name, "a") as file:
+            file.write(line + '\n')
+        self.current_target_number += 1
+
+    def display_data(self):
+        widget = FileDisplayWidget(self.file_name)
+        self.start_experience(widget)
diff --git a/TP1/experience/Experience.py b/TP1/experience/Experience.py
new file mode 100644
index 0000000..ea34303
--- /dev/null
+++ b/TP1/experience/Experience.py
@@ -0,0 +1,22 @@
+from enum import Enum
+
+from BubbleWidget import BubbleWidget
+from RopeWidget import RopeWidget
+from NormalWidget import NormalWidget
+
+class Experience(Enum):
+    BUBBLE = 1
+    ROPE = 2
+    NORMAL = 3
+
+    def create_widget(self, file_path, exp_setup, number_of_targets):
+        if self.value == Experience.BUBBLE.value:
+            widget = BubbleWidget(file_path, exp_setup, number_of_targets)
+        elif self.value == Experience.ROPE.value:
+            widget = RopeWidget(file_path, exp_setup, number_of_targets)
+        elif self.value == Experience.NORMAL.value:
+            widget = NormalWidget(file_path, exp_setup, number_of_targets)
+        else:
+            print('Aucune expérience selectionnée')
+            widget = None
+        return widget
\ No newline at end of file
diff --git a/TP1/experience/FileDisplayWidget.py b/TP1/experience/FileDisplayWidget.py
new file mode 100644
index 0000000..c71af36
--- /dev/null
+++ b/TP1/experience/FileDisplayWidget.py
@@ -0,0 +1,15 @@
+from PyQt5.QtWidgets import QTextEdit, QWidget, QApplication, QMainWindow
+
+
+class FileDisplayWidget(QWidget):
+    def __init__(self, filename):
+        super().__init__()
+        self.filename = filename
+        self.textEdit = QTextEdit(self)
+        self.textEdit.setReadOnly(True)
+
+        with open(self.filename, 'r') as f:
+            self.textEdit.setPlainText(f.read())
+
+    def resizeEvent(self, event):
+        self.textEdit.setGeometry(0, 0, self.width(), self.height())
diff --git a/TP1/experience/Generate_targets.py b/TP1/experience/Generate_targets.py
new file mode 100644
index 0000000..f0bc38c
--- /dev/null
+++ b/TP1/experience/Generate_targets.py
@@ -0,0 +1,52 @@
+import random
+import csv
+
+SIZE_X_MAX = 1000
+SIZE_Y_MAX = 800
+DIR_NAME = 'generated_exp/'
+SPACING = 5
+all_density = (30, 60, 90)
+all_size = (9, 12, 18)
+max_density = max(all_density)
+max_size = max(all_size)
+
+def generate_targets(num_targets, max_target_size, min_spacing):
+    all_targets = []
+    for _ in range(num_targets):
+        x = random.randint(0, SIZE_X_MAX)
+        y = random.randint(0, SIZE_Y_MAX)
+        target = (x, y, max_target_size)
+        if not all_targets:
+            all_targets.append(target)
+        else:
+            # cf. Theoreme de Pythagore
+            # Prendre la distance avec le cercle et pas le centre
+            min_distance = min([(((x - t[0]) ** 2 + (y - t[1]) ** 2) ** 0.5) - max_target_size/2 for t in all_targets])
+            if min_distance >= min_spacing:
+                all_targets.append(target)
+    return all_targets
+
+def save_to_csv(filename, all_targets, density, change_size):
+    with open(filename, "w", newline='\n') as f:
+        writer = csv.writer(f)
+        for target in all_targets[:density]:
+            as_list = list(target)
+            as_list[2] = change_size
+            writer.writerow(as_list)
+
+
+def create_csv(filename, all_targets, density, change_size):
+    save_to_csv(filename, all_targets, density, change_size)
+
+
+def create_all_files(min_spacing):
+    all_targets = generate_targets(max_density, max_size, min_spacing)
+
+    for density in all_density:
+        for size in all_size:
+            filename = "src_d_" + str(density) + '_s_' + str(size) + '.csv'
+            create_csv(DIR_NAME + filename, all_targets, density, size)
+
+
+if __name__ == '__main__':
+    create_all_files(SPACING)
diff --git a/TP1/experience/MainExp.py b/TP1/experience/MainExp.py
new file mode 100644
index 0000000..e68cc72
--- /dev/null
+++ b/TP1/experience/MainExp.py
@@ -0,0 +1,15 @@
+from PyQt5.QtWidgets import QApplication, QMainWindow
+
+from experience.ExpSetup import ExpSetup
+
+def main():
+    app = QApplication([])
+    window = QMainWindow()
+    exp_widget = ExpSetup(window)
+    window.setCentralWidget(exp_widget)
+    window.show()
+    app.exec_()
+
+
+if __name__ == "__main__":
+    main()
diff --git a/TP1/experience/data/__init__.py b/TP1/experience/data/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/TP1/experience/data/response.csv b/TP1/experience/data/response.csv
new file mode 100644
index 0000000..0d3c21c
--- /dev/null
+++ b/TP1/experience/data/response.csv
@@ -0,0 +1,15 @@
+1, 1, 1, 30, 9, BUBBLE, 6032.421827316284, 0
+1, 1, 2, 30, 9, BUBBLE, 966.8619632720947, 0
+1, 1, 3, 30, 9, BUBBLE, 1031.6030979156494, 0
+1, 1, 4, 30, 9, BUBBLE, 964.9369716644287, 0
+1, 1, 5, 30, 9, BUBBLE, 1550.239086151123, 0
+1, 1, 6, 30, 9, BUBBLE, 683.8860511779785, 0
+1, 1, 7, 30, 9, BUBBLE, 1350.4488468170166, 0
+1, 1, 8, 30, 9, BUBBLE, 1297.9211807250977, 0
+1, 1, 9, 30, 9, BUBBLE, 1032.7260494232178, 0
+1, 1, 10, 30, 9, BUBBLE, 1032.9539775848389, 0
+1, 1, 11, 30, 9, BUBBLE, 896.4080810546875, 0
+1, 1, 12, 30, 9, BUBBLE, 969.0001010894775, 1
+1, 1, 13, 30, 9, BUBBLE, 866.1530017852783, 0
+1, 1, 14, 30, 9, BUBBLE, 614.9580478668213, 0
+1, 1, 15, 30, 9, BUBBLE, 815.1013851165771, 0
diff --git a/TP1/experience/generated_exp/src_d_30_s_12.csv b/TP1/experience/generated_exp/src_d_30_s_12.csv
new file mode 100644
index 0000000..32d9f17
--- /dev/null
+++ b/TP1/experience/generated_exp/src_d_30_s_12.csv
@@ -0,0 +1,30 @@
+666,638,12
+1,172,12
+864,57,12
+8,125,12
+162,369,12
+796,19,12
+677,424,12
+312,9,12
+558,732,12
+674,128,12
+973,467,12
+592,150,12
+245,148,12
+425,561,12
+687,794,12
+14,652,12
+607,52,12
+295,440,12
+571,375,12
+769,588,12
+412,625,12
+857,611,12
+191,673,12
+648,702,12
+445,344,12
+218,338,12
+951,523,12
+542,229,12
+851,671,12
+518,383,12
diff --git a/TP1/experience/generated_exp/src_d_30_s_18.csv b/TP1/experience/generated_exp/src_d_30_s_18.csv
new file mode 100644
index 0000000..3d90b12
--- /dev/null
+++ b/TP1/experience/generated_exp/src_d_30_s_18.csv
@@ -0,0 +1,30 @@
+666,638,18
+1,172,18
+864,57,18
+8,125,18
+162,369,18
+796,19,18
+677,424,18
+312,9,18
+558,732,18
+674,128,18
+973,467,18
+592,150,18
+245,148,18
+425,561,18
+687,794,18
+14,652,18
+607,52,18
+295,440,18
+571,375,18
+769,588,18
+412,625,18
+857,611,18
+191,673,18
+648,702,18
+445,344,18
+218,338,18
+951,523,18
+542,229,18
+851,671,18
+518,383,18
diff --git a/TP1/experience/generated_exp/src_d_30_s_9.csv b/TP1/experience/generated_exp/src_d_30_s_9.csv
new file mode 100644
index 0000000..7b530a4
--- /dev/null
+++ b/TP1/experience/generated_exp/src_d_30_s_9.csv
@@ -0,0 +1,30 @@
+666,638,9
+1,172,9
+864,57,9
+8,125,9
+162,369,9
+796,19,9
+677,424,9
+312,9,9
+558,732,9
+674,128,9
+973,467,9
+592,150,9
+245,148,9
+425,561,9
+687,794,9
+14,652,9
+607,52,9
+295,440,9
+571,375,9
+769,588,9
+412,625,9
+857,611,9
+191,673,9
+648,702,9
+445,344,9
+218,338,9
+951,523,9
+542,229,9
+851,671,9
+518,383,9
diff --git a/TP1/experience/generated_exp/src_d_60_s_12.csv b/TP1/experience/generated_exp/src_d_60_s_12.csv
new file mode 100644
index 0000000..2e1da25
--- /dev/null
+++ b/TP1/experience/generated_exp/src_d_60_s_12.csv
@@ -0,0 +1,60 @@
+666,638,12
+1,172,12
+864,57,12
+8,125,12
+162,369,12
+796,19,12
+677,424,12
+312,9,12
+558,732,12
+674,128,12
+973,467,12
+592,150,12
+245,148,12
+425,561,12
+687,794,12
+14,652,12
+607,52,12
+295,440,12
+571,375,12
+769,588,12
+412,625,12
+857,611,12
+191,673,12
+648,702,12
+445,344,12
+218,338,12
+951,523,12
+542,229,12
+851,671,12
+518,383,12
+670,3,12
+304,665,12
+562,112,12
+198,128,12
+363,337,12
+583,344,12
+168,558,12
+715,629,12
+697,660,12
+435,149,12
+239,82,12
+46,69,12
+380,685,12
+964,5,12
+620,136,12
+351,471,12
+528,536,12
+501,75,12
+910,317,12
+223,724,12
+563,641,12
+791,244,12
+987,77,12
+907,244,12
+22,538,12
+782,353,12
+235,793,12
+751,447,12
+515,258,12
+418,538,12
diff --git a/TP1/experience/generated_exp/src_d_60_s_18.csv b/TP1/experience/generated_exp/src_d_60_s_18.csv
new file mode 100644
index 0000000..fc9e4bf
--- /dev/null
+++ b/TP1/experience/generated_exp/src_d_60_s_18.csv
@@ -0,0 +1,60 @@
+666,638,18
+1,172,18
+864,57,18
+8,125,18
+162,369,18
+796,19,18
+677,424,18
+312,9,18
+558,732,18
+674,128,18
+973,467,18
+592,150,18
+245,148,18
+425,561,18
+687,794,18
+14,652,18
+607,52,18
+295,440,18
+571,375,18
+769,588,18
+412,625,18
+857,611,18
+191,673,18
+648,702,18
+445,344,18
+218,338,18
+951,523,18
+542,229,18
+851,671,18
+518,383,18
+670,3,18
+304,665,18
+562,112,18
+198,128,18
+363,337,18
+583,344,18
+168,558,18
+715,629,18
+697,660,18
+435,149,18
+239,82,18
+46,69,18
+380,685,18
+964,5,18
+620,136,18
+351,471,18
+528,536,18
+501,75,18
+910,317,18
+223,724,18
+563,641,18
+791,244,18
+987,77,18
+907,244,18
+22,538,18
+782,353,18
+235,793,18
+751,447,18
+515,258,18
+418,538,18
diff --git a/TP1/experience/generated_exp/src_d_60_s_9.csv b/TP1/experience/generated_exp/src_d_60_s_9.csv
new file mode 100644
index 0000000..1052f3e
--- /dev/null
+++ b/TP1/experience/generated_exp/src_d_60_s_9.csv
@@ -0,0 +1,60 @@
+666,638,9
+1,172,9
+864,57,9
+8,125,9
+162,369,9
+796,19,9
+677,424,9
+312,9,9
+558,732,9
+674,128,9
+973,467,9
+592,150,9
+245,148,9
+425,561,9
+687,794,9
+14,652,9
+607,52,9
+295,440,9
+571,375,9
+769,588,9
+412,625,9
+857,611,9
+191,673,9
+648,702,9
+445,344,9
+218,338,9
+951,523,9
+542,229,9
+851,671,9
+518,383,9
+670,3,9
+304,665,9
+562,112,9
+198,128,9
+363,337,9
+583,344,9
+168,558,9
+715,629,9
+697,660,9
+435,149,9
+239,82,9
+46,69,9
+380,685,9
+964,5,9
+620,136,9
+351,471,9
+528,536,9
+501,75,9
+910,317,9
+223,724,9
+563,641,9
+791,244,9
+987,77,9
+907,244,9
+22,538,9
+782,353,9
+235,793,9
+751,447,9
+515,258,9
+418,538,9
diff --git a/TP1/experience/generated_exp/src_d_90_s_12.csv b/TP1/experience/generated_exp/src_d_90_s_12.csv
new file mode 100644
index 0000000..4633449
--- /dev/null
+++ b/TP1/experience/generated_exp/src_d_90_s_12.csv
@@ -0,0 +1,88 @@
+666,638,12
+1,172,12
+864,57,12
+8,125,12
+162,369,12
+796,19,12
+677,424,12
+312,9,12
+558,732,12
+674,128,12
+973,467,12
+592,150,12
+245,148,12
+425,561,12
+687,794,12
+14,652,12
+607,52,12
+295,440,12
+571,375,12
+769,588,12
+412,625,12
+857,611,12
+191,673,12
+648,702,12
+445,344,12
+218,338,12
+951,523,12
+542,229,12
+851,671,12
+518,383,12
+670,3,12
+304,665,12
+562,112,12
+198,128,12
+363,337,12
+583,344,12
+168,558,12
+715,629,12
+697,660,12
+435,149,12
+239,82,12
+46,69,12
+380,685,12
+964,5,12
+620,136,12
+351,471,12
+528,536,12
+501,75,12
+910,317,12
+223,724,12
+563,641,12
+791,244,12
+987,77,12
+907,244,12
+22,538,12
+782,353,12
+235,793,12
+751,447,12
+515,258,12
+418,538,12
+643,468,12
+471,327,12
+789,481,12
+48,420,12
+364,625,12
+296,629,12
+201,320,12
+159,3,12
+414,168,12
+873,230,12
+481,633,12
+357,702,12
+815,292,12
+393,674,12
+411,435,12
+646,90,12
+439,101,12
+691,187,12
+101,627,12
+411,597,12
+671,381,12
+977,516,12
+302,562,12
+383,285,12
+109,253,12
+37,337,12
+826,741,12
+583,91,12
diff --git a/TP1/experience/generated_exp/src_d_90_s_18.csv b/TP1/experience/generated_exp/src_d_90_s_18.csv
new file mode 100644
index 0000000..81c233b
--- /dev/null
+++ b/TP1/experience/generated_exp/src_d_90_s_18.csv
@@ -0,0 +1,88 @@
+666,638,18
+1,172,18
+864,57,18
+8,125,18
+162,369,18
+796,19,18
+677,424,18
+312,9,18
+558,732,18
+674,128,18
+973,467,18
+592,150,18
+245,148,18
+425,561,18
+687,794,18
+14,652,18
+607,52,18
+295,440,18
+571,375,18
+769,588,18
+412,625,18
+857,611,18
+191,673,18
+648,702,18
+445,344,18
+218,338,18
+951,523,18
+542,229,18
+851,671,18
+518,383,18
+670,3,18
+304,665,18
+562,112,18
+198,128,18
+363,337,18
+583,344,18
+168,558,18
+715,629,18
+697,660,18
+435,149,18
+239,82,18
+46,69,18
+380,685,18
+964,5,18
+620,136,18
+351,471,18
+528,536,18
+501,75,18
+910,317,18
+223,724,18
+563,641,18
+791,244,18
+987,77,18
+907,244,18
+22,538,18
+782,353,18
+235,793,18
+751,447,18
+515,258,18
+418,538,18
+643,468,18
+471,327,18
+789,481,18
+48,420,18
+364,625,18
+296,629,18
+201,320,18
+159,3,18
+414,168,18
+873,230,18
+481,633,18
+357,702,18
+815,292,18
+393,674,18
+411,435,18
+646,90,18
+439,101,18
+691,187,18
+101,627,18
+411,597,18
+671,381,18
+977,516,18
+302,562,18
+383,285,18
+109,253,18
+37,337,18
+826,741,18
+583,91,18
diff --git a/TP1/experience/generated_exp/src_d_90_s_9.csv b/TP1/experience/generated_exp/src_d_90_s_9.csv
new file mode 100644
index 0000000..76a475e
--- /dev/null
+++ b/TP1/experience/generated_exp/src_d_90_s_9.csv
@@ -0,0 +1,88 @@
+666,638,9
+1,172,9
+864,57,9
+8,125,9
+162,369,9
+796,19,9
+677,424,9
+312,9,9
+558,732,9
+674,128,9
+973,467,9
+592,150,9
+245,148,9
+425,561,9
+687,794,9
+14,652,9
+607,52,9
+295,440,9
+571,375,9
+769,588,9
+412,625,9
+857,611,9
+191,673,9
+648,702,9
+445,344,9
+218,338,9
+951,523,9
+542,229,9
+851,671,9
+518,383,9
+670,3,9
+304,665,9
+562,112,9
+198,128,9
+363,337,9
+583,344,9
+168,558,9
+715,629,9
+697,660,9
+435,149,9
+239,82,9
+46,69,9
+380,685,9
+964,5,9
+620,136,9
+351,471,9
+528,536,9
+501,75,9
+910,317,9
+223,724,9
+563,641,9
+791,244,9
+987,77,9
+907,244,9
+22,538,9
+782,353,9
+235,793,9
+751,447,9
+515,258,9
+418,538,9
+643,468,9
+471,327,9
+789,481,9
+48,420,9
+364,625,9
+296,629,9
+201,320,9
+159,3,9
+414,168,9
+873,230,9
+481,633,9
+357,702,9
+815,292,9
+393,674,9
+411,435,9
+646,90,9
+439,101,9
+691,187,9
+101,627,9
+411,597,9
+671,381,9
+977,516,9
+302,562,9
+383,285,9
+109,253,9
+37,337,9
+826,741,9
+583,91,9
-- 
GitLab