|
|
|
import matplotlib.pyplot as plt
|
|
|
|
import numpy as np
|
|
|
|
import json
|
|
|
|
import sys
|
|
|
|
import argparse
|
|
|
|
__author__ = 'm3x1m0m'
|
|
|
|
|
|
|
|
class c_settings_extractor:
|
|
|
|
def __init__(self, fname):
|
|
|
|
with open(fname, "r") as rf:
|
|
|
|
settings = json.load(rf)
|
|
|
|
kilometer_price_ccar = settings["ccar"]["litres_per_kilometer"] * settings["petrol_litre_price"]
|
|
|
|
self.labels = [settings["ecar"]["label"], settings["ccar"]["label"]]
|
|
|
|
self.purchase = np.array([settings["ecar"]["price"], settings["ccar"]["price"]])
|
|
|
|
self.taxes = np.array([settings["ecar"]["taxes"], settings["ccar"]["taxes"]])
|
|
|
|
self.insurance = np.array([settings["ecar"]["insurance"], settings["ccar"]["insurance"]])
|
|
|
|
kilometer_price_ecar = ( settings["ecar"]["charging_behaviour"]["percent_home_charges"] * settings["kwh_price_home"]
|
|
|
|
+ settings["ecar"]["charging_behaviour"]["percent_commercial_charges"] * settings["kwh_price_commercial"]) / 100.0
|
|
|
|
self.driving = np.array([kilometer_price_ecar * settings["kilometers_per_year"], kilometer_price_ccar * settings["kilometers_per_year"]])
|
|
|
|
self.maintenance = np.array([settings["ecar"]["maintenance"], settings["ecar"]["maintenance"]])
|
|
|
|
def get_labels(self):
|
|
|
|
return self.labels
|
|
|
|
def get_purchase(self):
|
|
|
|
return self.purchase
|
|
|
|
def get_taxes(self):
|
|
|
|
return self.taxes
|
|
|
|
def get_insurance(self):
|
|
|
|
return self.insurance
|
|
|
|
def get_driving(self):
|
|
|
|
return self.driving
|
|
|
|
def get_maintenance(self):
|
|
|
|
return self.maintenance
|
|
|
|
|
|
|
|
class c_ecar_comparator:
|
|
|
|
def __init__(self, fname):
|
|
|
|
self.settings_extractor = c_settings_extractor(fname)
|
|
|
|
def calculate_costs_a_year(self):
|
|
|
|
taxes = self.settings_extractor.get_taxes()
|
|
|
|
insurance = self.settings_extractor.get_insurance()
|
|
|
|
driving = self.settings_extractor.get_driving()
|
|
|
|
maintenance = self.settings_extractor.get_maintenance()
|
|
|
|
return taxes + insurance + driving + maintenance
|
|
|
|
def calculate_costs(self, years, months):
|
|
|
|
months_a_year = 12.0
|
|
|
|
costs_a_year = self.calculate_costs_a_year()
|
|
|
|
return costs_a_year * (years + months/months_a_year)
|
|
|
|
def calculate_break_even(self):
|
|
|
|
total_costs = self.settings_extractor.get_purchase()
|
|
|
|
months_a_year = 12.0
|
|
|
|
increment = self.calculate_costs_a_year() / months_a_year
|
|
|
|
months = 0
|
|
|
|
while total_costs[0] > total_costs[1]:
|
|
|
|
total_costs += increment
|
|
|
|
months += 1
|
|
|
|
return [months/months_a_year, months%months_a_year] # years, months
|
|
|
|
|
|
|
|
def main():
|
|
|
|
parser = argparse.ArgumentParser(description='This script allows to calculate if an electric car makes sense financially for you')
|
|
|
|
parser.add_argument('-a','--settings', help='Settings file', required=True, metavar=('FILENAME'))
|
|
|
|
parser.add_argument('-b','--break_even', help='Calculate the break even point. (When does the EV become cheaper)', action='store_true')
|
|
|
|
parser.add_argument('-c','--savings_per_year', help='Calculate savings per year', action='store_true')
|
|
|
|
parser.add_argument('-d','--savings_per_month', help='Calculate savings per month', action='store_true')
|
|
|
|
parser.add_argument('-e','--plot', help='Visualize costs over one or multiple years', type=int, metavar=('YEARS'))
|
|
|
|
args = parser.parse_args()
|
|
|
|
if not args.break_even and not args.savings_per_year and not args.savings_per_month and not args.plot:
|
|
|
|
sys.exit("Please choose one or multiple options")
|
|
|
|
comparator = c_ecar_comparator(args.settings)
|
|
|
|
extractor = c_settings_extractor(args.settings)
|
|
|
|
if args.plot:
|
|
|
|
width = 0.3
|
|
|
|
labels = extractor.get_labels()
|
|
|
|
purchase = extractor.get_purchase()
|
|
|
|
taxes = extractor.get_taxes()
|
|
|
|
insurance = extractor.get_insurance()
|
|
|
|
driving = extractor.get_driving()
|
|
|
|
maintenance = extractor.get_maintenance()
|
|
|
|
fig, ax = plt.subplots()
|
|
|
|
ax.bar(labels, purchase, width, label = "Price", color = "gray")
|
|
|
|
current_y = extractor.get_purchase()
|
|
|
|
y = 0
|
|
|
|
|
|
|
|
for i in range(args.plot):
|
|
|
|
ax.bar(labels, taxes, width, bottom = current_y, label = "Taxes".format(y), color = "darkgreen")
|
|
|
|
current_y = current_y + taxes
|
|
|
|
ax.bar(labels, insurance, width, bottom = current_y, label = "Insurance".format(y), color = "royalblue")
|
|
|
|
current_y = current_y + insurance
|
|
|
|
ax.bar(labels, driving, width, bottom = current_y, label = "Driving".format(y), color = "midnightblue")
|
|
|
|
current_y = current_y + driving
|
|
|
|
ax.bar(labels, maintenance, width, bottom = current_y, label = "Maintenance".format(y), color = "lavender")
|
|
|
|
current_y = current_y + maintenance
|
|
|
|
y += 1
|
|
|
|
ecar_top = current_y[0]
|
|
|
|
#ax.plot(np.linspace(-0.2, 1.2, 10), [ecar_top]*10, "--", color = "firebrick", label = "Break even")
|
|
|
|
#ax.text(0.3, ecar_top * 0.95, "Break even: {} years, {} kilometers".format(y, y*settings["kilometers_per_year"]))
|
|
|
|
ax.set_ylabel("CHF")
|
|
|
|
ax.set_title("Comparision of economics electric vs. combustion car")
|
|
|
|
ax.legend(["Price", "Taxes", "Insurance", "Driving", "Maintenance"])
|
|
|
|
ax.grid(axis = "y")
|
|
|
|
#print("Break even after {} years and {} kilometers. {}".format(y, y*settings["kilometers_per_year"], current_y[0]-current_y[1]))
|
|
|
|
plt.show()
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|