import arrow import random import pprint import json from datetime import datetime, timedelta rand = random.Random('a seed') tz = 'US/Pacific' startdate = arrow.Arrow(2019, 11, 1, tzinfo=tz) enddate = arrow.Arrow(2019, 12, 10, tzinfo=tz) meanwhprod = 20000 sigwhprod = 2000 def drange(s, e, interval): cmpfun = lambda s, e, ts, te: te < e if e < s: interval = -interval cmpfun = lambda s, e, ts, te: te > e ts = s.clone() te = ts + interval #print('dr:', repr((s, e, ts, te, cmpfun(s, e, ts, te), interval))) while cmpfun(s, e, ts, te): yield ts + (te - ts) ts, te = te, te + interval # idea: # first hour linear ramp up (25% in first half, 75% in second half) # middle 5 hours near constant generation # first/tailing linear is equiv of an hour total, so total power / 6 # approx 7 hours time def makestartend(t): s = t.replace(hour=9).shift(minutes=rand.gauss(30, 10)) e = t.replace(hour=16).shift(minutes=rand.gauss(30, 10)) return (s, e) def normdist(small, big, amount, minsize): '''Distribute most twoards the big side, total distribute amount over the entire range, [small, big]. ''' ret = [] timediff = abs(big - small) if timediff < minsize: scaledamount = amount * (timedelta(hours=1) / timediff) midpnt = small + (big - small) / 2 #print('ndf:', repr((small, big, midpnt, amount, scaledamount))) return [ (midpnt, scaledamount) ] #print('nd:', repr((small, big, amount))) dist = big - small halfpoint = small + (dist / 9 * 5) ret.extend(normdist(small, halfpoint, amount / 2, minsize)) ret.extend(normdist(halfpoint, big, amount / 2, minsize)) #print('ndr:') #pprint.pprint(ret) return ret def linramp(start, end, wtarget, minsize): mid = start + (end - start) / 2 timediff = abs(end - start) ret = [] ndates = abs((end - start) / minsize) #print('lr', ndates) for x, i in enumerate(drange(start, end, minsize)): #print(repr((x, i))) yield (i, x / ndates * wtarget) def makeconsumption(s, mean, sig, interval): s = s.replace(hour=0, minute=0, second=0) e = (s + timedelta(days=1)) - interval ret = [ (i, rand.gauss(mean, sig)) for i in drange(s, e, interval) ] return ret def distribute(s, e, prod, minsize): onehour = timedelta(hours=1) totaltime = e - s mid = s + totaltime / 2 startrampend = s + onehour endrampstart = e - onehour # prod == wh wtarget = prod / ((totaltime + onehour).seconds / 60 / 60) ret = [] #print('d:', repr((s, e))) ret.extend(linramp(s, startrampend, wtarget, minsize)) for i in drange(startrampend, endrampstart, minsize): ret.append((i, wtarget)) ret.extend(linramp(e, endrampstart, wtarget, minsize)) ret.sort() #pprint.pprint(ret) return ret #print('start') prodpoints = [] prodindex = [] conspoints = [] consindex = [] def serializearrowasmili(obj): if not isinstance(obj, arrow.Arrow): raise TypeError return int(obj.float_timestamp*1000) for i in arrow.Arrow.range('day', startdate, enddate): whprod = rand.gauss(meanwhprod, sigwhprod) s, e = makestartend(i) noon = i.replace(hour=12) prodindex.append((noon, whprod)) #print(repr(i), whprod) dist = [] tmppoints = makeconsumption(s, rand.uniform(400,800), 100, timedelta(minutes=1)) consindex.append((noon, sum((i[1] / 60 for i in tmppoints), 0))) conspoints.extend(tmppoints) # zero points for non-production import sys dist.extend(distribute(i, s, 0, timedelta(minutes=5))) # production dist.extend(distribute(s, e, whprod, timedelta(seconds=20))) # zero points for non-production eod = i.replace(hour=23, minute=55) dist.extend(distribute(e, eod, 0, timedelta(minutes=5))) # print timestamps as miliseconds if False: dist = ((int(a.float_timestamp*1000), b) for a, b in dist) # print space delimited time, else json if False: print('\n'.join('%s %s' % (a, b) for a, b in dist)) else: #print(json.dumps(tuple(dist), indent=2)) prodpoints.extend(dist) for i in { 'prodpoints', 'prodindex', 'conspoints', 'consindex',}: v = locals()[i] v = [ (x, int(y)) for x, y in v ] locals()[i] = v print('fakedata =', json.dumps(dict(production=prodpoints, prodindex=prodindex, consumption=conspoints, consindex=consindex), default=serializearrowasmili, indent=2))