7 changed files with 7 additions and 202 deletions
			
			
		@ -1,168 +0,0 @@ | 
				
			|||
import matplotlib | 
				
			|||
matplotlib.use('Qt5Agg')  # or 'Qt5Agg', depending on your setup | 
				
			|||
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["juice_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["ccar"]["maintenance"]]) | 
				
			|||
            self.kilometers = settings["kilometers_per_year"] | 
				
			|||
            self.currency = settings["currency"] | 
				
			|||
    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 | 
				
			|||
    def get_kilometers(self): | 
				
			|||
        return self.kilometers | 
				
			|||
    def get_currency(self): | 
				
			|||
        return self.currency | 
				
			|||
 | 
				
			|||
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 = total_costs + increment  | 
				
			|||
            months += 1 | 
				
			|||
        kilometers = self.settings_extractor.get_kilometers() * months / months_a_year | 
				
			|||
        return [months//months_a_year, months%months_a_year, kilometers] # years, months | 
				
			|||
    def calculate_amortization_point(self): | 
				
			|||
        y = 0 | 
				
			|||
        m = 1 | 
				
			|||
        months_a_year = 12.0 | 
				
			|||
        # Insurance and taxes need to be payed anyway | 
				
			|||
        relevant_costs_a_year = self.settings_extractor.get_driving() + self.settings_extractor.get_maintenance() | 
				
			|||
        savings_a_month = (relevant_costs_a_year[1]-relevant_costs_a_year[0]) / months_a_year | 
				
			|||
        months_till_amortized = self.settings_extractor.get_purchase()[0] / savings_a_month | 
				
			|||
        kilometers = months_till_amortized * self.settings_extractor.get_kilometers() / months_a_year | 
				
			|||
        months_till_amortized = np.ceil(months_till_amortized) | 
				
			|||
        return months_till_amortized//months_a_year, months_till_amortized%months_a_year, round(kilometers, ndigits=2) | 
				
			|||
 | 
				
			|||
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 the EV becomes cheaper).', action='store_true') | 
				
			|||
    parser.add_argument('-c','--amortization', help='Calculate the point in time when the electric vehicle is amortized completely by savings.', action='store_true') | 
				
			|||
    parser.add_argument('-d','--savings_per_month', help='Calculate savings per month.', action='store_true') | 
				
			|||
    parser.add_argument('-e','--savings_per_year', help='Calculate savings per year.', action='store_true') | 
				
			|||
    parser.add_argument('-f','--savings_per_kilometer', help='Calculate savings per 100 kilometers (only driving, no maintenance, taxes or insurance).', action='store_true') | 
				
			|||
    parser.add_argument('-g','--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) | 
				
			|||
    be_years = None | 
				
			|||
    be_months = None | 
				
			|||
    be_kilometers = None | 
				
			|||
    if args.break_even: | 
				
			|||
        be_years, be_months, be_kilometers = comparator.calculate_break_even() | 
				
			|||
        print("Break even after {} years and {} months.".format(be_years, be_months)) | 
				
			|||
    if args.savings_per_month: | 
				
			|||
        years = 0 | 
				
			|||
        months = 1 | 
				
			|||
        savings = comparator.calculate_costs(years, months) | 
				
			|||
        print("Savings per month based on yearly spending: {}.".format(round(savings[1]-savings[0], ndigits=2))) | 
				
			|||
    if args.savings_per_year: | 
				
			|||
        years = 1 | 
				
			|||
        months = 0 | 
				
			|||
        savings = comparator.calculate_costs(years, months) | 
				
			|||
        print("Savings per year: {}.".format(round(savings[1]-savings[0], ndigits=2))) | 
				
			|||
    if args.savings_per_kilometer: | 
				
			|||
        hundred_km = 100.0 | 
				
			|||
        driving = hundred_km * extractor.get_driving() / extractor.get_kilometers()  | 
				
			|||
        labels = extractor.get_labels() | 
				
			|||
        print("Costs driving 100 km in the {}: {}. Costs driving 100 km in the {}: {}.".format(labels[0], round(driving[0], ndigits=2), labels[1], round(driving[1]), ndigits=2)) | 
				
			|||
    am_years = None | 
				
			|||
    am_months = None | 
				
			|||
    am_kilometers = None | 
				
			|||
    if args.amortization: | 
				
			|||
        am_years, am_months, am_kilometers = comparator.calculate_amortization_point() | 
				
			|||
        print("The electric vehicle will be amortized by savings after {} years, {} months or exactely at {} kilometres.".format(am_years, am_months, am_kilometers)) | 
				
			|||
    if args.plot != None: | 
				
			|||
        width = 0.3 | 
				
			|||
        plt_colors = ["#8ecae6", "#219ebc", "#023047", "#ffb703", "#fb8500"]; | 
				
			|||
        color_ind = 0 | 
				
			|||
        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 = plt_colors[0]) | 
				
			|||
        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 = plt_colors[1]) | 
				
			|||
            current_y = current_y + taxes | 
				
			|||
            ax.bar(labels, insurance, width, bottom = current_y, label = "Insurance".format(y), color = plt_colors[2]) | 
				
			|||
            current_y = current_y + insurance | 
				
			|||
            ax.bar(labels, driving, width, bottom = current_y, label = "Driving".format(y), color = plt_colors[3]) | 
				
			|||
            current_y = current_y + driving | 
				
			|||
            ax.bar(labels, maintenance, width, bottom = current_y, label = "Maintenance".format(y), color = plt_colors[4]) | 
				
			|||
            current_y = current_y + maintenance | 
				
			|||
            y += 1 | 
				
			|||
        labels = ["Purchase", "Taxes", "Insurance", "Driving", "Maintenance"] | 
				
			|||
        lnspace_start = -0.2 | 
				
			|||
        lnspace_stop = 1.2 | 
				
			|||
        lnspace_n = 10 | 
				
			|||
        x_text = 0.2 | 
				
			|||
        if args.break_even: | 
				
			|||
            months_a_year = 12.0 | 
				
			|||
            be_money = (be_years + be_months/months_a_year) * comparator.calculate_costs_a_year() | 
				
			|||
            be_money = be_money[1] + extractor.get_purchase() | 
				
			|||
            ax.plot(np.linspace(lnspace_start, lnspace_stop, lnspace_n), [be_money[1]]*lnspace_n, "--", color = plt_colors[2], label = "Break even") | 
				
			|||
            ax.text(x_text, be_money[1] + 100, "Break even: {} years, {} months, {} kilometers".format(be_years, be_months, be_kilometers)) | 
				
			|||
            labels = ["Break even"] + labels | 
				
			|||
        if args.amortization: | 
				
			|||
            months_a_year = 12.0 | 
				
			|||
            am_money = (am_years + am_months/months_a_year) * comparator.calculate_costs_a_year() | 
				
			|||
            am_money = am_money[1] + extractor.get_purchase() | 
				
			|||
            ax.plot(np.linspace(lnspace_start, lnspace_stop, lnspace_n), [am_money[1]]*lnspace_n, "--", color = plt_colors[2], label = "Amortization") | 
				
			|||
            ax.text(x_text, am_money[1] + 100, "Amortization: {} years, {} months, {} kilometers".format(am_years, am_months, am_kilometers)) | 
				
			|||
            labels = ["Amortization"] + labels | 
				
			|||
        ax.set_ylabel(extractor.get_currency()) | 
				
			|||
        ax.set_title("Comparision of economics: Electric vs. combustion car") | 
				
			|||
        ax.legend(labels) | 
				
			|||
        ax.grid(axis = "y") | 
				
			|||
        plt.show() | 
				
			|||
 | 
				
			|||
if __name__ == "__main__": | 
				
			|||
    main() | 
				
			|||
@ -1,28 +0,0 @@ | 
				
			|||
{ | 
				
			|||
    "currency": "CHF",	 | 
				
			|||
    "kwh_price_home": 0.2, | 
				
			|||
    "kwh_price_commercial": 0.5, | 
				
			|||
    "juice_litre_price": 1.75, | 
				
			|||
    "kilometers_per_year": 20000.0, | 
				
			|||
    "ecar": { | 
				
			|||
	"label": "Nissan Leaf 2013", | 
				
			|||
        "price": 7600, | 
				
			|||
        "taxes": 0, | 
				
			|||
        "insurance": 354, | 
				
			|||
        "kwh_per_kilometer": 0.16, | 
				
			|||
        "maintenance": 100, | 
				
			|||
	"charging_behaviour": { | 
				
			|||
		"percent_free_charges": 90, | 
				
			|||
		"percent_home_charges": 5, | 
				
			|||
		"percent_commercial_charges": 5 | 
				
			|||
	} | 
				
			|||
    }, | 
				
			|||
    "ccar": { | 
				
			|||
	"label": "Suzuki Grand Vitara 2008", | 
				
			|||
        "price": 7000, | 
				
			|||
        "taxes": 350, | 
				
			|||
        "insurance": 362, | 
				
			|||
        "litres_per_kilometer": 0.08, | 
				
			|||
        "maintenance": 1000 | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
| 
		 After Width: | Height: | Size: 79 KiB  | 
| 
		 Before Width: | Height: | Size: 52 KiB  | 
					Loading…
					
					
				
		Reference in new issue