diff --git a/cmd/simu/main.go b/cmd/simu/main.go index c8ccb5a2534b19973e7cd4ee5d10e94ff0e700f4..f963e03be40af2a537924923ad7f76bad953b94a 100644 --- a/cmd/simu/main.go +++ b/cmd/simu/main.go @@ -6,8 +6,7 @@ import ( ) func main() { - s := simulation.NewSimulation(3, -1, 600*time.Second) - //go simulation.StartAPI(s) + s := simulation.NewSimulation(10, -1, 600*time.Second) //go simulation.StartAPI(s) s.Run() } diff --git a/go.mod b/go.mod index e05f097a3e2aa9273f01fe45320f4dd910b237cd..b98b1cd48f76bc17ca17b46f8e4776b9be866d54 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module metrosim -go 1.23 +go 1.21.1 diff --git a/internal/algorithms/astar.go b/internal/algorithms/astar.go index d1fc5062c3e54db8733201f9de67c1036b26b6e1..1b706ea39da6cbe1e0856ecde45cba215405521a 100644 --- a/internal/algorithms/astar.go +++ b/internal/algorithms/astar.go @@ -2,7 +2,9 @@ package algorithms import ( "container/heap" + "context" "math/rand" + "time" ) /* @@ -62,7 +64,11 @@ func (pq *PriorityQueue) Pop() interface{} { type ZoneID int type Coord [2]int -func FindPath(matrix [20][20]string, start, end Node, forbidenCell Node, orientation bool) []Node { +func FindPath(matrix [20][20]string, start, end Node, forbidenCell Node, orientation bool, timeout time.Duration) []Node { + // Création d'un context avec timeout, pour limiter le calcul + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + pq := make(PriorityQueue, 0) heap.Init(&pq) @@ -76,6 +82,13 @@ func FindPath(matrix [20][20]string, start, end Node, forbidenCell Node, orienta foundPath := false for pq.Len() > 0 { + select { + case <-ctx.Done(): + // Timeout reached, return an error or handle accordingly + return nil + default: + // Continue with the algorithm + } current := heap.Pop(&pq).(*Node) // Mise à jour du point le plus proche si le point actuel est plus proche @@ -120,10 +133,9 @@ func FindPath(matrix [20][20]string, start, end Node, forbidenCell Node, orienta } func getNeighbors(matrix [20][20]string, current, end Node, forbiddenCell Node, orientation bool) []*Node { - //fmt.Println("okk") neighbors := make([]*Node, 0) - // Possible moves: up, down, left, right + // Déplacements possibles: up, down, left, right possibleMoves := [][]int{{-1, 0}, {1, 0}, {0, -1}, {0, 1}} for _, move := range possibleMoves { @@ -131,8 +143,7 @@ func getNeighbors(matrix [20][20]string, current, end Node, forbiddenCell Node, if orientation { for or := 0; or < 4; or++ { current.orientation = or - //fmt.Println(orientation) - //Check if the new position is valid, considering agent dimensions and rotation + //Vérifie que le déplacement soit valide if isValidMove(matrix, current, forbiddenCell, newRow, newCol, orientation) { neighbors = append(neighbors, &Node{ row: newRow, @@ -169,7 +180,8 @@ func Heuristic(row, col int, end Node) int { // Heuristique simple : distance de Manhattan // On introduit de l'aléatoire pour ajouter de la diversité dans la construction des chemins // On évite d'avoir tout le temps le même chemin pour un même point de départ et d'arrivé - return abs(row-end.row) + abs(col-end.col) + rand.Intn(3) + //return abs(row-end.row) + abs(col-end.col) + rand.Intn(3) + return abs(row-end.row) + abs(col-end.col) + rand.Intn(10) } func abs(x int) int { diff --git a/internal/simulation/agent.go b/internal/simulation/agent.go index 53bd71836d92fbfe12821a7f2008d0f8931829e1..f90daf0b5114a74ac4300b5e8adc708b30cfe377 100644 --- a/internal/simulation/agent.go +++ b/internal/simulation/agent.go @@ -9,13 +9,9 @@ package simulation */ import ( - //"fmt" - - //"log" + "fmt" + "log" "math/rand" - - //"math" - //"math/rand" alg "metrosim/internal/algorithms" "time" ) @@ -27,9 +23,10 @@ const ( Mark Wait Move - Disapear + Disappear Expel // virer l'agent Stop // arreter l'agent + GiveInfos ) type Coord [2]int @@ -76,14 +73,7 @@ func NewRequest(demandeur chan Request, decision int) (req *Request) { func NewAgent(id string, env *Environment, syncChan chan int, vitesse time.Duration, force int, politesse bool, behavior Behavior, departure, destination Coord, width, height int) *Agent { isOn := make(map[Coord]string) - saveCells(&env.station, isOn, departure, width, height, 0) - // Enregistrement des panneaux menant à la zone - // visitedPanneaux := make(map[alg.Node]bool, len(env.panneaux[env.zones[destination]])) - // for _, panneau := range env.panneaux[env.zones[destination]] { - // visitedPanneaux[panneau] = false - // } - // visiting := alg.NewNode(destination[0], destination[1], 0, HeuristicWithObstacles(departure, destination, env), 0, 0) - return &Agent{AgentID(id), vitesse, force, politesse, departure, departure, destination, behavior, env, syncChan, Noop, isOn, false, width, height, 0, make([]alg.Node, 0), nil, 0} + return &Agent{AgentID(id), vitesse, force, politesse, departure, departure, destination, behavior, env, syncChan, Noop, isOn, false, width, height, 3, make([]alg.Node, 0), nil,0} } func (ag *Agent) ID() AgentID { @@ -91,8 +81,8 @@ func (ag *Agent) ID() AgentID { } func (ag *Agent) Start() { - //log.Printf("%s starting...\n", ag.id) - + log.Printf("%s starting...\n", ag.id) + go ag.listenForRequests() go func() { var step int for { @@ -101,7 +91,7 @@ func (ag *Agent) Start() { ag.behavior.Deliberate(ag) ag.behavior.Act(ag) ag.syncChan <- step - if ag.decision == Disapear { + if ag.decision == Disappear { ag.env.RemoveAgent(*ag) return } @@ -124,6 +114,10 @@ func IsMovementSafe(path []alg.Node, agt *Agent, env *Environment) (bool, int) { // Calcul des bornes de position de l'agent avant mouvement infRow, supRow, infCol, supCol := calculateBounds(agt.position, agt.width, agt.height, agt.orientation) + // Si pas encore sur la map, mais agent déja sur la position, on ne peut pas encore apparaître + if len(agt.isOn) == 0 && len(env.station[agt.path[0].Row()][agt.path[0].Col()]) > 1 { + return false, agt.orientation + } // Simulation du déplacement ag := *agt ag.position = Coord{path[0].Row(), path[0].Col()} @@ -165,16 +159,13 @@ func IsAgentBlocking(path []alg.Node, agt *Agent, env *Environment) bool { for or := 0; or < 4; or++ { rotateAgent(&ag, or) blocking := false - //Test - // Calcul des bornes de position de l'agent après mouvement borneInfRow, borneSupRow, borneInfCol, borneSupCol := calculateBounds(ag.position, ag.width, ag.height, ag.orientation) - + //fmt.Println(ag.id,borneInfRow,borneInfRow, borneSupRow, borneInfCol, borneSupCol) if !(borneInfCol < 0 || borneInfRow < 0 || borneSupRow > 20 || borneSupCol > 20) { for i := borneInfRow; i < borneSupRow; i++ { for j := borneInfCol; j < borneSupCol; j++ { - if !(j >= infCol && j < supCol && i >= infRow && i < supRow) && env.station[i][j] == "A" { - + if !(j >= infCol && j < supCol && i >= infRow && i < supRow) && len(env.station[i][j]) > 2 { // Si on n'est pas sur une case atteignable, en dehors de la zone qu'occupe l'agent avant déplacement, on est bloqué blocking = true } @@ -208,7 +199,7 @@ func (ag *Agent) isStuck() bool { count++ } // Case inaccessible - if i < 0 || j < 0 || i > 19 || j > 19 || ag.env.station[i][j] == "X" || ag.env.station[i][j] == "Q" || existAgent(ag.env.station[i][j]) { + if i < 0 || j < 0 || i > 19 || j > 19 || ag.env.station[i][j] == "X" || ag.env.station[i][j] == "Q" || len(ag.env.station[i][j]) > 2 { not_acc++ } @@ -248,26 +239,27 @@ func (ag *Agent) MoveAgent() { if len(ag.path) == 0 { start, end := ag.generatePathExtremities() // Recherche d'un chemin si inexistant - path := alg.FindPath(ag.env.station, start, end, *alg.NewNode(-1, -1, 0, 0, 0, 0), false) + path := alg.FindPath(ag.env.station, start, end, *alg.NewNode(-1, -1, 0, 0, 0, 0), false, 2*time.Second) ag.path = path } // ================== Etude de faisabilité ======================= if IsAgentBlocking(ag.path, ag, ag.env) { + if ag.politesse { start, end := ag.generatePathExtremities() // Si un agent bloque notre déplacement, on attend un temps aléatoire, et reconstruit time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond) - path := alg.FindPath(ag.env.station, start, end, *alg.NewNode(-1, -1, 0, 0, 0, 0), false) + path := alg.FindPath(ag.env.station, start, end, *alg.NewNode(-1, -1, 0, 0, 0, 0), false,2*time.Second) ag.path = path return } else { //Si individu impoli, demande à l'agent devant de bouger //On récupère le id de la personne devant blockingAgentID := AgentID(ag.WhichAgent()) - blockingAgent := ag.env.FindAgentByID(blockingAgentID) + //blockingAgent := ag.env.FindAgentByID(blockingAgentID) var reqToBlockingAgent *Request - var reqToImpoliteAgent *Request + //var reqToImpoliteAgent *Request i := 0 accept := false for !accept && i < 3 { @@ -282,7 +274,7 @@ func (ag *Agent) MoveAgent() { */ - + /* //BlockingAgent cherche si autour de lui c'est vide possible, or := IsMovementSafe(blockingAgent.path, blockingAgent, blockingAgent.env) @@ -295,6 +287,7 @@ func (ag *Agent) MoveAgent() { coordBlockingAgent := blockingAgent.position //Gérer le déplacement de Ag et de BlockingAgent + déplacement en fonction de la force !!!!!!!!!!!!!!!!!!!!!!!!!!!!! } + */ } } } @@ -302,13 +295,11 @@ func (ag *Agent) MoveAgent() { // ================== Déplacement si aucun problème ou si blockingAgent se pousse ======================= safe, or := IsMovementSafe(ag.path, ag, ag.env) if safe { - RemoveAgent(&ag.env.station, ag) - rotateAgent(ag, or) // mise à jour de l'orientation - //ag.env.station[ag.coordBasOccupation[0]][ag.coordBasOccupation[1]] = ag.isOn - - //MODIFICATION DE DIRECTION + if len(ag.isOn) > 0 { + RemoveAgent(&ag.env.station, ag) + } + rotateAgent(ag, or) ag.direction = calculDirection(ag.position, Coord{ag.path[0].Row(), ag.path[0].Col()}) - //fmt.Println("[MoveAgent]Direction : ", ag.direction) ag.position[0] = ag.path[0].Row() ag.position[1] = ag.path[0].Col() if len(ag.path) > 1 { @@ -317,12 +308,11 @@ func (ag *Agent) MoveAgent() { ag.path = nil } saveCells(&ag.env.station, ag.isOn, ag.position, ag.width, ag.height, ag.orientation) - //ag.env.station[ag.coordBasOccupation[0]][ag.coordBasOccupation[1]] = "A" writeAgent(&ag.env.station, ag) // ============ Prise en compte de la vitesse de déplacement ====================== time.Sleep(ag.vitesse * time.Millisecond) - } + } func (ag *Agent) generatePathExtremities() (alg.Node, alg.Node) { @@ -428,3 +418,16 @@ func calculateBounds(position Coord, width, height, orientation int) (infRow, su } return borneInfRow, borneSupRow, borneInfCol, borneSupCol } + +func (ag *Agent) listenForRequests() { + for { + if ag.request == nil { + req := <-ag.env.agentsChan[ag.id] + fmt.Println("Request received by UsagerLambda:", req.decision) + ag.request = &req + if req.decision == Disappear { + return + } + } + } +} diff --git a/internal/simulation/controleur.go b/internal/simulation/controleur.go index bbd400f8c696a11dcb57f6118418874f53893e48..bc17235c7803339b1a604efba5af299421e80fae 100644 --- a/internal/simulation/controleur.go +++ b/internal/simulation/controleur.go @@ -3,10 +3,11 @@ package simulation //ajouter liste des agents déjà controllés import ( + "fmt" "math/rand" "regexp" "time" - //"fmt" + //"time" ) /* @@ -73,9 +74,9 @@ func (c *Controleur) Act(ag *Agent) { } else if ag.decision == Wait { n := rand.Intn(2) // temps d'attente aléatoire time.Sleep(time.Duration(n) * time.Second) - } else { // Expel ou Wait - agt_face_id := AgentID(c.faceCase) //id de l'agent qui se trouve devant le controleur + } else { + 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 - //fmt.Print("[Controlleur , Act ]requête envoyée à l'agent ", agt_face_id, "\n") } } diff --git a/internal/simulation/env.go b/internal/simulation/env.go index 9d7f02e4b1eb43b7626ccd0013189b69c695bb13..9dbca0de1fcb8f16ed328c4a62467aa0e9d743bf 100644 --- a/internal/simulation/env.go +++ b/internal/simulation/env.go @@ -16,13 +16,6 @@ type Environment struct { // panneaux map[ZoneID][]alg.Node // Les panneaux de la station, permettant d'aller vers la zone } -type ZoneID int - - - - - - func NewEnvironment(ags []Agent, carte [20][20]string, agentsCh map[AgentID]chan Request) (env *Environment) { mapControlle := make(map[AgentID]bool) for _, ag := range ags { @@ -31,7 +24,6 @@ func NewEnvironment(ags []Agent, carte [20][20]string, agentsCh map[AgentID]chan return &Environment{ags: ags, agentCount: len(ags), station: carte, agentsChan: agentsCh, controlledAgents: mapControlle} } - func (env *Environment) AddAgent(agt Agent) { env.ags = append(env.ags, agt) env.agentCount++ @@ -39,9 +31,10 @@ func (env *Environment) AddAgent(agt Agent) { func (env *Environment) RemoveAgent(agt Agent) { for i := 0; i < len(env.station); i++ { - if env.ags[i].id == agt.id{ + if env.ags[i].id == agt.id { // Utiliser la syntaxe de découpage pour supprimer l'élément env.ags = append(env.ags[:i], env.ags[i+1:]...) + delete(env.agentsChan,agt.id) // Sortir de la boucle après avoir trouvé et supprimé l'élément break } @@ -79,7 +72,6 @@ func (env *Environment) Rect() Coord { return Coord{0, 0} } - func (env *Environment) GetAgentChan(agt_id AgentID) chan Request { return env.agentsChan[agt_id] } @@ -102,4 +94,4 @@ func calculDirection(depart Coord, arrive Coord) int { return 2 //bas } } -} \ No newline at end of file +} diff --git a/internal/simulation/metro.go b/internal/simulation/metro.go new file mode 100644 index 0000000000000000000000000000000000000000..a31708b76854f47807cac797f2f2fbfc72c3365f --- /dev/null +++ b/internal/simulation/metro.go @@ -0,0 +1,82 @@ +package simulation + +import ( + "fmt" + "log" + "math/rand" + "time" +) + +type Metro struct { + frequency time.Duration + stopTime time.Duration + freeSpace int // nombre de cases disponibles dans le métro + env *Environment + comChannel chan Request + way *Way +} + +func NewMetro(freq time.Duration, stopT time.Duration, freeS int, env *Environment, way *Way) *Metro { + return &Metro{ + frequency: freq, + stopTime: stopT, + freeSpace: freeS, + env: env, + comChannel: make(chan Request), + way: way, + } +} + +func (metro *Metro) Start() { + log.Printf("Metro starting...\n") + refTime := time.Now() + go func() { + //var step int + for { + //step = <-metro.syncChan + if refTime.Add(metro.frequency).Before(time.Now()) { + go metro.pickUpUsers() + metro.freeSpace = rand.Intn(10) + fmt.Println(metro.way.id, metro.freeSpace) + //go metro.dropUsers() + refTime = time.Now() + } + //metro.syncChan <- step + + } + }() +} + +func (metro *Metro) pickUpUsers() { + // Faire monter les usagers dans le métro + t := time.Now() + for time.Now().Before(t.Add(metro.stopTime)) { + if metro.freeSpace > 0 { + for _, gate := range metro.way.gates { + go metro.pickUpGate(&gate) + } + } + } +} + +func (metro *Metro) pickUpGate(gate *Coord) { + // Récupérer les usagers à une porte spécifique + gate_cell := metro.env.station[gate[0]][gate[1]] + if len(gate_cell) > 1 { + agent := metro.findAgent(AgentID(gate_cell)) + if agent != nil && agent.width*agent.height <= metro.freeSpace && agent.destination == *gate { + metro.env.agentsChan[agent.id] <- *NewRequest(metro.comChannel, Disappear) + metro.freeSpace-- + } + } +} + +func (metro *Metro) findAgent(agent AgentID) *Agent { + // Trouver l'adresse de l'agent + for _, agt := range metro.env.ags { + if agt.id == agent { + return &agt + } + } + return nil +} diff --git a/internal/simulation/simu.go b/internal/simulation/simu.go index 1d39fc2b5f6d5bb058e6307fd92254a3f6d78157..4f93e7d8e2a42141e36dec7970b3467ea4c7acb1 100644 --- a/internal/simulation/simu.go +++ b/internal/simulation/simu.go @@ -41,7 +41,6 @@ var carte [20][20]string = [20][20]string{ {"X", "X", "X", "X", "S", "S", "X", "X", "X", "X", "X", "X", "E", "E", "X", "X", "X", "X", "X", "X"}, } - var playground [20][20]string = [20][20]string{ {"_", "X", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_"}, {"_", "X", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_"}, @@ -73,6 +72,7 @@ type Simulation struct { step int // Stats start time.Time syncChans sync.Map + metros []Metro } func (sim *Simulation) Env() *Environment { @@ -87,32 +87,37 @@ func NewSimulation(agentCount int, maxStep int, maxDuration time.Duration) (simu // Communication entre agents mapChan := make(map[AgentID]chan Request) + + // Création de l'environement simu.env = *NewEnvironment([]Agent{}, carte, mapChan) //simu.env = *NewEnvironment([]Agent{}, playground, mapChan) + // Création du métro + metro1 := *NewMetro(10*time.Second, 5*time.Second, 2, &simu.env, NewWay(1, []Coord{{8, 5}})) + metro2 := *NewMetro(10*time.Second, 5*time.Second, 2, &simu.env, NewWay(2, []Coord{{13, 4}})) + simu.metros = []Metro{metro1, metro2} + // création des agents et des channels for i := 0; i < agentCount; i++ { // création de l'agent - + syncChan := make(chan int) //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{} - - if i%2==0{ //Type Agent + + if i%2 == 0 { //Type Agent id := fmt.Sprintf("Agent%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, 1000, 0, true, &UsagerLambda{}, Coord{16, 5+i}, Coord{0, 8}, 1, 1) - }else{ // Type Controleur - id := fmt.Sprintf("Controleur%d", i) - //ag = NewAgent(id, &simu.env, syncChan, 1000, 0, true, &UsagerLambda{}, Coord{1, 8}, Coord{8, 5}, 1, 1) - ag = NewAgent(id, &simu.env, syncChan, 1000, 0, true, &Controleur{}, Coord{16, 12}, Coord{18, 4}, 1, 1) + ag = NewAgent(id, &simu.env, syncChan, 200, 0, true, &UsagerLambda{}, Coord{18, 4}, Coord{13, 4}, 1, 1) + } else { // Type Controleur + //id := fmt.Sprintf("Controleur%d", i) + id := fmt.Sprintf("Agent%d", i) + ag = NewAgent(id, &simu.env, syncChan, 200, 0, true, &UsagerLambda{}, Coord{1, 8}, Coord{8, 5}, 1, 1) + //ag = NewAgent(id, &simu.env, syncChan, 1000, 0, true, &Controleur{}, Coord{18, 12}, Coord{18, 4}, 1, 1) } - - + //ag := NewAgent(id, &simu.env, syncChan, 1000, 0, true, &UsagerLambda{}, Coord{19, 12}, Coord{0, 8}, 2, 1) // ajout de l'agent à la simulation @@ -129,13 +134,11 @@ func NewSimulation(agentCount int, maxStep int, maxDuration time.Duration) (simu simu.env.agentsChan[ag.id] = make(chan Request) } - - return simu } func (simu *Simulation) Run() { - // A REVOIR si nécessaire de faire appeler simu.env.pi() + // A REVOIR si nécessaire de faire appeler simu.env.pi() log.Printf("Démarrage de la simulation [step: %d, π: %f]", simu.step, simu.env.PI()) // Démarrage du micro-service de Log go simu.Log() @@ -156,6 +159,15 @@ func (simu *Simulation) Run() { // On sauvegarde la date du début de la simulation simu.start = time.Now() + // Lancement des métros + for _, metro := range simu.metros { + wg.Add(1) + go func(metro Metro) { + defer wg.Done() + metro.Start() + }(metro) + } + // Lancement de l'orchestration de tous les agents // simu.step += 1 // plus de sens for _, agt := range simu.agents { @@ -164,8 +176,8 @@ func (simu *Simulation) Run() { for { step++ c, _ := simu.syncChans.Load(agt.ID()) // communiquer les steps aux agents - c.(chan int) <- step // /!\ utilisation d'un "Type Assertion" - time.Sleep(1 * time.Millisecond) // "cool down" + c.(chan int) <- step // /!\ utilisation d'un "Type Assertion" + time.Sleep(1 * time.Millisecond) // "cool down" <-c.(chan int) } }(agt) @@ -176,7 +188,6 @@ func (simu *Simulation) Run() { log.Printf("Fin de la simulation [step: %d, in: %d, out: %d, π: %f]", simu.step, simu.env.PI()) } - func (simu *Simulation) Print_v0() { for { for i := 0; i < 20; i++ { @@ -191,28 +202,26 @@ func (simu *Simulation) Print_v0() { } } func (simu *Simulation) Print() { - for { - for i := 0; i < 20; i++ { - for j := 0; j < 20; j++ { - element := simu.env.station[i][j] - if len(element) > 1 { - fmt.Print(string(element[0]) + " ") // Afficher le premier caractère si la longueur est supérieure à 1 - } else { - fmt.Print(element+" ") - } - } - fmt.Println() - } - fmt.Println() + for { + for i := 0; i < 20; i++ { + for j := 0; j < 20; 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.Println() + } fmt.Println() - //fmt.Println("============================================================") - //time.Sleep(time.Second / 4) // 60 fps ! - time.Sleep(500 * time.Millisecond) // 1 fps ! - //fmt.Print("\033[H\033[2J") // effacement du terminal - } + //fmt.Println("============================================================") + //time.Sleep(time.Second / 4) // 60 fps ! + time.Sleep(500 * time.Millisecond) // 1 fps ! + //fmt.Print("\033[H\033[2J") // effacement du terminal + } } - func (simu *Simulation) Log() { // Not implemented } diff --git a/internal/simulation/usagerLambda.go b/internal/simulation/usagerLambda.go index 216a45fd9902003a57db5a789403756f3ec63384..476751e00ba6ca85cf96915f9449768c74072a30 100644 --- a/internal/simulation/usagerLambda.go +++ b/internal/simulation/usagerLambda.go @@ -2,6 +2,7 @@ package simulation import ( //"fmt" + "fmt" "math/rand" alg "metrosim/internal/algorithms" "time" @@ -15,12 +16,23 @@ func (ul *UsagerLambda) Percept(ag *Agent) { // récupérer le channel de l'agent lambda //fmt.Println("[AgentLambda, Percept] direction ", ag.direction) - chan_agt := ag.env.GetAgentChan(ag.id) - select { - case req := <-chan_agt: //verifier si l'agent est communiqué par un autre agent, par exemple un controleur lui a demandé de s'arreter - //fmt.Println("[AgentLambda, Percept] Requete recue par l'agent lambda : ", req.decision) - ul.req = req - case <-time.After(time.Second): + // chan_agt := ag.env.GetAgentChan(ag.id) + // select { + // case req := <-chan_agt: //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 : ", req.decision, "\n") + // ul.req = req + // case <-time.After(100 * time.Millisecond): + // ag.stuck = ag.isStuck() + // if ag.stuck { + // return + + // } + // } + 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 @@ -37,9 +49,11 @@ func (ul *UsagerLambda) Deliberate(ag *Agent) { ag.decision = Wait } 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 ag.decision = Expel - } else if ag.position == ag.destination && (ag.isOn[ag.position] == "W" || ag.isOn[ag.position] == "S") { - //fmt.Println(ag.id, "disapear") - ag.decision = Disapear + } else if ul.req.decision == Disappear || (ag.position == ag.destination && (ag.isOn[ag.position] == "W" || ag.isOn[ag.position] == "S")) { + fmt.Println(ag.id, "disapear") + ag.decision = Disappear + } else if ul.req.decision == Wait { + ag.decision = Wait } else { ag.decision = Move } @@ -52,7 +66,7 @@ func (ul *UsagerLambda) Act(ag *Agent) { } 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 == Disapear { + } else if ag.decision == Disappear { RemoveAgent(&ag.env.station, ag) } else { //age.decision == Expel //fmt.Println("[AgentLambda, Act] Expel") diff --git a/internal/simulation/way.go b/internal/simulation/way.go new file mode 100644 index 0000000000000000000000000000000000000000..87212b517ae3fa6b73a3df679c04dbc661960854 --- /dev/null +++ b/internal/simulation/way.go @@ -0,0 +1,14 @@ +package simulation + +type Way struct { + id WayID + gates []Coord //listes des portes associée à la voie +} + +type WayID int + +func NewWay(wayId WayID, gates []Coord) *Way { + return &Way{ + id: wayId, + gates: gates} +}