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 [ " 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 " ]
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 ( - 0.2 , 1.2 , 10 ) , [ be_money [ 1 ] ] * 10 , " -- " , color = plt_colors [ 2 ] , label = " Break even " )
ax . text ( 0.3 , 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 ( - 0.2 , 1.2 , 10 ) , [ am_money [ 1 ] ] * 10 , " -- " , color = plt_colors [ 2 ] , label = " Amortization " )
ax . text ( 0.3 , 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 ( )