|
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
'''
|
|
gas.py: для расчета потребления газа
|
|
'''
|
|
|
|
import sys
|
|
import json
|
|
import datetime
|
|
|
|
|
|
__author__ = 'Nikolay Gatilov'
|
|
__copyright__ = 'Nikolay Gatilov'
|
|
__license__ = 'GPL'
|
|
__version__ = '1.0.20161118'
|
|
__maintainer__ = 'Nikolay Gatilov'
|
|
__email__ = 'eking.work@gmail.com'
|
|
|
|
DEBUG = False
|
|
|
|
def load_data(df):
|
|
try:
|
|
with open(df, 'r') as f:
|
|
data = json.load(f)
|
|
except Exception as e:
|
|
data = {}
|
|
print ('Unable to read data from file:\n%s\n' % str(e))
|
|
return data
|
|
|
|
|
|
def date_from_iso(s):
|
|
(y, m, d) = map(int, s.split('-'))
|
|
return datetime.date(y, m, d)
|
|
|
|
|
|
def convert_data(raw_d):
|
|
raw_d_t = {}
|
|
for i in raw_d.keys():
|
|
raw_d_t[date_from_iso(i)] = int(raw_d[i])
|
|
return raw_d_t
|
|
|
|
|
|
def get_first_date(raw_d):
|
|
fd = min(raw_d)
|
|
if fd.day > 1:
|
|
return (fd.replace(day=1) + datetime.timedelta(days=32)).replace(day=1)
|
|
else:
|
|
return fd
|
|
|
|
|
|
def get_last_date(raw_d):
|
|
fd = max(raw_d)
|
|
nm = fd + datetime.timedelta(days=1)
|
|
if fd.month != nm.month:
|
|
return fd
|
|
else:
|
|
nm = fd.replace(day=1) + datetime.timedelta(days=32)
|
|
return nm.replace(day=1) - datetime.timedelta(days=1)
|
|
|
|
|
|
def get_month_dates(k, month):
|
|
md = []
|
|
tmax = max(k)
|
|
tdmax = tmax - month
|
|
tmin = min(k)
|
|
tdmin = month - tmin
|
|
for i in k:
|
|
if i.year == month.year and i.month == month.month:
|
|
md.append(i)
|
|
elif i > month and i - month < tdmax:
|
|
tdmax = i - month
|
|
tmax = i
|
|
elif i < month and month - i < tdmin:
|
|
tdmin = month - i
|
|
tmin = i
|
|
if tmax not in md:
|
|
md.append(tmax)
|
|
if tmin not in md and month not in md:
|
|
md.append(tmin)
|
|
return sorted(md)
|
|
|
|
|
|
def compute(md):
|
|
k = md.keys()
|
|
now = get_first_date(k)
|
|
last_date = get_last_date(k)
|
|
mad = {}
|
|
while now < last_date:
|
|
mda = get_month_dates(k, now)
|
|
if DEBUG:
|
|
print('\n', now, mda)
|
|
nxt = (now + datetime.timedelta(days=32)).replace(day=1)
|
|
mad[now] = 0
|
|
h = mda.pop(0)
|
|
for i in mda:
|
|
r = (md[i]-md[h])
|
|
if DEBUG:
|
|
print('==> ', md[i], md[h], r)
|
|
if h < now:
|
|
mad[now] = mad[now] + r*abs(min(i, nxt) - now)/abs(i - h)
|
|
if DEBUG:
|
|
print(' from h < now (',
|
|
min(i, nxt),
|
|
'-',
|
|
now,
|
|
')/(',
|
|
i,
|
|
'-',
|
|
h,
|
|
') = ',
|
|
mad[now])
|
|
elif i > nxt:
|
|
mad[now] = mad[now] + r*abs(nxt - max(h, now))/abs(i - h)
|
|
if DEBUG:
|
|
print(' from i > nxt (',
|
|
nxt,
|
|
'-',
|
|
max(h, now),
|
|
')/(',
|
|
i,
|
|
'-',
|
|
h,
|
|
') = ',
|
|
mad[now])
|
|
else:
|
|
mad[now] = mad[now] + r
|
|
if DEBUG:
|
|
print(' only add r ',
|
|
h,
|
|
i,
|
|
' = ',
|
|
mad[now])
|
|
h = i
|
|
mad[now] = round(mad[now])
|
|
if DEBUG:
|
|
print('----- ', mad[now])
|
|
now = nxt
|
|
return mad
|
|
|
|
|
|
def save_data(df, data):
|
|
try:
|
|
with open(df, 'w') as f:
|
|
json.dump(data, f, sort_keys=True)
|
|
except Exception as e:
|
|
print('Unable to save data in file:\n%s\n' % str(e))
|
|
|
|
|
|
if __name__ == "__main__": # main
|
|
RAW_DATA_FILE = '%s_raw.json' % sys.argv[0]
|
|
AVG_DATA_FILE = '%s_avg.json' % sys.argv[0]
|
|
raw_data = load_data(RAW_DATA_FILE)
|
|
if len(sys.argv) > 2:
|
|
di = sys.argv[1].split('.')
|
|
count_in = int(sys.argv[2])
|
|
da = date_from_iso(sys.argv[1])
|
|
raw_data[da.isoformat()] = count_in
|
|
else:
|
|
by_month_data = convert_data(raw_data)
|
|
avg_data = compute(by_month_data)
|
|
avg_i = iter(sorted(avg_data.keys()))
|
|
raw_i = iter(sorted(by_month_data.keys()))
|
|
a_i_n = next(avg_i, None)
|
|
r_i_n = next(raw_i, None)
|
|
ma = by_month_data[max(by_month_data.keys())]
|
|
mi = by_month_data[min(by_month_data.keys())]
|
|
total_raw_sum = (ma-mi)
|
|
total_avg_sum = 0
|
|
print('\n| Raw counters: | Average by mounth:\n')
|
|
while a_i_n is not None or r_i_n is not None:
|
|
if a_i_n is not None:
|
|
ain_d = '{:%Y-%m}'.format(a_i_n)
|
|
ain_n = '{:6d}'.format(avg_data[a_i_n])
|
|
ain = '| %s %s' % (ain_d, ain_n)
|
|
total_avg_sum = total_avg_sum + avg_data[a_i_n]
|
|
else:
|
|
ain = ' ' * 14
|
|
if r_i_n is not None:
|
|
rin_d = '{:%Y-%m-%d}'.format(r_i_n)
|
|
rin_n = '{:6d}'.format(by_month_data[r_i_n])
|
|
rin = '| %s %s' % (rin_d, rin_n)
|
|
else:
|
|
rin = ' ' * 24
|
|
print(rin, ain)
|
|
a_i_n = next(avg_i, None)
|
|
r_i_n = next(raw_i, None)
|
|
s = '\n{:s}\n| Total sum: {:7d} | Total average sum: {:7d}\n'
|
|
s = s.format('=' * 60, total_raw_sum, total_avg_sum)
|
|
print(s)
|
|
avg = {}
|
|
for i in avg_data.keys():
|
|
avg[i.isoformat()] = avg_data[i]
|
|
save_data(AVG_DATA_FILE, avg)
|
|
save_data(RAW_DATA_FILE, raw_data)
|