Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # -*- coding: utf-8 -*-
- ####################
- #
- # Travail 2
- # Réalisé par: Caroline Beauchamp
- # Remise: 13/11/2018
- #
- ####################
- import csv
- from math import radians, sin, cos, sqrt, asin
- #fonction de base pour calculer la distance en KM entre 2 point
- def haversine(lat1, lon1, lat2, lon2):
- R = 6372.8 # diamètre de la Terre en KM
- dLat = radians(float(lat2) - float(lat1))
- dLon = radians(float(lon2) - float(lon1))
- lat1 = radians(float(lat1))
- lat2 = radians(float(lat2))
- a = sin(dLat / 2) ** 2 + cos(float(lat1)) * cos(float(lat2)) * sin(dLon / 2) ** 2
- c = 2 * asin(sqrt(a))
- return R * c
- class Company: #classe permettant de gérer l'entité "Company"
- # constructeur de Company, permet la création des listes de chauffeurs(listDrivers) et la liste des voitures(listCars)
- def __init__(self, name):
- self.name = name #name est le nom que l'on veut donner à la compagnie
- self.listCars = []
- self.listDrivers = []
- #méthode pour ajout manuel d'une voiture à listCars
- def addCar(self, car): #où car est la voiture à ajouter
- self.listCars.append(car)
- #méthode pour un ajout en "batch" de voitures, via un fichier CSV
- def addCarByCSV(self, csvCars): #où csvCars est le chemin du fichier csv contenant les informations sur les voitures
- with open(csvCars, 'rb') as csvfile:
- csvreader = csv.reader(csvfile, delimiter=',')#importance de valider de délimitateur du fichier CSV
- for row in csvreader:
- self.listCars.append(row)
- # méthode pour ajout manuel d'un chauffeur à la liste listDrivers
- def addDriver(self, driver): #où driver est le conducteur à ajouter
- self.listDrivers.append(driver)
- # méthode pour un ajout en "batch" de conducteurs , via un fichier CSV
- def addDriverByCSV(self, csvDriver): #où csvCars est le path du fichier csv des voiture
- with open(csvDriver, 'rb') as csvfile:
- csvreader = csv.reader(csvfile, delimiter=',')#importance de valider de délimitateur du fichier CSV
- for row in csvreader:
- self.listDrivers.append(row)
- #méthode pour trouver une voiture en fonction de son identifiant(id)
- def getCarById(self, id): #où id est l'id de la voiture
- for c in self.listCars: #on parcours la liste de voiture
- if c.id == id : #pour trouver un identifiant correspondant et on le retourne
- return c
- # méthode pour trouver le conducteur d'une voiture en fonction de l'identifiant de la voiture(id)
- def getDriverByCarId(self, id): #où id est l'id de la voiture
- for d in self.listDrivers: #on parcours la liste des conducteurs
- if d.carId == id: #pour trouver les informations du conducteur associé à l'id de la voiture et on le retourne
- return d
- #méthode pour la création d'un CSV qui indique l'état actuelle des voitures de la compagnies
- #ce n'est fort probablement pas optimal, mais c'est fonctionnel
- def CSVstatus(self):
- with open(r'csvstatus.csv', 'wb') as file: #création du fichier CSV
- csvwriter = csv.writer(file, delimiter=',')
- status = [] #liste des éléments à inclure par ligne du CSV
- csvline= [] #fusion des éléments de status pour l'ajout d'une rangée simple
- for d in self.listDrivers:
- for c in self.listCars: #on parcours la liste des conducteurs et des voitures
- if d[3] == c[0]: #si le id de la voiture correspond à l'id de voiture du chauffeur
- status.append(c[0]) #ajout de l'id
- status.append(c[5]) #ajout de la longitude
- status.append(c[6]) #ajout de la latitude
- status.append(d[0]) #ajout du prénom du conducteur
- status.append(d[1]) #ajout du nom du chauffeur
- status.append(c[1]) #ajout de la marque de la voiture
- status.append(c[2]) #ajout du modèle de la voiture
- status.append(c[7]) #ajout du status d'occupation de la voiture
- csvline.append(status) #ajout de l'ensemble des informations en une seule liste
- csvwriter.writerow(csvline) #ajout de cette ligne dans le csv
- del status[:] #on supprime status et csvline afin que les informations ne se répète pas à chaque nouvelle ligne
- del csvline[:]
- #méthode permettant le traitement des appels des clients de la compagnie
- def CallClient(self,appel): #où appel est le numéro initial de l'appel. On le met à 1 par défaut ou si c'est le début d'une nouvelle journée
- print "*****APPEL CLIENT ENTRANT*****" #message pour indiquer le début du processus
- lat_client = raw_input("Latitude de l'emplacement du client (ex.45.3936): ") #on demande à l'employé d'entrer l'emplacement du client
- long_client = raw_input("Longitude de l'emplacement du client (ex.-71.9041): ")
- adapt = raw_input("Besoin adapté (oui/non)?: ") #on demande si le transport doit être adapté
- car_dispo = [] #liste des voitures actuellement dispoble
- distclient = {} #dictionnaire qui a pour clé l'identifiant de la voiture et comme valeur de distance entre la voiture et le client
- #pour déterminer les voitures disponibles
- for d in self.listCars: #en parcourant la liste des voitures
- if int(d[7]) == 0: # on recherche le status d'occupation, où 0 stipule que la voiture n'est pas occupée
- if adapt.lower() == 'oui' and int(d[8]) == 1: #si le client indique que la voiture doit être adaptée, où 1 est le code indiquant une voiture adaptable
- car_dispo.append(d)#on l'ajoute à la liste des voitures disponibles
- else:
- car_dispo.append(d) #si la voiture est libre et il n'y a pas de besoin d'adaptabilité, on fait simplement l'ajouter à la liste
- #pour établir la distance entre le client et une voiture
- for r in car_dispo:
- latCar = r[6] #emplacement de la voiture
- longCar = r[5]
- distclient[r[0]] = (haversine(lat_client, long_client, latCar, longCar)) #on inclue dans la formule de distance les paramètres entrés pour l'emplacement du client et celle de la voiture
- closestCar=sorted(distclient.iteritems(), key=lambda (k,v): (v,k)) #tri la distances des voitures de la plus près à la plus éloignée
- print " "
- print "Id des trois voitures les plus proches (dans l'ordre):" #indique à l'employé les id des trois voitures les plus près du client
- for i in closestCar[0:3]:
- print i[0]
- action=raw_input("Id de la voiture à envoyer:") #l'employé peut sélectionné la voiture à envoyer
- #pour générer le message de confirmation de l'envoie de la voiture
- for i in closestCar:
- for y in self.listCars:
- for z in self.listDrivers:
- if action == y[0] and y[0] == z[3] and i[0]==y[0]:
- y[7] = 1 #pour convertir le status d'occupation de libre (0) à occupé (1) afin de ne pas resélectionner la voiture
- temps= float(i[1])*(50.0/60) #pour calculer le temps d'arrivée si on considère la vitesse moyenne de 50km/h
- print "Appel #%s: voiture %s %s, conduite par %s %s (distance à parcourir: %.2f km, arrivée dans %.1f minutes." % (appel, str(y[1]), str(y[2]), str(z[0]), str(z[1]), float(i[1]), float(temps))
- nextCall=raw_input("Autre appel à traiter (oui/non):") #on demande à l'employé s'il veut poursuivre
- while nextCall.lower() == 'oui':
- print " "
- appel+=1 #incrémentation du numéro de l'appel si on poursuit le traitement
- self.CallClient(appel) #on appelle à nouveau la méthode pour recommencer le traitement
- else:
- print "Merci de travailler pour THE COMPANY!" #message de cloture du programme d'appel
- exit()
- #méthode pour obtenir le nombre de voiture par model
- def CarbyModel(self):
- listModel= [] #liste des modèles de voiture
- countdict={} #pour compter le nombre de voitures par modèle
- for i in self.listCars:
- if i[2] not in listModel:
- listModel.append(str(i[2])) #on ajoute le nom du modèle si celui-ci n'est pas déjà dans la liste de modèle
- for y in listModel:
- for z in self.listCars:
- if y not in countdict:
- countdict[y] = 0 #si le modèle n'est pas déjà présent, on l'ajoute en tant que clé avec la valeur de 0
- if y in z[2]:
- countdict[y] += 1 #si le modèle est présent à nouveau dans la liste de voiture, on ajoute 1 au compteur du modèle
- #message d'impression du résultat
- print "Le nombre de voitures selon les modèles:"
- for x in countdict:
- print "%s : %d" % (x, countdict[x])
- print " " #pour aérer les réponses
- #méthode pour obtenir le nombre de voiture datant de chaque année
- def CarbyYear(self):
- listyear= [] #liste des années
- countdict={} #pour compter le nombre d'année
- for i in self.listCars:
- if i[3] not in listyear:
- listyear.append(str(i[3])) #on ajoute l'année si celle-ci n'est pas dans la liste
- for y in listyear:
- for z in self.listCars:
- if y not in countdict:
- countdict[y] = 0 #si l'année de la voiture n'est pas déjà présente, on l'ajoute en tant que clé avec la valeur de 0
- if y in z[3]:
- countdict[y] += 1 #si l'année est présente à nouveau dans la liste , on ajoute 1 au compteur de l'année
- # message d'impression du résultat
- print "Le nombre de voitures selon les années:"
- for x in countdict:
- print "%s : %d" % (x, countdict[x])
- print " " # pour aérer les réponses
- #méthode pour obtenir le nombre de voitures libres ou occupées
- def StatusCar(self):
- libre=0
- occupe=0
- for i in self.listCars:
- if int(i[7]) == 0:
- libre += 1
- if int(i[7]) == 1:
- occupe+= 1
- #message d'impression du résultat
- print "Il y a actuellement %d voitures libres et %d voitures occupées." % (libre, occupe)
- print " " # pour aérer les réponses
- #méthode pour obtenir le nombre de voiture conduites par des femmes selon le modèle
- def CarFemme(self):
- listModel = []
- countdict = {}
- for i in self.listCars:
- if i[2] not in listModel:
- listModel.append(str(i[2])) #on ajoute le modèle s'il n'est pas déjà présent dans la liste
- for y in listModel:
- for z in self.listCars:
- for w in self.listDrivers:
- if y not in countdict:
- countdict[y] = 0 #si le modèle de la voiture n'est pas déjà présent, on l'ajoute en tant que clé avec la valeur de 0
- if y == z[2] and z[0] == w[3] and w[2] == 'F':
- countdict[y] += 1 #si le modèle est dans la liste, que l'id de la voiture correspond à celle du conducteur et que le conducteur est une femme, on incrémente le compteur
- # message d'impression du résultat
- print "Le nombre de voiture conduites par des femmes selon le modèle:"
- for x in countdict:
- print "%s : %d" % (x, countdict[x])
- print " " # pour aérer les réponses
- # méthode pour obtenir le nombre de voiture conduites par des hommes selon le modèle
- def CarHomme(self):
- listModel = []
- countdict = {}
- for i in self.listCars:
- if i[2] not in listModel:
- listModel.append(str(i[2]))#on ajoute le modèle s'il n'est pas déjà présent dans la liste
- for y in listModel:
- for z in self.listCars:
- for w in self.listDrivers:
- if y not in countdict:
- countdict[y] = 0 #si le modèle de la voiture n'est pas déjà présent, on l'ajoute en tant que clé avec la valeur de 0
- if y == z[2] and z[0] == w[3] and w[2] == 'M':
- countdict[y] += 1 #si le modèle est dans la liste, que l'id de la voiture correspond à celle du conducteur et que le conducteur est un homme, on incrémente le compteur
- # message d'impression du résultat
- print "Le nombre de voiture conduites par des hommes selon le modèle:"
- for x in countdict:
- print "%s : %d" % (x, countdict[x])
- print " " # pour aérer les réponses
- #méthode qui permet d'appeler d'un coup l'ensemble des méthodes statistiques, pour chaque méthode appelée, voir description ci-haut
- def StatsCars(self):
- print "**********STATISTIQUES:**********"
- self.CarbyModel()
- self.CarbyYear()
- self.StatusCar()
- self.CarFemme()
- self.CarHomme()
- class Car: #classe qui permet de gérer l'entité Car et qui va permettre de gérer l'information des voitures
- def __init__(self, id, brand, model): #contructeur de Car pour créer une voiture
- self.id = id #id de la voiture
- self.brand = brand #marque
- self.model = model #modèle de la voiture
- self.year = 1900 #année
- class Driver: #classe qui permet de gérer l'entité Driver et qui va permettre de gérer l'information des conducteurs
- def __init__(self, firstName, lastName, sex): #contructeur de Driver pour créer un conducteur
- self.firstName = firstName #prénom
- self.lastName = lastName #nom de famille
- self.sex = sex #sexe (F/H)
- #méthode qui permet l'assignation d'un id de voiture à un conducteur
- def setCarId(self, id):
- self.carId = id #où id est l'identifiant de la voiture
- #################### EXEMPLE D'EXÉCUTION #######################
- thecompany = Company("THE COMPANY") #le nom que l'on attribue à la compagnie, ici très originalement inspiré de la série télévisé Heroes
- thecompany.addCarByCSV('C:\\Users\\mydar\\Downloads\\cars.csv') # où le chemin peut être modifié en fonction de l'emplacement du csv des voitures
- thecompany.addDriverByCSV('C:\\Users\\mydar\\Downloads\\drivers.csv') #où le chemin peut être modifié en fonction de l'emplacement du csv des conducteurs
- thecompany.StatsCars() #pour afficher d'un coup l'ensemble des statistiques
- thecompany.CallClient(1) #où on appelle la méthode pour traiter les appels
- #RÉSULTATS DES APPELS DU TD
- '''
- *****APPEL CLIENT ENTRANT*****
- Latitude de l'emplacement du client (ex.45.3936): 45.542969
- Longitude de l'emplacement du client (ex.-71.9041): -73.610119
- Besoin adapté (oui/non)?: non
- Id des trois voitures les plus proches (dans l'ordre):
- 295
- 152
- 67
- Id de la voiture à envoyer:295
- Appel #1: voiture Toyota Camry hybrid, conduite par Laurence Poulin (distance à parcourir: 1.53 km, arrivée dans 1.3 minutes.
- Autre appel à traiter (oui/non):oui
- *****APPEL CLIENT ENTRANT*****
- Latitude de l'emplacement du client (ex.45.3936): 45.538280
- Longitude de l'emplacement du client (ex.-71.9041): -73.670715
- Besoin adapté (oui/non)?: non
- Id des trois voitures les plus proches (dans l'ordre):
- 253
- 219
- 88
- Id de la voiture à envoyer:253
- Appel #2: voiture Honda Accord, conduite par Arthur Nelson (distance à parcourir: 0.62 km, arrivée dans 0.5 minutes.
- Autre appel à traiter (oui/non):oui
- *****APPEL CLIENT ENTRANT*****
- Latitude de l'emplacement du client (ex.45.3936): 45.542367
- Longitude de l'emplacement du client (ex.-71.9041): -73.638443
- Besoin adapté (oui/non)?: oui
- Id des trois voitures les plus proches (dans l'ordre):
- 194
- 347
- 121
- Id de la voiture à envoyer:194
- Appel #3: voiture Honda Accord, conduite par Olivia Simard (distance à parcourir: 0.82 km, arrivée dans 0.7 minutes.
- Autre appel à traiter (oui/non):oui
- *****APPEL CLIENT ENTRANT*****
- Latitude de l'emplacement du client (ex.45.3936): 45.551744
- Longitude de l'emplacement du client (ex.-71.9041): -73.606514
- Besoin adapté (oui/non)?: oui
- Id des trois voitures les plus proches (dans l'ordre):
- 152
- 123
- 108
- Id de la voiture à envoyer:152
- Appel #4: voiture Hyundai Elantra, conduite par Édouard Collins (distance à parcourir: 0.85 km, arrivée dans 0.7 minutes.
- *****APPEL CLIENT ENTRANT*****
- Autre appel à traiter (oui/non):oui
- Latitude de l'emplacement du client (ex.45.3936): 45.570975
- Longitude de l'emplacement du client (ex.-71.9041): -73.636726
- Besoin adapté (oui/non)?: non
- Id des trois voitures les plus proches (dans l'ordre):
- 171
- 232
- 87
- Id de la voiture à envoyer:171
- Appel #5: voiture Kia Cerato, conduite par Naomie Pérez (distance à parcourir: 0.85 km, arrivée dans 0.7 minutes.
- Autre appel à traiter (oui/non):oui
- *****APPEL CLIENT ENTRANT*****
- Latitude de l'emplacement du client (ex.45.3936): 45.547176
- Longitude de l'emplacement du client (ex.-71.9041): -73.666595
- Besoin adapté (oui/non)?: non
- Id des trois voitures les plus proches (dans l'ordre):
- 88
- 121
- 64
- Id de la voiture à envoyer:88
- Appel #6: voiture Kia Rondo, conduite par Ariane Lee (distance à parcourir: 1.22 km, arrivée dans 1.0 minutes.
- Autre appel à traiter (oui/non):non
- Merci de travailler pour THE COMPANY!
- Process finished with exit code 0
- '''
Advertisement
Add Comment
Please, Sign In to add comment