#!/usr/bin/python
# -*- coding: utf-8 -*-

###################################################
# La classe Porte
###################################################

class Porte:
	###################################################
	# Documentation
	###################################################
	""" Classe abstraite représentant une porte """

	###################################################
	# Constructeur / Destructeur
	###################################################

	# Je veux choisir si ma porte est ouverte ou fermée
	# lors de sa construction
	def __init__(self, ouvert=False):
		self.__ouvert = ouvert

	def __del__(self):
		return

	###################################################
	# Accesseurs
	###################################################

	# Les utilisateurs peuvent savoir si la poste est 
	# ouverte, il faut donc que l'accesseur soit 
	# publique
	def getOuvert(self):
		return self.__ouvert

	###################################################
	# Mutateurs
	###################################################

	# Les utilisateurs ne peuvent pas modifier l'état 
	# de la porte directement, le mutateur ne doit pas
	# être publique. Cependant les classes héritant de 
	# Porte peuvent modifier l'état. Le mutateur ne 
	# peut donc pas être privé. Il est donc protégé.
	def _setOuvert(self, ouvert):
		self.__ouvert = ouvert

	###################################################
	# Méthodes publiques
	###################################################

	# Permet d'ouvrir une porte (abstrait)
	def ouvrir(self):
		raise NotImplementedError()

	# Permet de fermer une porte (abstrait)
	def fermer(self):
		raise NotImplementedError()


###################################################
# Fin de la classe Porte
###################################################


















###################################################
# La classe PorteAGonds, héritant de Porte
###################################################

class PorteAGonds(Porte):
	###################################################
	# Documentation
	###################################################
	""" Classe représentant une porte ayant des gonds """

	# La ligne suivante permet d'appeler le destructeur
	# de la classe mère
	parents = [Porte]

	###################################################
	# Constructeur / Destructeur
	###################################################
	# On peut choisir si la porte est ouverte ou fermée
	def __init__(self, ouvert=False):
		Porte.__init__(self, ouvert)

	def __del__(self):
		Porte.__del__(self)

	###################################################
	# Accesseurs
	###################################################

	###################################################
	# Mutateurs
	###################################################

	###################################################
	# Méthodes publiques
	###################################################

	# Permet d'ouvrir une porte (abstrait)
	def ouvrir(self):
		print "Ouverture de la porte"
		self._setOuvert(True)

	# Permet de fermer une porte (abstrait)
	def fermer(self):
		print "Fermeture de la porte"
		self._setOuvert(False)

###################################################
# Fin de la classe PorteAGonds
###################################################























###################################################
# La classe PorteCoulissante, héritant de Porte
###################################################
import time

class PorteCoulissante(Porte):
	###################################################
	# Documentation
	###################################################
	""" Classe représentant une porte coulissante """

	###################################################
	# Constructeur / Destructeur
	###################################################
	# Par défaut la porte et fermée et elle ne s'ouvre 
	# que pendant une certaine durée (en s).
	def __init__(self, delai_s=3.0):	
		# J'appelle le constructeur avec False en 
		# paramètre car ma porte est fermée par
		# défaut.
		Porte.__init__(self, False)
		# J'initialise la durée d'ouverture
		self.__delai = delai_s
		# J'initialise l'heure de la dernière ouverture
		self.__heureOuverture = 0.0

	def __del__(self):
		Porte.__del__(self)

	###################################################
	# Accesseurs
	###################################################
	# Les utilisateurs de la classe peuvent voir la
	# durée d'ouverture de la porte => publique
	def getDelai(self):
		return self.__delai

	# Je ne veux pas que les utilisateurs aient accès 
	# à la dernière heure d'ouverture comme ça ils ne 
	# savent pas quand elle va se fermer
	def __getHeureOuverture(self):
		return self.__heureOuverture

	# Comme la porte se referme automatiquement, il 
	# faut modifier l'accesseur getOuvert
	def getOuvert(self):
		# Est-ce que la porte est ouverte depuis trop longtemps
		if (self.__getHeureOuverture() + self.getDelai()) <= time.time() and Porte.getOuvert(self) == True:
			# Si oui, on la ferme
			self._setOuvert(False)
		# On renvoi la valeur de Porte.__ouvert
		return Porte.getOuvert(self)

	###################################################
	# Mutateurs
	###################################################
	# Le délai ne peut pas être modifié de l'extérieur
	def __setDelai(self, value):
		self.__delai = value

	def __setHeureOuverture(self, value):
		self.__heureOuverture = value

	###################################################
	# Méthodes publiques
	###################################################

	# Permet d'ouvrir une porte
	def ouvrir(self):
		print "Ouverture de la porte pendant", self.getDelai(), "secondes"
		self._setOuvert(True)
		self.__setHeureOuverture(time.time())

	# Permet de fermer une porte
	def fermer(self):
		print "La porte se ferme toute seule"

###################################################
# Fin de la classe PorteCoulissante
###################################################





















###################################################
# La classe Pièce
###################################################

class Piece:
	###################################################
	# Documentation
	###################################################
	""" Classe représentant une pièce """

	###################################################
	# Constructeur / Destructeur
	###################################################
	# On doit donner un nom à la pièce, il n'y a pas de
	# nom par défaut. Chaque pièce possède sa liste de 
	# portes qui permet d'arriver dans d'autres pièces
	# On stoque les liaisons entre les pièces sous 
	# forme de tuples (porte, piece)
	def __init__(self, nom):
		self.__nom = nom
		self.__listePorte = []

	def __del__(self):
		del self.__listePorte

	###################################################
	# Accesseurs
	###################################################
	# Pour récupérer le nom de la pièce
	def getNom(self):
		return self.__nom

	# Un utilisateur peut connaître le nombre des portes
	def getNbPortes(self):
		return len(self.__listePorte)

	# Un utilisateur peut récupérer un tuple (porte, piece)
	def getPortePiece(self, index):
		if index < self.getNbPortes():
			return self.__listePorte[index]
		else:
			return (None, None)

	###################################################
	# Mutateurs
	###################################################
	# On ne peut pas modifier le nom
	def __setNom(self, value):
		self.__nom = value

	# Un utilisateur peut définir quelle porte permet 
	# d'aller dans quelle pièce
	def addPortePiece(self, porte, piece):
		self.__listePorte.append((porte, piece))

	###################################################
	# Méthodes publiques
	###################################################

###################################################
# Fin de la classe Piece
###################################################















if __name__ == "__main__":
	pieces = [Piece("le hall"), Piece("l'ascenseur"), Piece("le couloir de l'etage 1"), Piece("la chambre")]
	portes = [PorteCoulissante(5.0), PorteAGonds(False)]

	pieces[0].addPortePiece(portes[0], pieces[1]) # hall -> ascenseur (porte 0)
	pieces[1].addPortePiece(portes[0], pieces[0]) # ascenceur -> hall (porte 0)
	pieces[1].addPortePiece(portes[0], pieces[2]) # ascenceur -> etage 1 (porte 0)
	pieces[2].addPortePiece(portes[0], pieces[1]) # etage 1 -> ascenseur (porte 0)
	pieces[2].addPortePiece(portes[1], pieces[3]) # etage 1 -> chambre (porte 1)
	pieces[3].addPortePiece(portes[1], pieces[2]) # chambre -> etage1 (porte 1)

	pieceCourante = pieces[0]

	choix = -1
	while choix != 0:
		print "-----------------------------------------------------"
		print "Vous êtes dans", pieceCourante.getNom(), "que voulez vous faire ?"
		print "1 - Ouvrir/Fermer une porte"
		print "2 - Aller dans une pièce"
		print ""
		choix = input("> ")

		if choix == 1:
			if pieceCourante.getNbPortes() == 0:
				print "Il n'y a pas de portes à ouvrir"
			else:
				choixPorte = -1
				while choixPorte >= pieceCourante.getNbPortes() or choixPorte < 0:
					for i in range(pieceCourante.getNbPortes()):
						(porte, piece) = pieceCourante.getPortePiece(i)
						print i,
						if porte.getOuvert():
							print "- Fermer", 
						else:
							print "- Ouvrir",
						print "a porte menant vers", piece.getNom()
					print "Entrez le numéro de la porte"
					choixPorte = input("> ")
				(porte, piece) = pieceCourante.getPortePiece(choixPorte)
				if porte.getOuvert():
					porte.fermer()
				else:
					porte.ouvrir()
		elif choix == 2:
			choixPorte = -1
			nbPortesOuvertes = 0
			while choixPorte >= pieceCourante.getNbPortes() or choixPorte < 0:
				for i in range(pieceCourante.getNbPortes()):
					(porte, piece) = pieceCourante.getPortePiece(i)
					if porte.getOuvert():
						nbPortesOuvertes += 1
						print i, "- Aller dans", piece.getNom()
					else:
						print i, "- La porte", i, "menant vers", piece.getNom(), "est fermée"
				if nbPortesOuvertes == 0:
					break
				print "Entrez le numéro de la porte"
				choixPorte = input("> ")
			if nbPortesOuvertes == 0:
				print "Toutes les portes sont fermées"
			else:
				(porte, piece) = pieceCourante.getPortePiece(choixPorte)
				if porte.getOuvert():
					pieceCourante = piece
				else:
					print "La porte choisie est fermée"
		else:
			break


syntax highlighted by Code2HTML, v. 0.9.1