| 
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -2,6 +2,7 @@ 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 | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -13,23 +14,20 @@ class JsonSettingsExtractor: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        with open(fname, "r") as rf: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            settings = json.load(rf) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            self._currency = settings["currency"] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            self._legend = settings["legend"] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            # Kind of inefficient code. Does not matter only runs once at startup | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            _technologies = settings["technologies"] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            self._label = [technology["label"] for technology in _technologies] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            self._installation_price = [technology["installation_price"] for technology in _technologies] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            self._reinstallation_price = [technology["reinstallation_price"] for technology in _technologies] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            self._kwh_expenditure = [technology["kwh_expenditure"] for technology in _technologies] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            self._kwh_price = [technology["kwh_price"] for technology in _technologies] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            self._percent_inflation = [technology["percent_inflation"] for technology in _technologies] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            self._years_lifespan = [technology["years_lifespan"] for technology in _technologies] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            self._amount_of_technologies = len(self.label) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    @property | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    def currency(self): | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return self._currency | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					     | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    @property | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    def legend(self): | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return self._legend | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    @property | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    def label(self): | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -37,56 +35,114 @@ class JsonSettingsExtractor: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    @property | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    def installation_price(self): | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return self._installation_price | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return np.array(self._installation_price) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					     | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    @property | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    def reinstallation_price(self): | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return np.array(self._reinstallation_price) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    @property | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    def kwh_expenditure(self): | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return self._kwh_expenditure | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return np.array(self._kwh_expenditure) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					     | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    @property | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    def percent_inflation(self): | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        self._percent_inflation | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return np.array(self._percent_inflation) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    @property | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    def years_lifespan(self): | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        self._years_lifespan | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return self._years_lifespan | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    @property | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    def amount_of_technologies(self): | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return self._amount_of_technologies | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					def main(): | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    parser = argparse.ArgumentParser(description='This script allows to calculate which heating technology makes sense financially for you.') | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    parser.add_argument('-a','--settings', help='Settings file.', required=True, metavar=('FILENAME')) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    parser.add_argument('-g','--plot', help='Visualize costs over one or multiple years.', type=int, metavar=('YEARS')) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    parser.add_argument('-b','--years', help='Amount of years for which to run the simulation.', required=True, type=int, metavar=('YEARS')) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    parser.add_argument('-c','--plot', help='Visualize the calculations done.', action='store_true') | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    args = parser.parse_args() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    input_data = JsonSettingsExtractor(args.settings) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    print("Inflations: {}".format(input_data.percent_inflation)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    print("Expend: {}".format(input_data.kwh_expenditure)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    # if args.plot != None: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    #     # Basic settings | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    #     width = 0.3 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    #     plt_colors = ["#8ecae6", "#219ebc", "#023047", "#ffb703", "#fb8500"]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    #     fig, ax = plt.subplots() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    #     ax.bar(input_data.label, input_data.installation_price, width, label = "Installation price", color = plt_colors[0]) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    # Basic settings | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    currency = input_data.currency | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    # Initializations | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    year = 0 #first year | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    #grand_total = DynamicArray(shape=(0, input_data._amount_of_technologies)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    grand_total = np.empty((0, input_data.amount_of_technologies)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    # Iteration for years in service | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    for i in range(args.years): | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        # Initializations | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        increase_total = np.zeros(input_data.amount_of_technologies) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        increase_installation = np.zeros(input_data.amount_of_technologies) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        increase_expenditure = np.zeros(input_data.amount_of_technologies) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        # Handle possible replacement of heating system | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        for j in range(len(input_data.years_lifespan)):  | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (year % input_data.years_lifespan[j]) == 0 and year == 0: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                increase_installation[j] = input_data.installation_price[j] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            elif (year % input_data.years_lifespan[j]) == 0 and year > 0: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                increase_installation[j] = input_data.reinstallation_price[j] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            else:  | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                increase_installation[j] = 0 # just to be clear | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					         | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    #     current_y = input_data.installation_price | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    #     years = 0 #first year | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    #     # Iteration for years in service | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    #     for i in range(args.plot): | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    #         inflation_factor = 1.0 + (input_data.percent_inflation * years) / 100.0 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    #         increase = input_data.kwh_expenditure * inflation_factor | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    #         ax.bar(input_data.label, increase, width, bottom = current_y, label = "Expenditure".format(y), color = plt_colors[1]) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    #         years += 1 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    #         current_y += increase | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    #     ax.set_ylabel(input_data.currency) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    #     ax.set_title("Comparision of economics w/ different heating technologies") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    #     ax.legend(input_data.legend) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    #     plt.show() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        # 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 * inflation_factor | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        increase_total = increase_installation + increase_expenditure | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        # Safe the yearly costs for plotting | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        if year > 0: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            grand_total = np.vstack((grand_total, increase_total + grand_total[year - 1])) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        elif year == 0: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            grand_total = np.vstack((grand_total, increase_total)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        # Output data every year | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        # Rounding | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        increase_total = np.round(increase_total, decimals=0) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        increase_installation = np.round(increase_installation, decimals=0) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        increase_expenditure = np.round(increase_expenditure, decimals=0) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        print(f"Year {year:2.0f} \t\tInstallation [{currency}] \tExpenditure [{currency}] \tTotal [{currency}] \tGrand total [{currency}]") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        print("-------------------------------------------------------------------------------------------------------------") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        for j in range(input_data.amount_of_technologies): | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            print(f"{input_data.label[j]} \t{increase_installation[j]:8.0f} \t\t{increase_expenditure[j]:8.0f} \t\t{increase_total[j]:8.0f} \t{grand_total[year][j]:8.0f}") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        print("\n") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        year += 1 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if args.plot: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        # Define colors for each line | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        plt_colors = ["#8ecae6", "#219ebc", "#023047", "#ffb703", "#fb8500"]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        # Number of years and technologies | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        years = grand_total.shape[0] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        technologies = grand_total.shape[1] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        # Create a figure and axis | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        plt.figure(figsize=(10, 6)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        # Generate line plots for each technology | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        for i in range(technologies): | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            plt.plot(range(years), grand_total[:, i], marker='o', color=plt_colors[i], label=f'Technology {i+1}') | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        # Adding titles and labels | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        plt.title('Economical comparision of different heating technologies') | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        plt.xlabel('Year') | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        plt.ylabel(f'Cost {currency}') | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        # plt.xticks(range(years), [f'Year {j+1}' for j in range(years)])  # Customize x-ticks if needed | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        plt.legend(input_data.label) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        plt.grid() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        # Show the plot | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        plt.tight_layout() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        plt.show() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					if __name__ == "__main__": | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    main() | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
					 | 
				
				 | 
				
					
  |