diff --git a/cmd/simu/main.go b/cmd/simu/main.go
index 9127258c9d064186e80c3cd37ba03c22ea0cc76b..a4c765ec763cea6fa19babf9d257506f54cc92ca 100644
--- a/cmd/simu/main.go
+++ b/cmd/simu/main.go
@@ -10,7 +10,7 @@ import (
 )
 
 func main() {
-	s := simulation.NewSimulation(1, -1, 600*time.Second)
+	s := simulation.NewSimulation(6, -1, 600*time.Second)
 	//go simulation.StartAPI(s)
 	go func() {
 		for {
diff --git a/internal/simulation/agent.go b/internal/simulation/agent.go
index db5e60b13c91cba6a52a41a12e545af09f2f4378..a78c1f1d18f3fd2ef72a87c7bad672b7b8004637 100644
--- a/internal/simulation/agent.go
+++ b/internal/simulation/agent.go
@@ -11,10 +11,8 @@ import (
 
 	//"log"
 	"math/rand"
-	"math"
 	alg "metrosim/internal/algorithms"
 	"time"
-	"sort"
 )
 
 type Action int64
@@ -570,88 +568,7 @@ func (ag *Agent) findNearestExit() (alg.Coord){
 	return nearest
 }
 
-func (ag *Agent) findNearestGates(gates []alg.Coord) []Gate {
-	var gateDistances []Gate
-	// Calcul de la distance pour chaque porte
-	for _, gate := range gates {
-		dist := alg.Abs(ag.position[0]-gate[0]) + alg.Abs(ag.position[1]-gate[1])
-		gateDistances = append(gateDistances, Gate{Position: gate, Distance: float64(dist)})
-	}
-
-	// Tri des Coords par distance
-	sort.Slice(gateDistances, func(i, j int) bool {
-		return gateDistances[i].Distance < gateDistances[j].Distance
-	})
-
-	return gateDistances
-}
-
-// Normalise les valeurs d'un ensemble de portes
-func normalizeGates(gates []Gate) ([]Gate, float64, float64) {
-    var minAgents, maxAgents float64 = math.MaxFloat64, 0
-    var minDistance, maxDistance float64 = math.MaxFloat64, 0
-
-    // Trouver les valeurs max et min pour la normalisation
-    for _, gate := range gates {
-        if gate.NbAgents > maxAgents {
-            maxAgents = gate.NbAgents
-        }
-        if gate.NbAgents < minAgents {
-            minAgents = gate.NbAgents
-        }
-        if gate.Distance > maxDistance {
-            maxDistance = gate.Distance
-        }
-        if gate.Distance < minDistance {
-            minDistance = gate.Distance
-        }
-    }
-
-    // Normaliser les valeurs
-	d_agt := (maxAgents - minAgents) 
-	if  d_agt == 0 {
-		d_agt = 1.0
-	}
-	d_dist := (maxDistance - minDistance)
-	if d_dist == 0 {
-		d_dist = 1.0
-	}
-	fmt.Println("[normalizeGates] d_dist : ",d_dist)
-    for i := range gates {
-        gates[i].NbAgents = (gates[i].NbAgents - minAgents) / d_agt
-		//fmt.Println("[normalizeGates] gates[i].Distance : ",gates[i].Distance)
-		//fmt.Println("[normalizeGates] minDistance : ",minDistance)
-		//fmt.Println("[normalizeGates] d_dist : ",d_dist)
-        gates[i].Distance = (gates[i].Distance - minDistance) / d_dist
-	}
-    return gates, float64(maxAgents - minAgents), maxDistance - minDistance
-}
-
-
-
-func (ag *Agent) findBestGate(gates []alg.Coord) alg.Coord {
-	gatesDistances := make([]Gate, len(gates))
-	for i, gate := range gates {
-		dist := alg.Abs(ag.position[0]-gate[0]) + alg.Abs(ag.position[1]-gate[1])
-		nbAgents := float64(ag.env.getNbAgentsAround(gate))
-		gatesDistances[i] = Gate{Position: gate, Distance: float64(dist), NbAgents: nbAgents}
-	}
-	fmt.Println("[findBestGate] gates non normalisé : ",gatesDistances)
-	normalizedGates, _, _ := normalizeGates(gatesDistances)
-	fmt.Println("[findBestGate] gates normalisé : ",normalizedGates)
-	var bestGate Gate
-	lowestScore := 2.0 // Puisque la somme des scores normalisés ne peut pas dépasser 2
-
-	for _, gate := range normalizedGates {
-		score := float64(gate.NbAgents) + gate.Distance
-		if score < lowestScore {
-			lowestScore = score
-			bestGate = gate
-		}
-	}
 
-	return bestGate.Position
-}
 
 
 func findMetro(env *Environment, gateToFind *alg.Coord) *Metro {
diff --git a/internal/simulation/controleur.go b/internal/simulation/controleur.go
index 4fdb61e6b72e2717e1c72d53e0f7f2e2a36ad6e0..0085ac0ff9a20275cb112db8be453b9a65c49dad 100644
--- a/internal/simulation/controleur.go
+++ b/internal/simulation/controleur.go
@@ -1,6 +1,10 @@
 package simulation
 
-//ajouter liste des agents déjà controllés
+/*
+	Le controleur se déplace aléatoirement dans la station pendant un certain temps
+	et controle les agents qui se trouvent devant lui si ils ne sont pas déjà controllés par un autre controleur,
+	si l'agent est un fraudeur alors il est expulsé, sinon il est arreté pendant un certain temps
+*/
 
 import (
 	"fmt"
@@ -10,13 +14,6 @@ import (
 	alg "metrosim/internal/algorithms"
 )
 
-/*
-	Je suppose que l'id du controleur est de format "Cont + un chiffre"
-	Exemple : "Cont1"
-	et l'id du l'agent est de format "Agent + un chiffre"
-	Exemple : "Agent1"
-*/
-
 type Controleur struct {
 	req *Request // requete reçue par le controleur
 	faceCase string // chaine de caractère qui contient l'id de l'agent qui se trouve devant le controleur, exemple : "Agent1", "Fraudeur1", "X" ,etc.
@@ -24,14 +21,12 @@ type Controleur struct {
 	isExpired bool // true si le controleur est expiré, false sinon
 }
 
-
-
 func (c *Controleur) Percept(ag *Agent) {
 	//initialiser le faceCase en fonction de la direction de l'agent
 	c.faceCase = ag.getFaceCase()
 	switch {
 		// comportement par défaut (comportement agent Lambda)
-		case ag.request != nil: //verifier si l'agent est communiqué par un autre agent (A VOIR SI IL EXISTE DEJA UN AGENT QUI COMMUNIQUE AVEC LE CONTROLEUR)
+		case ag.request != nil: //verifier si l'agent est communiqué par un autre agent
 			//print("Requete recue par l'agent lambda : ", ag.request.decision, "\n")
 			c.req = ag.request
 		default:
@@ -46,29 +41,29 @@ func (c *Controleur) Percept(ag *Agent) {
 func (c *Controleur) Deliberate(ag *Agent) {
 	// Verifier si la case devant lui contient un agent ou un fraudeur
 	// Créer l'expression régulière
-	regexAgent := `^Agent\d+$` // \d+ correspond à un ou plusieurs chiffres
+	//regexAgent := `^Agent\d+$` // \d+ correspond à un ou plusieurs chiffres
 	regexFraudeur := `^Fraudeur\d+$`
 
+	existAgt := existAgent(c.faceCase) // true si l'agent existe dans la case en face , false sinon 
 	// Vérifier si la valeur de faceCase ne correspond pas au motif
-	matchedAgt, err1 := regexp.MatchString(regexAgent, c.faceCase)
-	matchedFraud, err2 := regexp.MatchString(regexFraudeur, c.faceCase)
+	//matchedAgt, err1 := regexp.MatchString(regexAgent, c.faceCase)
+	matchedFraud, err := regexp.MatchString(regexFraudeur, c.faceCase)
 	//fmt.Println("faceCase : ", c.faceCase)
 	//fmt.Println("matchedAgt : ", matchedAgt)
 
-	if err1 != nil || err2 != nil {
-		fmt.Println("Erreur lors de l'analyse de la regex :", err1, err2)
+	if err!= nil {
+		fmt.Println("Erreur lors de l'analyse de la regex :",err)
 		return
 	} else {
-		if matchedAgt && ag.env.controlledAgents[AgentID(c.faceCase)] == false { // si l'agent devant le controleur est un agent et qu'il n'a pas encore été controlé
-			//fmt.Println("L'agent ", c.face, " a été détecté par le controleur")
-			ag.decision = Stop // arreter l'agent devant lui
-		} else if matchedFraud && !ag.env.controlledAgents[AgentID(c.faceCase)] {
+		if matchedFraud && !ag.env.controlledAgents[AgentID(c.faceCase)] {
 			ag.decision = Expel // virer l'agent devant lui
-			//sinon comportement par défaut (comportement de l'usager lambda)
-			}else if ag.position == ag.destination && (ag.isOn[ag.position] == "W" || ag.isOn[ag.position] == "S") { // si l'agent est arrivé à sa destination et qu'il est sur une sortie
+		}else if existAgt && !ag.env.controlledAgents[AgentID(c.faceCase)] { // si l'agent devant le controleur est un agent et qu'il n'a pas encore été controlé
+			//fmt.Println("L'agent ", c.face, " a été détecté par le controleur")
+			ag.decision = Stop // arreter l'agent 
+		}else if ag.position == ag.destination && (ag.isOn[ag.position] == "W" || ag.isOn[ag.position] == "S") { // si le controleur est arrivé à sa destination et qu'il est sur une sortie
 				//fmt.Println(ag.id, "disappear")
 				ag.decision = Disappear
-				} else if ag.stuck{ // si l'agent est bloqué
+				} else if ag.stuck{ // si le controleur est bloqué
 					ag.decision = Wait
 					}else {
 					ag.decision = Move
@@ -97,7 +92,7 @@ func (c *Controleur) Act(ag *Agent) {
 	case Disappear:
 		RemoveAgent(&ag.env.station, ag)
 
-	default : //Expel ou Wait
+	case Expel, Stop : //Expel ou Stop
 		agt_face_id := AgentID(c.faceCase) //id de l'agent qui se trouve devant le controleur
 		//fmt.Print("L'agent ", agt_face_id, " a été expulsé\n")
 		ag.env.agentsChan[agt_face_id] <- *NewRequest(ag.env.agentsChan[ag.id], ag.decision) // envoie la decision du controleur à l'agent qui se trouve devant lui
@@ -106,11 +101,11 @@ func (c *Controleur) Act(ag *Agent) {
 
 func (c *Controleur) randomDestination(ag *Agent) alg.Coord {
 	rand.Seed(time.Now().UnixNano()) // le générateur de nombres aléatoires
-	randomRow := rand.Intn(20) // Génère un entier aléatoire entre 0 et 19
-	randomCol := rand.Intn(20) // Génère un entier aléatoire entre 0 et 19
+	randomRow := rand.Intn(len(ag.env.station[0])) // Génère un entier aléatoire entre 0 et 19
+	randomCol := rand.Intn(len(ag.env.station[1])) // Génère un entier aléatoire entre 0 et 19
 	for ag.env.station[randomRow][randomCol] != "_" {
-		randomRow = rand.Intn(20) // Génère un entier aléatoire entre 0 et 19
-		randomCol = rand.Intn(20) // Génère un entier aléatoire entre 0 et 19
+		randomRow = rand.Intn(len(ag.env.station[0])) // Génère un entier aléatoire entre 0 et 19
+		randomCol = rand.Intn(len(ag.env.station[1])) // Génère un entier aléatoire entre 0 et 19
 	}
 	return alg.Coord{randomRow, randomCol}
 }
diff --git a/internal/simulation/metro.go b/internal/simulation/metro.go
index 3b30ac3daf0ec6a5aa8c253ef1e085981ee3264c..4130bffd523adc9c61e99cd698cf301b7973ca27 100644
--- a/internal/simulation/metro.go
+++ b/internal/simulation/metro.go
@@ -47,7 +47,7 @@ func (metro *Metro) Start() {
 			metro.printMetro()
 		}
 		if refTime.Add(metro.frequency).Before(time.Now()) {
-			metro.dropUsers()
+			//metro.dropUsers()
 			metro.way.openGates()
 			metro.pickUpUsers()
 			metro.way.closeGates()
diff --git a/internal/simulation/mobiliteReduite.go b/internal/simulation/mobiliteReduite.go
index 75a90231ffbd706971429dfe2972b78b4139b33e..0da37a4f1499aac008e5b2d31e5ac6976d7ef112 100644
--- a/internal/simulation/mobiliteReduite.go
+++ b/internal/simulation/mobiliteReduite.go
@@ -1,4 +1,7 @@
 package simulation
+/*
+	L'agent à Mobilité Reduite cherche la porte du metro la plus proche de lui
+*/
 
 import (
 	"fmt"
@@ -6,6 +9,7 @@ import (
 	"math/rand"
 	"time"
 	alg "metrosim/internal/algorithms"
+	"sort"
 )
 
 
@@ -16,7 +20,7 @@ type MobiliteReduite struct {
 
 
 func (mr *MobiliteReduite) Percept(ag *Agent) {
-	mr.once.Do(func(){mr.setUpDestination(ag)}) // la fonction setUp est executé à la premiere appel de la fonction Percept()
+	mr.once.Do(func(){mr.setUpDestination(ag)}) // la fonction setUp est executé à la premiere appel à la fonction Percept()
 	switch {
 	case ag.request != nil: //verifier si l'agent est communiqué par un autre agent, par exemple un controleur lui a demandé de s'arreter
 		fmt.Printf("Requete recue par l'agent mR : %d \n", ag.request.decision)
@@ -101,7 +105,24 @@ func (mr *MobiliteReduite) Act(ag *Agent) {
 */
 func (mr *MobiliteReduite)setUpDestination(ag *Agent){
 	choix_voie := rand.Intn(2) // choix de la voie de métro aléatoire
-	dest_porte := (ag.findNearestGates(ag.env.metros[choix_voie].way.gates))
+	dest_porte := (mr.findNearestGates(ag, ag.env.metros[choix_voie].way.gates))
 	//fmt.Println("[MobiliteReduite, setUpDestination] dest_porte = ",dest_porte)
 	ag.destination = dest_porte[0].Position
 }
+
+
+func (mr *MobiliteReduite) findNearestGates(ag *Agent, gates []alg.Coord) []Gate {
+	var gateDistances []Gate
+	// Calcul de la distance pour chaque porte
+	for _, gate := range gates {
+		dist := alg.Abs(ag.position[0]-gate[0]) + alg.Abs(ag.position[1]-gate[1])
+		gateDistances = append(gateDistances, Gate{Position: gate, Distance: float64(dist)})
+	}
+
+	// Tri des Coords par distance
+	sort.Slice(gateDistances, func(i, j int) bool {
+		return gateDistances[i].Distance < gateDistances[j].Distance
+	})
+
+	return gateDistances
+}
\ No newline at end of file
diff --git a/internal/simulation/simu.go b/internal/simulation/simu.go
index 2bf9704e7c86c409fa5089b4a80acc1053ed2103..1855a48c7fc970db0d4f1b44bd7e80657ad3e849 100644
--- a/internal/simulation/simu.go
+++ b/internal/simulation/simu.go
@@ -140,17 +140,25 @@ func NewSimulation(agentCount int, maxStep int, maxDuration time.Duration) (simu
 		// création de l'agent
 
 		syncChan := make(chan int)
+		ag := &Agent{}
 		//ag := NewAgent(id, &simu.env, syncChan, time.Duration(time.Second), 0, true, Coord{0, 8 + i%2}, Coord{0, 8 + i%2}, &UsagerLambda{}, Coord{0, 8 + i%2}, Coord{12 - 4*(i%2), 18 - 15*(i%2)})
 		//ag := NewAgent(id, &simu.env, syncChan, 1000, 0, true, &UsagerLambda{},  Coord{18, 4}, Coord{0, 8}, 2, 1)
 		//ag := &Agent{}
-		
+		/*
 		id := fmt.Sprintf("Agent%d", i)
 		ag := NewAgent(id, &simu.env, syncChan, 400, 0, true, &UsagerLambda{}, alg.Coord{0, 28}, alg.Coord{8, 5}, 1, 1)
+		*/
+
+		id := fmt.Sprintf("Cont%d", i)
+		//NewAgent(id string, env *Environment, syncChan chan int, vitesse time.Duration, force int, politesse bool, behavior Behavior, departure, destination Coord, width, height int)
+		ag = NewAgent(id, &simu.env, syncChan, 200, 0, true, &Controleur{}, alg.Coord{0, 28}, alg.Coord{0, 9}, 1, 1)
+
 		/*
+		
 		if i%2 == 0 { //Type Agent
-			id := fmt.Sprintf("MR%d", i)
+			id := fmt.Sprintf("Cont%d", i)
 			//NewAgent(id string, env *Environment, syncChan chan int, vitesse time.Duration, force int, politesse bool, behavior Behavior, departure, destination Coord, width, height int)
-			ag = NewAgent(id, &simu.env, syncChan, 200, 0, true, &UsagerLambda{}, alg.Coord{49, 32}, alg.Coord{0, 9}, 2, 1)
+			ag = NewAgent(id, &simu.env, syncChan, 200, 0, true, &Controleur{}, alg.Coord{0, 28}, alg.Coord{0, 9}, 2, 1)
 		} else { // Type Controleur
 			//id := fmt.Sprintf("Controleur%d", i)
 			id := fmt.Sprintf("Agent%d", i)
@@ -256,11 +264,13 @@ func (simu *Simulation) Print() {
 		for i := 0; i < 20; i++ {
 			for j := 0; j < 50; j++ {
 				element := simu.env.station[i][j]
+				
 				if len(element) > 1 {
-					fmt.Print(element[len(element)-1:] + " ") // Afficher le premier caractère si la longueur est supérieure à 1
-				} else {
-					fmt.Print(element + " ")
-				}
+					//fmt.Print(element[len(element)-1:] + " ") // Afficher le premier caractère si la longueur est supérieure à 1
+					fmt.Print(element[0:1] + " ")
+					} else {
+						fmt.Print(element + " ")
+					}
 			}
 			fmt.Println()
 		}
diff --git a/internal/simulation/usagerLambda.go b/internal/simulation/usagerLambda.go
index dccadee1b27f2a3fad625f9ea94779ca9e64f181..cea92ebdb940cbb9df94e267a1a4fe6a938fc8d0 100644
--- a/internal/simulation/usagerLambda.go
+++ b/internal/simulation/usagerLambda.go
@@ -15,7 +15,7 @@ type UsagerLambda struct {
 }
 
 func (ul *UsagerLambda) Percept(ag *Agent) {
-	ul.once.Do(func(){ul.setUpDestination(ag)}) // la fonction setUp est executé à la premiere appel de la fonction Percept()
+	//ul.once.Do(func(){ul.setUpDestination(ag)}) // la fonction setUp est executé à la premiere appel de la fonction Percept()
 	switch {
 	case ag.request != nil: //verifier si l'agent est communiqué par un autre agent, par exemple un controleur lui a demandé de s'arreter
 		//print("Requete recue par l'agent lambda : ", ag.request.decision, "\n")
@@ -84,9 +84,3 @@ func (ul *UsagerLambda) Act(ag *Agent) {
 	}
 }
 
-
-func (ul *UsagerLambda)setUpDestination(ag *Agent){
-	choix_voie := rand.Intn(2) // choix de la voie de métro aléatoire
-	dest_porte := (ag.findBestGate(ag.env.metros[choix_voie].way.gates))
-	ag.destination = dest_porte
-}
\ No newline at end of file
diff --git a/internal/simulation/usagerNormal.go b/internal/simulation/usagerNormal.go
new file mode 100644
index 0000000000000000000000000000000000000000..0458e54240129df7a7b9de12cd8cccd3e3e96efa
--- /dev/null
+++ b/internal/simulation/usagerNormal.go
@@ -0,0 +1,165 @@
+package simulation
+
+
+/*
+  Agent qui se dirige vers la porte la plus proche sans trop de monde (bon rapport monde/proximité )
+*/
+
+import (
+	"fmt"
+
+	"math/rand"
+	alg "metrosim/internal/algorithms"
+	"time"
+	"sync"
+	"math"
+)
+
+type UsagerNormal struct {
+	req *Request // requete recue par l'agent lambda
+	once sync.Once
+}
+
+func (ul *UsagerNormal) Percept(ag *Agent) {
+	ul.once.Do(func(){ul.setUpDestination(ag)}) // la fonction setUp est executé à la premiere appel de la fonction Percept()
+	switch {
+	case ag.request != nil: //verifier si l'agent est communiqué par un autre agent, par exemple un controleur lui a demandé de s'arreter
+		//print("Requete recue par l'agent lambda : ", ag.request.decision, "\n")
+		ul.req = ag.request
+	default:
+		ag.stuck = ag.isStuck()
+		if ag.stuck {
+			return
+
+		}
+	}
+}
+
+func (ul *UsagerNormal) Deliberate(ag *Agent) {
+	//fmt.Println("[AgentLambda Deliberate] decision :", ul.req.decision)
+	if (ul.req != nil ) {
+		if ul.req.decision == Stop{
+			ag.decision = Wait
+			ul.req = nil //demande traitée
+			return
+		} else if ul.req.decision == Expel { // cette condition est inutile car l'usager lambda ne peut pas etre expulsé , elle est nécessaire pour les agents fraudeurs
+				//fmt.Println("[AgentLambda, Deliberate] Expel")
+				ag.decision = Expel
+				ul.req = nil //demande traitée
+				return
+		}else if ul.req.decision == Disappear {
+			ag.decision = Disappear
+			return
+		}else if ul.req.decision == Wait {
+			ag.decision = Wait
+		}else if ul.req.decision == EnterMetro {
+			ag.decision = EnterMetro
+			}
+	}else if (ag.position != ag.departure && ag.position == ag.destination) && (ag.isOn[ag.position] == "W" || ag.isOn[ag.position] == "S") { // si l'agent est arrivé à sa destination et qu'il est sur une sortie
+			//fmt.Println(ag.id, "disappear")
+			ag.decision = Disappear
+		} else if ag.stuck{ // si l'agent est bloqué
+			ag.decision = Wait
+				}else {
+				ag.decision = Move
+				}
+}
+
+func (ul *UsagerNormal) Act(ag *Agent) {
+	//fmt.Println("[AgentLambda Act] decision :",ag.decision)
+	if ag.decision == Move {
+		ag.MoveAgent()
+	} else if ag.decision == Wait {
+		n := rand.Intn(2) // temps d'attente aléatoire
+		time.Sleep(time.Duration(n) * time.Second)
+	} else if ag.decision == Disappear {
+		RemoveAgent(&ag.env.station, ag)
+	} else if ag.decision == EnterMetro {
+		fmt.Println("[UsagerNormal, Act] EnterMetro")
+		RemoveAgent(&ag.env.station, ag)
+		ul.req.demandeur <- *NewRequest(ag.env.agentsChan[ag.id], ACK)
+	} else if ag.decision == Expel {
+		//fmt.Println("[AgentLambda, Act] Expel")
+		ag.destination = ag.findNearestExit()
+		//fmt.Println("[AgentLambda, Act] destination = ",ag.destination)
+		ag.env.controlledAgents[ag.id] = true
+		ag.path = make([]alg.Node, 0)
+		ag.MoveAgent()
+	} else {
+		// nothing to do
+	}
+}
+
+
+func (ul *UsagerNormal)setUpDestination(ag *Agent){
+	choix_voie := rand.Intn(2) // choix de la voie de métro aléatoire
+	dest_porte := (ul.findBestGate(ag, ag.env.metros[choix_voie].way.gates))
+	ag.destination = dest_porte
+}
+
+
+
+func (ul *UsagerNormal) findBestGate(ag *Agent, gates []alg.Coord) alg.Coord {
+	gatesDistances := make([]Gate, len(gates))
+	for i, gate := range gates {
+		dist := alg.Abs(ag.position[0]-gate[0]) + alg.Abs(ag.position[1]-gate[1])
+		nbAgents := float64(ag.env.getNbAgentsAround(gate))
+		gatesDistances[i] = Gate{Position: gate, Distance: float64(dist), NbAgents: nbAgents}
+	}
+	fmt.Println("[findBestGate] gates non normalisé : ",gatesDistances)
+	normalizedGates, _, _ := normalizeGates(gatesDistances)
+	fmt.Println("[findBestGate] gates normalisé : ",normalizedGates)
+	var bestGate Gate
+	lowestScore := 2.0 // Puisque la somme des scores normalisés ne peut pas dépasser 2
+
+	for _, gate := range normalizedGates {
+		score := float64(gate.NbAgents) + gate.Distance
+		if score < lowestScore {
+			lowestScore = score
+			bestGate = gate
+		}
+	}
+	return bestGate.Position
+}
+
+
+// Normalise les valeurs d'un ensemble de portes
+func normalizeGates(gates []Gate) ([]Gate, float64, float64) {
+    var minAgents, maxAgents float64 = math.MaxFloat64, 0
+    var minDistance, maxDistance float64 = math.MaxFloat64, 0
+
+    // Trouver les valeurs max et min pour la normalisation
+    for _, gate := range gates {
+        if gate.NbAgents > maxAgents {
+            maxAgents = gate.NbAgents
+        }
+        if gate.NbAgents < minAgents {
+            minAgents = gate.NbAgents
+        }
+        if gate.Distance > maxDistance {
+            maxDistance = gate.Distance
+        }
+        if gate.Distance < minDistance {
+            minDistance = gate.Distance
+        }
+    }
+
+    // Normaliser les valeurs
+	d_agt := (maxAgents - minAgents) 
+	if  d_agt == 0 {
+		d_agt = 1.0
+	}
+	d_dist := (maxDistance - minDistance)
+	if d_dist == 0 {
+		d_dist = 1.0
+	}
+	fmt.Println("[normalizeGates] d_dist : ",d_dist)
+    for i := range gates {
+        gates[i].NbAgents = (gates[i].NbAgents - minAgents) / d_agt
+		//fmt.Println("[normalizeGates] gates[i].Distance : ",gates[i].Distance)
+		//fmt.Println("[normalizeGates] minDistance : ",minDistance)
+		//fmt.Println("[normalizeGates] d_dist : ",d_dist)
+        gates[i].Distance = (gates[i].Distance - minDistance) / d_dist
+	}
+    return gates, float64(maxAgents - minAgents), maxDistance - minDistance
+}