From 7cfe3f6dcf66750e40d213710650b73f461263f8 Mon Sep 17 00:00:00 2001 From: jrafei <jana.eltayeb-el-rafei@etu.utc.fr> Date: Tue, 12 Dec 2023 20:35:23 +0100 Subject: [PATCH] first_modifs --- cmd/test/main.go | 26 ++++++++++ internal/simulation/agent.go | 18 +++++-- internal/simulation/controleur.go | 77 +++++++++++++++++++++++++++++ internal/simulation/env.go | 13 ++++- internal/simulation/simu.go | 8 ++- internal/simulation/usagerLambda.go | 40 ++++++++++++--- 6 files changed, 168 insertions(+), 14 deletions(-) create mode 100644 cmd/test/main.go create mode 100644 internal/simulation/controleur.go diff --git a/cmd/test/main.go b/cmd/test/main.go new file mode 100644 index 0000000..f5e5e2d --- /dev/null +++ b/cmd/test/main.go @@ -0,0 +1,26 @@ +package main + +import ( + "fmt" + "regexp" +) + +func main() { + faceCase := "Agent1000" // Remplacez ceci par votre variable + + // Créer l'expression régulière + regexPattern := `^Agent\d+$` // \d+ correspond à un ou plusieurs chiffres + matched, err := regexp.MatchString(regexPattern, faceCase) + + if err != nil { + fmt.Println("Erreur lors de l'analyse de la regex :", err) + return + } + + // Vérifiez si la chaîne ne correspond pas au motif + if !matched { + fmt.Println("La chaîne ne correspond pas au motif 'Agentx'") + } else { + fmt.Println("La chaîne correspond au motif 'Agentx'") + } +} diff --git a/internal/simulation/agent.go b/internal/simulation/agent.go index 5013677..b775130 100644 --- a/internal/simulation/agent.go +++ b/internal/simulation/agent.go @@ -24,6 +24,7 @@ const ( Mark Wait Move + Expel // decision du Controleur ) type Coord [2]int @@ -45,19 +46,30 @@ type Agent struct { stuck bool width int height int - orientation int + orientation int //0 : vers le haut, 1 : vers la droite, 2 : vers le bas, 3 : vers la gauche + request *Request } +type Request struct { + demandeur AgentID + decision int +} + + type Behavior interface { Percept(*Agent) Deliberate(*Agent) Act(*Agent) } +func NewRequest(demandeur AgentID, decision int) (req *Request) { + return &Request{demandeur, decision} +} + 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) - return &Agent{AgentID(id), vitesse, force, politesse, departure, departure, destination, behavior, env, syncChan, Noop, isOn, false, width, height, 0} + return &Agent{AgentID(id), vitesse, force, politesse, departure, departure, destination, behavior, env, syncChan, Noop, isOn, false, width, height, 0, nil} } func (ag *Agent) ID() AgentID { @@ -229,7 +241,7 @@ func writeAgent(matrix *[20][20]string, agt *Agent) { for i := borneInfRow; i < borneSupRow; i++ { for j := borneInfCol; j < borneSupCol; j++ { - matrix[i][j] = "A" + matrix[i][j] = string(agt.id) } } diff --git a/internal/simulation/controleur.go b/internal/simulation/controleur.go new file mode 100644 index 0000000..b7e3ea0 --- /dev/null +++ b/internal/simulation/controleur.go @@ -0,0 +1,77 @@ +package simulation + +import ( + "math/rand" + "time" + "regexp" + "fmt" +) + + +/* + 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{ + faceCase string // chaine de caractère qui contient l'id de l'agent qui se trouve devant le controleur, exemple : "Agent1", "Fraudeur1", "X" ,etc. +} + +func (c *Controleur) Percept(ag *Agent) { + env := ag.env + + if ag.orientation == 0 { // vers le haut + c.faceCase = env.station[ag.position[0]-1][ag.position[1]] + } else if ag.orientation == 1 { // vers la droite + c.faceCase = env.station[ag.position[0]][ag.position[1]+1] + } else if ag.orientation == 2 { // vers le bas + c.faceCase = env.station[ag.position[0]+1][ag.position[1]] + } else { // vers la gauche + c.faceCase = env.station[ag.position[0]][ag.position[1]-1] + } + +} + + +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 + regexFraudeur := `^Fraudeur\d+$` + + // 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) + + if err1 != nil || err2 != nil { + fmt.Println("Erreur lors de l'analyse de la regex :", err1, err2) + return + } else { + if matchedAgt { + ag.decision = Wait // arreter l'agent devant lui + } else if matchedFraud { + ag.decision = Expel // virer l'agent devant lui + } else{ + // Comportement de l'usager lambda (par defaut) + if ag.stuck { + ag.decision = Wait + } else { + ag.decision = Move + } + } + } +} + +func (c *Controleur) Act(ag *Agent) { + 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 { + agt_face_id := AgentID(c.faceCase) + ag.env.agentsChan[agt_face_id] <- *NewRequest(ag.id, ag.decision) // envoie la decision du controleur à l'agent qui se trouve devant lui + } +} diff --git a/internal/simulation/env.go b/internal/simulation/env.go index 107b44e..5ed6c4b 100644 --- a/internal/simulation/env.go +++ b/internal/simulation/env.go @@ -10,13 +10,17 @@ type Environment struct { ags []Agent agentCount int station [20][20]string - agentsChan map[AgentID]chan AgentID + agentsChan map[AgentID]chan Request } -func NewEnvironment(ags []Agent, carte [20][20]string, agentsCh map[AgentID]chan AgentID) (env *Environment) { + + + +func NewEnvironment(ags []Agent, carte [20][20]string, agentsCh map[AgentID]chan Request) (env *Environment) { return &Environment{ags: ags, agentCount: len(ags), station: carte, agentsChan: agentsCh} } + func (env *Environment) AddAgent(agt Agent) { env.ags = append(env.ags, agt) env.agentCount++ @@ -51,3 +55,8 @@ func (env *Environment) PI() float64 { func (env *Environment) Rect() Coord { return Coord{0, 0} } + + +func (env *Environment) GetAgentChan(agt_id AgentID) chan Request { + return env.agentsChan[agt_id] +} \ No newline at end of file diff --git a/internal/simulation/simu.go b/internal/simulation/simu.go index 52a019e..04b7e22 100644 --- a/internal/simulation/simu.go +++ b/internal/simulation/simu.go @@ -18,6 +18,7 @@ import ( * Q : Voie * _ : Couloir, case libre * B: Bridge/Pont, zone accessible + * valeur de AgentID : Agent */ var carte [20][20]string = [20][20]string{ {"X", "X", "X", "X", "X", "X", "X", "X", "W", "W", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X"}, @@ -110,13 +111,14 @@ func NewSimulation(agentCount int, maxStep int, maxDuration time.Duration) (simu ag.env.AddAgent(*ag) // ajout - simu.env.agentsChan[ag.id] = make(chan AgentID) + simu.env.agentsChan[ag.id] = make(chan Requete) } return simu } func (simu *Simulation) Run() { + // 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 @@ -145,7 +147,7 @@ func (simu *Simulation) Run() { step := 0 for { step++ - c, _ := simu.syncChans.Load(agt.ID()) + 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) @@ -163,6 +165,8 @@ func (simu *Simulation) Print() { for i := 0; i < 20; i++ { fmt.Println(simu.env.station[i]) } + 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 diff --git a/internal/simulation/usagerLambda.go b/internal/simulation/usagerLambda.go index 843be37..1041644 100644 --- a/internal/simulation/usagerLambda.go +++ b/internal/simulation/usagerLambda.go @@ -5,19 +5,27 @@ import ( "time" ) -type UsagerLambda struct{} +type UsagerLambda struct{ + req Request +} func (ul *UsagerLambda) Percept(ag *Agent) { - ag.stuck = ag.isStuck() - if ag.stuck { - return - + // récupérer le channel de l'agent lambda + 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 + ul.req = req + case <- time.After(time.Second): + ag.stuck = ag.isStuck() } - } func (ul *UsagerLambda) Deliberate(ag *Agent) { - if ag.stuck { + if ul.req.decision == Wait{ + ag.decision = Wait + } else if ul.req.decision == Expel{ + ag.decision = Expel + } else if ag.stuck { ag.decision = Wait } else { ag.decision = Move @@ -30,6 +38,24 @@ 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 { + ag.destination = ul.findNearestExit(ag.env) + ag.MoveAgent() } +} + +/* + * Fonction qui permet de trouver la sortie la plus proche +*/ +func (ul *UsagerLambda) findNearestExit(env *Environment) Coord{ + station := env.station + for i := 0; i < len(station); i++ { + for j := 0; j < len(station[i]); j++ { + if station[i][j] == "X" { + return Coord{i,j} + } + } + } + return Coord{0,0} } -- GitLab