-
Notifications
You must be signed in to change notification settings - Fork 8
/
power.rb
executable file
·153 lines (123 loc) · 4.15 KB
/
power.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
require "csv"
require "time"
require "optparse"
require "logger"
require_relative "./lib/plans"
def colorize_string(string, code)
"\e[0;#{code};49m#{string}\e[0m"
end
logger = Logger.new $stderr
# default lat/long are for Phoenix in general
options = { provider: "srp", lat: 33.448376, long: -112.074036, cpw: 3.52, efficiency: 1.0, loadcap: 9999 }
parser = OptionParser.new do |opts|
opts.banner = "Usage: example.rb [options]"
opts.on("-d", "--debug", "Print debug information") do |v|
options[:debug] = v
end
opts.on("-f", "--file CSV", "CSV to parse") do |v|
options[:csv] = v
end
opts.on("-p", "--provider (aps|srp)", "Electric provider's rate plans to use") do |v|
options[:provider] = v
end
opts.on("-m", "--demand CSV", "Provide an additional demand CSV, available to customers on the SRP E27 plan") do |v|
options[:demand_schedule] = v
end
opts.on("-o", "--offset kwh", "Estimate an offset of this many kWh from a solar system") do |v|
options[:offset] = v.to_f
end
opts.on("--srp-ez3-start-hour [14,15,16]", %w(14 15 16), "Specify the starting hour as 24h time for SRP's EZ3 plan, for legacy customers.") do |v|
options[:srp_ez3_start_hour] = v.to_i
end
opts.on("--location loc", "Specify your location as lat,long for accurate sunrise/sunset times") do |v|
options[:lat], options[:long] = v.split(",").map(&:to_f)
end
opts.on("-w", "--costperwatt cpw", "Cost per watt (installed)") do |v|
options[:cpw] = v.to_f
end
opts.on("-e", "--efficiency efficiency", "Array efficiency vs nominal (0.78 default)") do |v|
options[:efficiency] = v.to_f
end
opts.on("-l", "--loadgov gov", "Simulate a load governor by capping hourly usage at a given level") do |v|
options[:loadcap] = v.to_f
end
opts.on("-x", "--extended", "Show extended breakout tables") do |v|
options[:extended] = v
end
opts.on("-s", "--schedule file", "PVWatts Hourly Generation Schedule CSV") do |v|
options[:pvwatts] = v
end
opts.on("--exclude-solar-plans", "Exclude Solar Plans") do |v|
options[:exclude_solar_plans] = true
end
end
begin
parser.parse!
rescue OptionParser::InvalidArgument => e
puts colorize_string "Invalid option: #{e.message}", 31
puts ""
puts parser.help
puts ""
exit
end
if options[:csv].nil?
puts colorize_string "Missing data file! Pass your CSV with the -f option.", 31
puts ""
puts parser.help
exit
end
if options[:debug]
logger.level = Logger::DEBUG
else
logger.level = Logger::INFO
end
root = case options[:provider]
when "srp"
Plans::SRP
else
Plans::APS
end
demand_schedule = nil
if options[:demand_schedule]
demand_schedule = {}
CSV.open(options[:demand_schedule], headers: true).each do |row|
key = Date.strptime(row[0], "%m/%d/%Y").strftime("%Y-%m")
demand = row[2].to_f
demand_schedule[key] ||= demand
demand_schedule[key] = demand if demand > demand_schedule[key]
end
end
applicable_plans = root::PLANS.reject{|c| c.solar_eligible if options[:exclude_solar_plans]}
plans = applicable_plans.select { |c| !options[:offset] || c.solar_eligible }.map { |c| c.new(logger, demand_schedule, options) }
CSV.open(options[:csv], headers: true) do |csv|
arr = csv.to_a
arr.each do |row|
row[0] = Date.strptime(row[0], "%m/%d/%Y") rescue nil
end
arr.select(&:first).sort_by(&:first).each do |row|
date = row[0]
time = Time.parse(row[1])
datetime = Time.local(date.year, date.month, date.day, time.hour, time.min, time.sec)
plans.each { |plan| plan.add(datetime, row[2].to_f) }
end
end
sorted = plans.sort_by(&:total)
all = sorted.dup
best = sorted.shift
worst = sorted.pop
puts <<-EOF
NOTE: The following projections include fixed fees (such as monthly service charges)
and energy costs, but do not include taxes or extra costs such as SRP Earthwise. These
projections may not match your actual bill as a result, but should accurately reflect
the relative cost of the programs.
EOF
Plans::Base.print_header
puts colorize_string best, 32
sorted.each do |plan|
puts colorize_string plan, 33
end
puts colorize_string worst, 31 if worst
puts ""
all.each do |plan|
plan.extra_notes
end if options[:extended]