mmnode-blocks-info: -s totals -> -s total; rewrite total stats code

This commit is contained in:
The MMGen Project 2021-03-24 16:25:25 +00:00
commit cb42dd9207
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
2 changed files with 67 additions and 21 deletions

View file

@ -96,14 +96,14 @@ class BlocksInfo:
)
fs_lsqueeze2 = ('interval',)
all_stats = ['avg','totals','range','diff']
all_stats = ['avg','total','range','diff']
dfl_stats = ['range','diff']
noindent_stats = ['avg']
avg_stats_skip = {'block', 'hash', 'date', 'version','miner'}
stats_deps = {
'avg': set(fields) - avg_stats_skip,
'totals': {'interval','subsidy','totalfee','nTx','inputs','outputs','utxo_inc'},
'total': {'interval','subsidy','totalfee','nTx','inputs','outputs','utxo_inc'},
'range': {},
'diff': {},
}
@ -424,7 +424,8 @@ class BlocksInfo:
yield self.fs.format(*hdr2)
def process_stats(self,sname):
return self.output_stats(getattr(self,f'create_{sname}_stats')(),sname)
method = getattr(self,f'create_{sname}_stats',None)
return self.output_stats(method() if method else self.create_stats(sname),sname)
def fmt_stat_item(self,fs,s):
return fs.format(s) if type(fs) == str else fs(s)
@ -535,25 +536,68 @@ class BlocksInfo:
fs = ''.join(self.gen_fs(self.fnames,fill=self.avg_stats_skip,add_name=True)).strip()
return ('averages', ('Averages:', (fs, dict(gen())) ))
async def create_totals_stats(self):
def total_stats_data(self,data,spec_conv,spec_val):
coin = self.rpc.proto.coin
fields = {
'interval': ('Solve Time: {} h/m/s', secs_to_dhms),
'subsidy': ('Subsidy: {} %s' % coin, self.fmt_funcs['su']),
'totalfee': ('Fees: {} %s' % coin, self.fmt_funcs['tf']),
'earnings': ('Subsidy+Fees: {} %s' % coin, self.fmt_funcs['tf']),
'nTx': ('nTx: {}', int),
'inputs': ('Inputs: {}', int),
'outputs': ('Outputs: {}', int),
'utxo_inc': ('UTXO change: {:<+}', int),
}
fnames = list( set(fields) & set(self.fnames) )
vals = dict( ( name, sum(getattr(blk,name) for blk in self.res) ) for name in fnames )
if 'subsidy' in vals and 'totalfee' in vals:
vals['earnings'] = vals['subsidy'] + vals['totalfee']
fnames.append('earnings')
res = [( v[0], k, v[1], vals[k] ) for k,v in fields.items() if k in fnames]
return ( 'totals', ['Totals:'] + res )
return data(
hdr = 'Totals for processed blocks:',
func = lambda field: sum(getattr(block,field) for block in self.res),
spec_sufs = { 'subsidy': f' {coin}', 'totalfee': f' {coin}', 'reward': f' {coin}' },
spec_convs = {
'interval': spec_conv(0, lambda arg: secs_to_dhms(arg)),
'utxo_inc': spec_conv(-1, '{:<+}'),
'reward': spec_conv(0, self.fmt_funcs['tf']),
},
spec_vals = (
spec_val(
'reward', 'Reward', 'totalfee',
lambda values: {'subsidy','totalfee'} <= set(values),
lambda values: values['subsidy'] + values['totalfee']
),
)
)
async def create_stats(self,sname):
def convert_stats_hdr(field):
v = self.fields[field]
return '{} {}'.format(v.hdr1.strip(), v.hdr2.strip()).replace('- ','') if v.hdr1 else v.hdr2.strip()
d = getattr(self,f'{sname}_stats_data')(
namedtuple('stats_data',['hdr','func','spec_sufs','spec_convs','spec_vals']),
namedtuple('spec_conv',['width_adj','conv']),
namedtuple('spec_val',['name','lbl','insert_after','condition','code'])
)
fnames = [n for n in self.fnames if n in self.stats_deps[sname]]
lbls = {n:convert_stats_hdr(n) for n in fnames}
values = {n:d.func(n) for n in fnames}
col1_w = max((len(l) for l in lbls.values()),default=0) + 2
for v in d.spec_vals:
if v.condition(values):
try: idx = fnames.index(v.insert_after) + 1
except: idx = 0
fnames.insert(idx,v.name)
lbls[v.name] = v.lbl
values[v.name] = v.code(values)
def gen():
for n,fname in enumerate(fnames):
spec_conv = d.spec_convs.get(fname)
yield (
'{lbl:{wid}} {{}}{suf}'.format(
lbl = lbls[fname] + ':',
wid = col1_w + (spec_conv.width_adj if spec_conv else 0),
suf = d.spec_sufs.get(fname) or ''
),
fname,
spec_conv.conv if spec_conv else (
(lambda x: self.fmt_funcs[x] if x else '{}')(self.fields[fname].fmt_func)
),
values[fname]
)
return ( sname, (d.hdr,) + tuple(gen()) )
def process_stats_pre(self,i):
if (self.fnames and not self.opt.stats_only) or i != 0:

View file

@ -52,6 +52,8 @@ class dummyOpt:
fields = None
stats = None
miner_info = None
header_info = None
full_stats = None
class unit_tests: