-
julienpillis authoredjulienpillis authored
mobiliteReduite.go 4.14 KiB
package simulation
/*
L'agent à Mobilité Reduite cherche la porte du metro la plus proche de lui
*/
import (
"fmt"
"math/rand"
alg "metrosim/internal/algorithms"
req "metrosim/internal/request"
"sort"
"time"
)
type MobiliteReduite struct {
req *req.Request
//once sync.Once
}
func (mr *MobiliteReduite) Percept(ag *Agent) {
//mr.once.Do(func(){mr.setUpDestination(ag)}) // on initialise la destination la plus proche, 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())
mr.req = ag.request
default:
ag.stuck = ag.isStuck()
if ag.stuck {
return
}
}
}
func (mr *MobiliteReduite) Deliberate(ag *Agent) {
//fmt.Println("[AgentLambda Deliberate] decision :", ul.req.decision)
if mr.req != nil {
switch mr.req.Decision() {
case Expel: // sinon alors la requete est de type "Viré" cette condition est inutile car MR ne peut pas etre expulsé , elle est nécessaire pour les agents fraudeurs
//fmt.Println("[AgentLambda, Deliberate] Expel")
ag.decision = Expel
return
case Disappear:
fmt.Println("[Deliberate]", ag.id, "Disappear cond 1 (requete)")
ag.decision = Disappear
return
case Wait:
ag.decision = Wait
return
case EnterMetro:
fmt.Println("[MobiliteReduite, Deliberate] EnterMetro")
ag.decision = EnterMetro
return
case YouHaveToMove:
//fmt.Println("J'essaye de bouger")
movement := ag.MoveAgent()
//fmt.Printf("Je suis agent %s Resultat du mouvement de la personne %t \n", ag.id, movement)
if movement {
ag.decision = Done
} else {
ag.decision = Noop
}
return
default:
ag.decision = Move
return
}
} 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("[Deliberate]",ag.id, "Disappear cond 2")
ag.decision = Disappear
/*}else if (ag.position != ag.departure && ag.position == ag.destination){
// si l'agent est arrivé à la porte mais n'a pas reçu une requete du metro pour entrer, il attend
ag.decision = Wait [A REVOIR]
}*/
} else if ag.stuck { // si l'agent est bloqué
ag.decision = Wait
} else {
ag.decision = Move
}
}
func (mr *MobiliteReduite) Act(ag *Agent) {
//fmt.Println("[AgentLambda Act] decision :",ag.decision)
switch ag.decision {
case Move:
//mr.MoveMR(ag)
ag.MoveAgent()
case Wait:
n := rand.Intn(2) // temps d'attente aléatoire
time.Sleep(time.Duration(n) * time.Second)
case Disappear:
ag.env.RemoveAgent(ag)
case 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)
//mr.MoveMR(ag)
ag.MoveAgent()
case EnterMetro:
fmt.Printf("[MobiliteReduite, Act %s] EnterMetro \n", ag.id)
ag.env.RemoveAgent(ag)
mr.req.Demandeur() <- *req.NewRequest(ag.env.agentsChan[ag.id], ACK)
}
ag.request = nil
}
/*
* Fonction qui permet de définir la destination d'un agent à mobilité réduite
*/
func (mr *MobiliteReduite) SetUpDestination(ag *Agent) {
choix_voie := rand.Intn(len(ag.env.metros)) // choix de la voie de métro aléatoire
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
}