Engineering School, 2nd year
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

403 lines
10 KiB

#|
| #(@)connexion.lsp ENSICAEN 2006-01-09
|
| @author MASSE Nicolas <nicolas27.masse@laposte.net>
| @author LIMIN Thomas <thomas.limin@laposte.net>
|
| ENSICAEN
| 6 Boulevard Marechal Juin
| F-14050 Caen Cedex
|
| Ce fichier est l'oeuvre d'eleves de l'ENSI de Caen. Il ne peut etre
| reproduit, utilise ou modifie sans l'avis express de ses auteurs.
|#
#|
| Initiation à la programmation avec des agents.
|#
#|
| version: 2006-02-07
|
| done: all
|
| todo: none
|#
#|
| Classe Connexion.
|
|#
(defclass Connexion ()
((nom
:accessor nom
:initarg :nom
:initform nil
:documentation "Le nom de la connexion"
)
(boitiers
:accessor boitiers
:initarg :boitiers
:initform nil
:documentation "La liste des boitiers reliés à cette connexion"
)
(provenance
:accessor provenance
:initarg :provenance
:initform nil
:documentation "La référence du boitier qui a mis la valeur de cet objet"
)
(valeur
:accessor valeur
:initarg :valeur
:initform nil
:documentation "La valeur de cette connexion"
)
(gestionnaire
:accessor gestionnaire
:initform nil
:documentation "Le gestionnaire de l'application"
))
(:documentation "Une connexion a un nom et relie des boitiers")
)
#|
| Mets une valeur dans cette connexion, et propage la valeur aux boitiers
| voisins.
|#
(defmethod mettre-valeur (val demandeur (oself Connexion))
(cond
((null (valeur oself))
(setf (valeur oself) val)
(format t "~s: valeur modifiée~%" oself)
(setf (provenance oself) demandeur)
(mapcar #'(lambda (x)
(if (not (eql demandeur x))
(attention-une-valeur oself x)
)
)
(boitiers oself)
)
)
((= val (valeur oself))
(format t "~s: valeur non modifiée mais identique~%" oself)
)
(t
(format t "~s: valeurs differentes, valeur non modifiée !~%" oself)
(il-y-a-incoherence oself (gestionnaire oself))
)
)
)
#|
| Oublie la valeur de cette connexion et propage l'oubli aux boitiers voisins.
|#
(defmethod oublier-valeur (demandeur (oself Connexion))
(cond
((or (null (valeur oself)) (null (provenance oself)))
t
)
((eql demandeur (provenance oself))
(setf (valeur oself) nil)
(format t "~s: valeur oubliée~%" oself)
(mapcar #'(lambda (x)
(if (not (eql demandeur x))
(plus-de-valeur oself x)
)
)
(boitiers oself)
)
t
)
(t
(format t "~s: valeur non oubliée~%" oself)
nil
)
)
)
#|
| Modifie la valeur de la connexion après l'avoir oubliée.
|#
(defmethod modifier-valeur (val demandeur (oself Connexion))
(if (oublier-valeur demandeur oself)
(mettre-valeur val demandeur oself)
)
)
#|
| Classe Boitier
|#
(defclass Boitier ()
((borne1
:accessor borne1
:initarg :borne1
:initform nil
:documentation "La borne première borne d'entrée"
)
(borne2
:accessor borne2
:initarg :borne2
:initform nil
:documentation "La seconde borne d'entrée"
)
(borneS
:accessor borneS
:initarg :borneS
:initform nil
:documentation "La borne de sortie"
))
(:documentation "Un boitier a deux connexions d'entrée et une de sortie")
)
#|
| Surcharge de la méthode initialize-instance, le mot clé after
| indique que la surcharge s'execute après la méthode de base,
| prédéfinie et toujours executée après make-instance (Sorte de
| constructeur automatique). Le oself est un nom choisi pour
| référencer l'objet en cours, correspond au self de Smalltalk
|#
(defmethod initialize-instance :after ((oself Boitier) &rest args)
(declare (ignore args))
; Raccorde les bornes au boitier
(setf (boitiers (borne1 oself)) (cons oself (boitiers (borne1 oself))))
(setf (boitiers (borne2 oself)) (cons oself (boitiers (borne2 oself))))
(setf (boitiers (borneS oself)) (cons oself (boitiers (borneS oself))))
)
#|
| Méthode appelée par les connexions lorsqu'elles ont reçu une valeur.
|#
(defmethod attention-une-valeur (cnx (oself Boitier))
(format t "~s: attention une valeur !~%" oself )
)
#|
| Méthode appelée par les connexions lorsqu'elles ont perdu leur valeur.
|#
(defmethod plus-de-valeur (cnx (oself Boitier))
(format t "~s: attention plus de valeur !~%" oself)
(oublier-valeur oself (borne1 oself))
(oublier-valeur oself (borne2 oself))
(oublier-valeur oself (borneS oself))
(attention-une-valeur oself oself)
)
#|
| Définition de la classe Add(itionneur), qui hérite de Boitier
|#
(defclass Add (Boitier)
()
)
(defmethod attention-une-valeur :after (cnx (oself Add))
(cond
((and (not (null (valeur (borne1 oself)))) (not (null (valeur (borne2 oself)))))
(format t "~s: addition: je connais borne1 et borne2 ~%" oself)
(mettre-valeur (+ (valeur (borne1 oself)) (valeur (borne2 oself))) oself (borneS oself))
)
((and (not (null (valeur (borne1 oself)))) (not (null (valeur (borneS oself)))))
(format t "~s: addition: je connais borne1 et borneS ~%" oself)
(mettre-valeur (- (valeur (borneS oself)) (valeur (borne1 oself))) oself (borne2 oself))
)
((and (not (null (valeur (borne2 oself)))) (not (null (valeur (borneS oself)))))
(format t "~s: addition: je connais borne2 et borneS ~%" oself)
(mettre-valeur (- (valeur (borneS oself)) (valeur (borne2 oself))) oself (borne1 oself))
)
)
)
#|
| Définition de la classe Mul(iplieur), qui hérite de Boitier
|#
(defclass Mul (Boitier)
()
)
(defmethod attention-une-valeur :after (cnx (oself Mul))
(cond
((and (not (null (valeur (borne1 oself)))) (not (null (valeur (borne2 oself)))))
(format t "~s: multiplication: je connais borne1 et borne2 ~%" oself)
(mettre-valeur (* (valeur (borne1 oself)) (valeur (borne2 oself))) oself (borneS oself))
)
((and (not (null (valeur (borne1 oself)))) (not (null (valeur (borneS oself)))))
(format t "~s: multiplication: je connais borneS et borne1 ~%" oself)
(mettre-valeur (/ (valeur (borneS oself)) (valeur (borne1 oself))) oself (borne2 oself))
)
((and (not (null (valeur (borne2 oself)))) (not (null (valeur (borneS oself)))))
(format t "~s: multiplication: je connais borneS et borne2 ~%" oself)
(mettre-valeur (/ (valeur (borneS oself)) (valeur (borne2 oself))) oself (borne1 oself))
)
)
)
#|
| Classe Gestionnaire
|#
(defclass Gestionnaire ()
((historique
:accessor historique
:initform nil
:documentation "La liste des valeurs de toutes les connexions"
)
(incoherence
:accessor incoherence
:initform nil
:documentation "Permet de savoir s'il y a eu incohérence lors du calcul"
))
(:documentation "Un gestionnaire gère les opérations de d'annulation")
)
#|
| Ajoute la connexion à ce gestionnaire, afin qu'il gère les incohérences
| de la connexion.
|#
(defmethod ajouter-au-gestionnaire (cnx (oself Gestionnaire))
(setf (historique oself)
(cons
(list cnx (valeur cnx) (provenance cnx))
(historique oself)
)
)
(setf (gestionnaire cnx) oself)
)
#|
| Sauvegarde l'état de toutes les connexions. Méthode à appeler avant toute
| modification de valeur par l'utilisateur.
|#
(defmethod sauvegarde-gestionnaire ((oself Gestionnaire))
(setf (historique oself)
(loop for x in (historique oself) collect (list (car x) (valeur (car x)) (provenance (car x))))
)
)
#|
| Restauration des anciennes valeurs des connexions.
|#
(defmethod restauration-gestionnaire ((oself Gestionnaire))
(loop for x in (historique oself) do
(setf (valeur (car x)) (cadr x))
(setf (provenance (car x)) (caddr x))
)
(setf (incoherence oself) nil)
)
#|
| Méthode appelée par les connexions pour signaler une incohérence.
|#
(defmethod il-y-a-incoherence (cnx (oself Gestionnaire))
(setf (incoherence oself) t)
(format t "~s: INCOHERENCE DETECTEE !~%" cnx)
)
#|
| Teste le flag d'incohérence.
|#
(defmethod y-a-t-il-incoherence ((oself Gestionnaire))
(incoherence oself)
)
#|
| Créer les instances de Connexion
|#
(setq a (make-instance 'Connexion :nom "a"))
(setq b (make-instance 'Connexion :nom "b"))
(setq c (make-instance 'Connexion :nom "c"))
(setq d (make-instance 'Connexion :nom "d"))
(setq e (make-instance 'Connexion :nom "e"))
(setq f (make-instance 'Connexion :nom "f"))
(setq g (make-instance 'Connexion :nom "g"))
(setq h (make-instance 'Connexion :nom "h"))
(setq i (make-instance 'Connexion :nom "i"))
(setq j (make-instance 'Connexion :nom "j"))
#|
| Créer les instances de Boitier
|#
(setq mul1 (make-instance 'Mul :borne1 a :borne2 b :borneS c))
(setq mul2 (make-instance 'Mul :borne1 c :borne2 e :borneS d))
(setq mul3 (make-instance 'Mul :borne1 f :borne2 j :borneS h))
(setq add1 (make-instance 'Add :borne1 e :borne2 f :borneS g))
(setq add2 (make-instance 'Add :borne1 d :borne2 h :borneS i))
#|
| Créer le gestionnaire.
|#
(setq gest (make-instance 'Gestionnaire))
#|
| Fonction utilitaire.
|#
(defun affichage ()
(format t
"ETAT DES CNX: a = ~s, b = ~s, c = ~s, d = ~s, e = ~s, f = ~s, g = ~s, h = ~s, i = ~s, j = ~s~%"
(valeur a) (valeur b) (valeur c) (valeur d) (valeur e)
(valeur f) (valeur g) (valeur h) (valeur i) (valeur j)
)
)
; Ajout des connexions au gestionnaire
(ajouter-au-gestionnaire a gest)
(ajouter-au-gestionnaire b gest)
(ajouter-au-gestionnaire c gest)
(ajouter-au-gestionnaire d gest)
(ajouter-au-gestionnaire e gest)
(ajouter-au-gestionnaire f gest)
(ajouter-au-gestionnaire g gest)
(ajouter-au-gestionnaire h gest)
(ajouter-au-gestionnaire i gest)
(ajouter-au-gestionnaire j gest)
#|
| Début du test présent dans l'énoncé du TP.
|#
(mettre-valeur 2 'utilisateur a)
(affichage)
(sauvegarde-gestionnaire gest)
(mettre-valeur 3 'utilisateur b)
(if (y-a-t-il-incoherence gest) (restauration-gestionnaire gest))
(affichage)
(sauvegarde-gestionnaire gest)
(mettre-valeur 3 'utilisateur i)
(if (y-a-t-il-incoherence gest) (restauration-gestionnaire gest))
(affichage)
(sauvegarde-gestionnaire gest)
(mettre-valeur 1 'utilisateur j)
(if (y-a-t-il-incoherence gest) (restauration-gestionnaire gest))
(affichage)
(sauvegarde-gestionnaire gest)
(mettre-valeur 1 'utilisateur g)
(if (y-a-t-il-incoherence gest) (restauration-gestionnaire gest))
(affichage)
(sauvegarde-gestionnaire gest)
(mettre-valeur 1 'utilisateur f)
(if (y-a-t-il-incoherence gest) (restauration-gestionnaire gest))
(affichage)
(sauvegarde-gestionnaire gest)
(mettre-valeur (/ 3 5) 'utilisateur f)
(if (y-a-t-il-incoherence gest) (restauration-gestionnaire gest))
(affichage)