Initial commit
This commit is contained in:
499
Project.py
Normal file
499
Project.py
Normal file
@@ -0,0 +1,499 @@
|
||||
# Install necessary libraries if they are not already installed
|
||||
# Asenna tarvittavat kirjastot, jos niitä ei ole jo asennettu
|
||||
try:
|
||||
import matplotlib.pyplot as plt
|
||||
except ImportError:
|
||||
import os
|
||||
os.system('pip install matplotlib')
|
||||
import matplotlib.pyplot as plt
|
||||
try:
|
||||
from prettytable import PrettyTable
|
||||
except ImportError:
|
||||
import os
|
||||
os.system('pip install prettytable')
|
||||
from prettytable import PrettyTable
|
||||
from datetime import datetime
|
||||
import random
|
||||
import string
|
||||
now = datetime.now()
|
||||
|
||||
|
||||
# Go back to main menu
|
||||
# Palaa päävalikkoon
|
||||
|
||||
|
||||
def back():
|
||||
input('\nPress ENTER to return to main menu...')
|
||||
menu()
|
||||
|
||||
# Modify vehicle.txt file
|
||||
# Muokkaa vehicle.txt-tiedostoa
|
||||
|
||||
|
||||
def modify(tf, mod):
|
||||
if tf:
|
||||
with open(r'Vehicle.txt', 'w+') as rew:
|
||||
for w in mod:
|
||||
rew.write(w)
|
||||
|
||||
# Display cars available for rent
|
||||
# Näytä autot vuokrattavissa
|
||||
|
||||
|
||||
def displayCars(u):
|
||||
table = PrettyTable(['Registration number', 'Model name',
|
||||
'Type (Ordinary/Premium)', 'Free mileage (km)', 'Daily rent (€)'])
|
||||
with open(r'Vehicle.txt', 'r') as f1:
|
||||
cars1 = f1.readlines()
|
||||
for i in cars1:
|
||||
i = i.split(',')
|
||||
i = [x.replace('\n', "") for x in i]
|
||||
if u == 'A':
|
||||
if i[5] == 'A':
|
||||
table.add_row([i[0], i[1], i[2], i[3], i[4]])
|
||||
elif u == 'R':
|
||||
if i[5] == 'R':
|
||||
table.add_row([i[0], i[1], i[2], i[3], i[4]])
|
||||
else:
|
||||
print('\nInvalid choice.')
|
||||
return
|
||||
print(table)
|
||||
|
||||
# Add and delete vehicles
|
||||
# Lisää ja poista ajoneuvoja
|
||||
|
||||
|
||||
def Add_Vehicle():
|
||||
lcpl = input('\nEnter Vehicle ID: ')
|
||||
ehto = True
|
||||
with open(r'Vehicle.txt', 'r') as fv:
|
||||
vec = fv.readlines()
|
||||
for vc in vec:
|
||||
vc = vc.split(',')
|
||||
if lcpl == vc[0]:
|
||||
print('\nVehicle already exists in database.')
|
||||
ehto = False
|
||||
if ehto:
|
||||
name = input('Enter Vehicle Name: ')
|
||||
while True:
|
||||
typ = input('Enter vehicle type (O/P): ')
|
||||
if typ == 'P':
|
||||
try:
|
||||
mileage = float(
|
||||
input("Enter Type-P Vehicle's mileage allowance: "))
|
||||
except Exception:
|
||||
print('\nInvalid choice.\n')
|
||||
continue
|
||||
else:
|
||||
mileage = str(mileage)
|
||||
break
|
||||
elif typ == 'O':
|
||||
mileage = '0'
|
||||
break
|
||||
else:
|
||||
print('\nInvalid choice.\n')
|
||||
continue
|
||||
while True:
|
||||
try:
|
||||
dailyrent = float(input("Enter daily rent rate: "))
|
||||
except Exception:
|
||||
print('\nInvalid choice.\n')
|
||||
continue
|
||||
else:
|
||||
dailyrent = str(dailyrent)
|
||||
break
|
||||
stat = input(
|
||||
"Enter status (A/R, if choose R please add rent details to rentVehicle.txt): ")
|
||||
with open(r'Vehicle.txt', 'a') as fa:
|
||||
fa.write('\n'+lcpl + ','+name+','+typ + ',' +
|
||||
mileage + ','+dailyrent+','+stat)
|
||||
while True:
|
||||
try:
|
||||
con = input('\nDo you want to add another vehicle? (Y/N): ')
|
||||
except Exception:
|
||||
print("\nInvalid choice.")
|
||||
continue
|
||||
else:
|
||||
if con == 'Y':
|
||||
Add_Vehicle()
|
||||
elif con == 'N':
|
||||
menu()
|
||||
return
|
||||
else:
|
||||
print("\nInvalid choice.")
|
||||
continue
|
||||
|
||||
|
||||
def Delete_Vehicle():
|
||||
lcpl2 = input('\nEnter Vehicle ID: ')
|
||||
with open(r'Vehicle.txt', 'r') as fd:
|
||||
ved = fd.readlines()
|
||||
for vd in ved:
|
||||
vd = vd.split(',')
|
||||
if lcpl2 == vd[0]:
|
||||
vd = ','.join(vd)
|
||||
with open(r'deletedVehicles.txt', 'a') as fr:
|
||||
fr.write(vd+'\n')
|
||||
pos = ved.index(vd)
|
||||
del ved[pos]
|
||||
modify(True, ved)
|
||||
break
|
||||
else:
|
||||
print("\nVehicle does not exist.")
|
||||
while True:
|
||||
try:
|
||||
con = input('\nDo you want to delete another vehicle? (Y/N): ')
|
||||
except Exception:
|
||||
print("\nInvalid choice.")
|
||||
continue
|
||||
else:
|
||||
if con == 'Y':
|
||||
Delete_Vehicle()
|
||||
elif con == 'N':
|
||||
menu()
|
||||
return
|
||||
else:
|
||||
print("\nInvalid choice.")
|
||||
continue
|
||||
|
||||
# Add rent details to files
|
||||
# Lisää tiedostoihin vuokratiedot
|
||||
|
||||
|
||||
def rentDetails(path, app):
|
||||
plate = app.split(',')
|
||||
if path == 1:
|
||||
with open(r'rentVehicle.txt', 'a') as q:
|
||||
q.write(str(app))
|
||||
print('\nCar '+plate[1]+' is rented successfully.')
|
||||
elif path == 2:
|
||||
with open(r'Transactions.txt', 'a') as p:
|
||||
p.write(str(app))
|
||||
print('\nCar '+plate[1]+' is returned successfully.')
|
||||
|
||||
# Generate Receipt ID and check if it is already taken
|
||||
# Luo kuittitunnus ja tarkista, onko se jo varattu
|
||||
|
||||
|
||||
def receiptID():
|
||||
while True:
|
||||
code = ''.join([random.choice(string.ascii_letters + string.digits)
|
||||
for n in range(10)])
|
||||
with open('rentVehicle.txt', 'r') as cd:
|
||||
cdc = cd.readlines()
|
||||
for cdi in cdc:
|
||||
cdi = cdi.split(',')
|
||||
if cdi[0] == code:
|
||||
continue
|
||||
else:
|
||||
return code
|
||||
|
||||
# Check Odometer reading
|
||||
# Tarkista matkamittarin lukema
|
||||
|
||||
|
||||
def odometer(way, qq):
|
||||
if way == 1:
|
||||
while True:
|
||||
try:
|
||||
vv = float(
|
||||
input('Enter odometer reading at time of renting: '))
|
||||
except Exception:
|
||||
print('\nOdometer reading must be a float or an integer.\n')
|
||||
continue
|
||||
else:
|
||||
return vv
|
||||
elif way == 2:
|
||||
while True:
|
||||
try:
|
||||
ww = float(
|
||||
input('Enter odometer reading at time of returning: '))
|
||||
except Exception:
|
||||
print('\nOdometer reading must be a float or an integer.\n')
|
||||
continue
|
||||
else:
|
||||
if (ww) < (qq):
|
||||
print(
|
||||
'\nEnd odometer value must be larger than initial odometer value.\n')
|
||||
continue
|
||||
else:
|
||||
return ww
|
||||
|
||||
# Add accessories
|
||||
# Lisää lisävarusteita
|
||||
|
||||
|
||||
def accessories():
|
||||
while True:
|
||||
paina = input('\nDo you want to add them? (Y/N): ')
|
||||
if paina == 'Y':
|
||||
return 20
|
||||
elif paina == 'N':
|
||||
return 0
|
||||
else:
|
||||
print("\nInvalid choice.")
|
||||
continue
|
||||
|
||||
# Rent a car
|
||||
# Vuokrata auton
|
||||
|
||||
|
||||
def rentVehicle(id1):
|
||||
with open(r'Vehicle.txt', 'r') as f2:
|
||||
cars2 = f2.readlines()
|
||||
for j in cars2:
|
||||
j = [i.rstrip() for i in j.split(',')]
|
||||
if id1 == j[0]:
|
||||
if j[5] == 'A':
|
||||
rentID = input('Enter Renter ID: ')
|
||||
odo = str(odometer(1, 0))
|
||||
acc = 0
|
||||
recid = receiptID()
|
||||
if j[2] == 'P':
|
||||
print(
|
||||
'\nThe following accessories could be added to your vehicle for only €20:')
|
||||
print('1. HD Dash Cam')
|
||||
print('2. GPS Navigation')
|
||||
print('3. Engine Heater')
|
||||
acc = accessories()
|
||||
print('\nCar '+j[0]+' is rented to '+rentID)
|
||||
table1 = PrettyTable(['Receipt ID', recid])
|
||||
table1.add_row(['Renter ID', rentID])
|
||||
table1.add_row(['Vehicle ID', id1])
|
||||
table1.add_row(['Description', j[1]])
|
||||
table1.add_row(['Status', 'A -> R'])
|
||||
table1.add_row(['Accessories', '€'+str(acc)])
|
||||
table1.add_row(['Daily rate', '€'+j[4]])
|
||||
table1.add_row(['Date/time of rent',
|
||||
now.strftime("%d/%m/%Y %H:%M")])
|
||||
table1.add_row(['Rent starting odometer', odo])
|
||||
print(table1)
|
||||
appnew = (recid+','+id1+','+rentID+',' +
|
||||
now.strftime("%d/%m/%Y %H:%M") +
|
||||
','+odo+','+str(acc)+'\n')
|
||||
rentDetails(1, appnew)
|
||||
j[5] = 'A\n'
|
||||
dx = cars2.index(','.join(j))
|
||||
j[5] = 'R\n'
|
||||
j = ','.join(j)
|
||||
cars2[dx] = j
|
||||
return True, cars2
|
||||
elif j[5] == 'R\n':
|
||||
print('\nVehicle is on rent.')
|
||||
return False, []
|
||||
else:
|
||||
print('\nVehicle does not exist.')
|
||||
return False, []
|
||||
|
||||
# Return a car
|
||||
# Palauta auton
|
||||
|
||||
|
||||
def rentComplete(id2):
|
||||
with open(r'rentVehicle.txt', 'r') as f3:
|
||||
cars3 = f3.readlines()
|
||||
for r in cars3:
|
||||
r = r.split(',')
|
||||
if id2 == r[0]:
|
||||
with open(r'Vehicle.txt', 'r') as f4:
|
||||
rented = f4.readlines()
|
||||
for v in rented:
|
||||
v = v.split(',')
|
||||
if v[5] == 'R\n':
|
||||
odo2 = str(odometer(2, float(r[4])))
|
||||
startdate = r[3]
|
||||
dayrent = datetime.strptime(
|
||||
startdate, '%d/%m/%Y %H:%M')
|
||||
daydelta = (now - dayrent).days
|
||||
kms = float(odo2)-float(r[4])
|
||||
typefee = 0
|
||||
if v[2] == 'O':
|
||||
typefee = 0.020
|
||||
elif v[2] == 'P':
|
||||
typefee = 0.025
|
||||
charge = str(
|
||||
((daydelta+1)*float(v[4]))+((daydelta+1)*float(r[5]))+(kms*typefee))
|
||||
print('\nCar '+r[1]+' is returned from '+r[2])
|
||||
table2 = PrettyTable(['Receipt ID', r[0]])
|
||||
table2.add_row(['Renter ID', r[2]])
|
||||
table2.add_row(['Vehicle ID', r[1]])
|
||||
table2.add_row(['Description', v[1]])
|
||||
table2.add_row(['Status', 'R -> A'])
|
||||
table2.add_row(
|
||||
['Accessories', '€'+r[5].strip('\n')])
|
||||
table2.add_row(['Daily rate', '€'+v[4]])
|
||||
table2.add_row(['Date/time of rent', r[3]])
|
||||
table2.add_row(['Date/time of return',
|
||||
now.strftime("%d/%m/%Y %H:%M")])
|
||||
table2.add_row(['Number of days', daydelta+1])
|
||||
table2.add_row(['Rent starting odometer', r[4]])
|
||||
table2.add_row(['Rent end odometer', odo2])
|
||||
table2.add_row(['Distance traveled', kms])
|
||||
table2.add_row(['Rental charges', '€'+charge])
|
||||
print(table2)
|
||||
appdone = (id2+','+r[1]+',' + r[2]+',' + now.strftime(
|
||||
"%d/%m/%Y %H:%M") + ','+r[4]+','+odo2+','+charge+'\n')
|
||||
rentDetails(2, appdone)
|
||||
dy = rented.index(','.join(v))
|
||||
v[5] = 'A\n'
|
||||
v = ','.join(v)
|
||||
rented[dy] = v
|
||||
return True, rented
|
||||
else:
|
||||
print(
|
||||
"Receipt ID found but vehicle is not on rent.")
|
||||
return False, []
|
||||
else:
|
||||
print('\nReceipt ID does not exist.')
|
||||
return False, []
|
||||
|
||||
# Data visualization
|
||||
# Tietojen visualisointi
|
||||
|
||||
|
||||
def Graph1():
|
||||
ordinary = 0
|
||||
premium = 0
|
||||
with open(r'Vehicle.txt', 'r') as g:
|
||||
gc = g.readlines()
|
||||
for gline in gc:
|
||||
gline = gline.split(',')
|
||||
gline = [gl.replace('\n', '') for gl in gline]
|
||||
if gline[2] == 'O':
|
||||
ordinary += 1
|
||||
elif gline[2] == 'P':
|
||||
premium += 1
|
||||
labels = ['Ordinary', 'Premium']
|
||||
data = [ordinary, premium]
|
||||
plt.xticks(range(len(data)), labels)
|
||||
plt.xlabel('Types')
|
||||
plt.ylabel('Amounts')
|
||||
plt.title('Number of Ordinary and Premium Vehicles')
|
||||
plt.bar(range(len(data)), data, color='pink')
|
||||
plt.show()
|
||||
|
||||
|
||||
def Graph2():
|
||||
dct = {}
|
||||
sanakirja = {}
|
||||
total = 0
|
||||
with open(r'Transactions.txt', 'r') as g2:
|
||||
gd = g2.readlines()
|
||||
for item in gd:
|
||||
if len(dct.keys()) == 12:
|
||||
break
|
||||
item = item.split(',')
|
||||
item = [gh.replace('\n', '') for gh in item]
|
||||
item[6] = float(item[6])
|
||||
total += item[6]
|
||||
paivamaara = datetime.strptime(
|
||||
item[3], '%d/%m/%Y %H:%M')
|
||||
paiva = paivamaara.strftime('%m/%Y')
|
||||
try:
|
||||
dct[paiva] = item[6]+float(dct[paiva])
|
||||
except KeyError:
|
||||
dct[paiva] = 0
|
||||
dct[paiva] = item[6]+float(dct[paiva])
|
||||
d_items = dct.items()
|
||||
sortdct = sorted(d_items)
|
||||
for sana in sortdct:
|
||||
sanakirja[sana[0]] = sana[1]
|
||||
kuukausi = sanakirja.keys()
|
||||
tulo = sanakirja.values()
|
||||
plt.plot(kuukausi, tulo, color='maroon', marker='*')
|
||||
plt.title('Income earned for last '+str(len(dct.keys()))+' month(s)')
|
||||
plt.xlabel('Month')
|
||||
plt.ylabel('Income (€/month)')
|
||||
plt.grid(True)
|
||||
plt.show()
|
||||
|
||||
|
||||
# Remove extra lines
|
||||
# Poista ylimääräiset rivit
|
||||
|
||||
def extraLinesTerminator():
|
||||
with open('Vehicle.txt', 'r') as z:
|
||||
content = z.readlines()
|
||||
for i in content:
|
||||
if i == '\n' or not i:
|
||||
content.remove(i)
|
||||
modify(True, content)
|
||||
|
||||
# Main menu
|
||||
# Päävalikko
|
||||
|
||||
|
||||
def menu():
|
||||
extraLinesTerminator()
|
||||
print('\n Vehicle Menu')
|
||||
print('Display Cars 1')
|
||||
print('Add/delete Vehicle 2')
|
||||
print('Rent Vehicle 3')
|
||||
print('Complete Rent 4')
|
||||
print('Reporting Vehicle Information 5')
|
||||
print('Exit 6')
|
||||
try:
|
||||
choice = int(input('\nChoose your options: '))
|
||||
except Exception:
|
||||
print("\nInvalid choice.")
|
||||
back()
|
||||
else:
|
||||
if choice == 1:
|
||||
slt = input(
|
||||
'\nA for available vehicles or R for vehicles on rent: ')
|
||||
displayCars(slt)
|
||||
back()
|
||||
elif choice == 2:
|
||||
try:
|
||||
slt2 = int(
|
||||
input('\n1 to add vehicles and 2 to delete vehicles: '))
|
||||
except Exception:
|
||||
print("\nInvalid choice.")
|
||||
back()
|
||||
else:
|
||||
if slt2 == 1:
|
||||
Add_Vehicle()
|
||||
elif slt2 == 2:
|
||||
Delete_Vehicle()
|
||||
else:
|
||||
print("\nInvalid choice.")
|
||||
back()
|
||||
elif choice == 3:
|
||||
idc2 = input('\nEnter Vehicle ID: ')
|
||||
o2 = rentVehicle(idc2)
|
||||
modify(o2[0], o2[1])
|
||||
back()
|
||||
elif choice == 4:
|
||||
idc3 = input('\nEnter Receipt ID: ')
|
||||
o3 = rentComplete(idc3)
|
||||
modify(o3[0], o3[1])
|
||||
back()
|
||||
elif choice == 5:
|
||||
print(
|
||||
'\nDisplay the number of vehicles of each type: Ordinary and Premium 1')
|
||||
print(
|
||||
'Display the income earned for last months (maximum 12) 2')
|
||||
try:
|
||||
opp = int(input('\nCHoose your options: '))
|
||||
except Exception:
|
||||
print("\nInvalid choice.")
|
||||
back()
|
||||
else:
|
||||
if opp == 1:
|
||||
Graph1()
|
||||
back()
|
||||
elif opp == 2:
|
||||
Graph2()
|
||||
back()
|
||||
else:
|
||||
print("\nInvalid choice.")
|
||||
back()
|
||||
elif choice == 6:
|
||||
print('\nThanks for using Car Rental System. Bye!')
|
||||
return
|
||||
else:
|
||||
print('\nInvalid choice.')
|
||||
back()
|
||||
|
||||
|
||||
menu()
|
||||
Reference in New Issue
Block a user