diff --git a/LICENSE b/LICENSE index effdf2c..cd4a96d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) . All rights reserved. +Copyright (c) 2024 Maximilian Stiefel. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/ecar.py b/ecar.py deleted file mode 100644 index ebd022f..0000000 --- a/ecar.py +++ /dev/null @@ -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() diff --git a/example_1.json b/example.json similarity index 96% rename from example_1.json rename to example.json index d633471..ad5bb59 100644 --- a/example_1.json +++ b/example.json @@ -15,7 +15,7 @@ { "label": "Geothermal heat pump", "installation_price": 222788, - "reinstallation_price": 160000, + "reinstallation_price": 120000, "kwh_expenditure": 4519.1, "kwh_price": 1.94, "maintenance_price": 2000, diff --git a/example_0.json b/example_0.json deleted file mode 100644 index 73e4532..0000000 --- a/example_0.json +++ /dev/null @@ -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 - } -} diff --git a/heatpump.py b/heatpump.py index 2d10b00..b79b9e8 100644 --- a/heatpump.py +++ b/heatpump.py @@ -2,7 +2,6 @@ import matplotlib matplotlib.use('Qt5Agg') # or 'Qt5Agg', depending on your setup import matplotlib.pyplot as plt import numpy as np -from numpy_da import DynamicArray import json import sys import argparse @@ -92,12 +91,15 @@ def main(): increase_installation = np.zeros(input_data.amount_of_technologies) increase_expenditure = np.zeros(input_data.amount_of_technologies) + # Calculate inflation + inflation_factor = np.array([1.0 + (x * year) / 100.0 for x in input_data.percent_inflation]) + # Handle possible replacement of heating system for j in range(input_data.amount_of_technologies): if (year % input_data.years_lifespan[j]) == 0 and year == 0: - increase_installation[j] = input_data.installation_price[j] + increase_installation[j] = input_data.installation_price[j] * inflation_factor[j] elif (year % input_data.years_lifespan[j]) == 0 and year > 0: - increase_installation[j] = input_data.reinstallation_price[j] + increase_installation[j] = input_data.reinstallation_price[j] * inflation_factor[j] else: increase_installation[j] = 0 # just to be clear @@ -107,7 +109,6 @@ def main(): increase_expenditure[j] += input_data.maintenance_price[j] # Calculate increase - inflation_factor = np.array([1.0 + (x * year) / 100.0 for x in input_data.percent_inflation]) increase_expenditure = input_data.kwh_expenditure * input_data._kwh_price * inflation_factor increase_total = increase_installation + increase_expenditure diff --git a/pictures/example.png b/pictures/example.png new file mode 100644 index 0000000..8cd9de3 Binary files /dev/null and b/pictures/example.png differ diff --git a/pictures/plot_ex_0.png b/pictures/plot_ex_0.png deleted file mode 100644 index 47804b1..0000000 Binary files a/pictures/plot_ex_0.png and /dev/null differ