diff --git a/mmgen/node_tools/BlocksInfo.py b/mmgen/node_tools/BlocksInfo.py index b0fb1a2..6778e04 100644 --- a/mmgen/node_tools/BlocksInfo.py +++ b/mmgen/node_tools/BlocksInfo.py @@ -405,15 +405,22 @@ class BlocksInfo: def process_stats(self,sname): return self.output_stats(getattr(self,f'create_{sname}_stats')(),sname) + def fmt_stat_item(self,fs,s): + return fs.format(s) if type(fs) == str else fs(s) + async def output_stats(self,res,sname): + def gen(data): for d in data: if len(d) == 2: - yield (indent+d[0]).format(**d[1]) - elif len(d) == 3: - yield (indent+d[0]).format(d[2]) - else: + yield (indent+d[0]).format(**{k:self.fmt_stat_item(*v) for k,v in d[1].items()}) + elif len(d) == 4: + yield (indent+d[0]).format(self.fmt_stat_item(d[2],d[3])) + elif type(d) == str: yield d + else: + assert False, f'{d}: invalid stats data' + foo,data = await res indent = '' if sname in self.noindent_stats else ' ' Msg('\n'.join(gen(data))) @@ -428,22 +435,22 @@ class BlocksInfo: yield 'Range Statistics:' yield ( 'Range: {start}-{end} ({range} blocks [{elapsed}]%s)' % step_disp, { - 'start': self.hdrs[0]['height'], - 'end': self.hdrs[-1]['height'], - 'range': self.hdrs[-1]['height'] - self.hdrs[0]['height'] + 1, # includes Genesis Block - 'elapsed': self.t_fmt(elapsed), - 'nBlocks': total_blks, - 'step': self.step, + 'start': ('{}', self.hdrs[0]['height']), + 'end': ('{}', self.hdrs[-1]['height']), + 'range': ('{}', self.hdrs[-1]['height'] - self.hdrs[0]['height'] + 1), + 'elapsed': (self.t_fmt, elapsed), + 'nBlocks': ('{}', total_blks), + 'step': ('{}', self.step), } ) if elapsed: avg_bdi = int(elapsed / nblocks) if 'bs' in self.deps: rate = (self.total_bytes / 10000) / (self.total_solve_time / 36) - yield ( 'Avg size: {} bytes', 'avg_size', self.total_bytes//total_blks ) - yield ( 'Avg weight: {} bytes', 'avg_weight', self.total_weight//total_blks ) - yield ( 'MB/hr: {}', 'mb_per_hour', f'{rate:0.4f}' ) - yield ('Avg BDI: {} min', 'avg_bdi', f'{avg_bdi/60:.2f}') + yield ( 'Avg size: {} bytes', 'avg_size', '{}', self.total_bytes//total_blks ) + yield ( 'Avg weight: {} bytes', 'avg_weight', '{}', self.total_weight//total_blks ) + yield ( 'MB/hr: {}', 'mb_per_hour', '{:0.4f}', rate ) + yield ('Avg BDI: {} min', 'avg_bdi', '{:.2f}', avg_bdi/60) return ( 'range', gen() ) @@ -474,22 +481,22 @@ class BlocksInfo: return ( 'difficulty', ( 'Difficulty Statistics:', - ('Current height: {}', 'chain_tip', self.tip), + ('Current height: {}', 'chain_tip', '{}', self.tip), ('Next diff adjust: {next_diff_adjust} (in {blks_remaining} block%s [{time_remaining}])' % suf(rem), { - 'next_diff_adjust': self.tip + rem, - 'blks_remaining': rem, - 'time_remaining': self.t_fmt(rem * bdi_avg) + 'next_diff_adjust': ('{}', self.tip + rem), + 'blks_remaining': ('{}', rem), + 'time_remaining': (self.t_fmt, rem * bdi_avg) } ), ('Avg BDI: {avg_bdi} min (over {avg_bdi_blks}-block period)', { - 'avg_bdi': f'{bdi_disp/60:.2f}', - 'avg_bdi_blks': max(rel,bdi_avg_blks) + 'avg_bdi': ('{:.2f}', bdi_disp/60), + 'avg_bdi_blks': ('{}', max(rel,bdi_avg_blks)) } ), - ('Cur difficulty: {}', 'cur_diff', f'{tip_hdr["difficulty"]:.2e}'), - ('Est. diff adjust: {}%', 'est_diff_adjust_pct', f'{((600 / bdi) - 1) * 100:+.2f}'), + ('Cur difficulty: {}', 'cur_diff', '{:.2e}', tip_hdr['difficulty']), + ('Est. diff adjust: {}%', 'est_diff_adjust_pct', '{:+.2f}', ((600 / bdi) - 1) * 100), )) async def create_avg_stats(self): @@ -497,11 +504,11 @@ class BlocksInfo: def gen(): for field in self.fnames: if field in skip: - yield ( field, '' ) + yield ( field, ('{}','') ) else: ret = sum(getattr(block,field) for block in self.res) // len(self.res) vn = self.fields[field].varname - yield ( field, (self.fmt_funcs[vn](ret) if vn in self.fmt_funcs else ret) ) + yield ( field, ( (self.fmt_funcs[vn] if vn in self.fmt_funcs else '{}'), ret )) fs = ''.join(self.gen_fs(self.fnames,fill=skip,add_name=True)).strip() return ('averages', ('Averages:', (fs, dict(gen())) )) @@ -547,6 +554,7 @@ class JSONBlocksInfo(BlocksInfo): super().__init__(cmd_args,opt,rpc) if opt.json_raw: self.output_block = self.output_block_raw + self.fmt_stat_item = self.fmt_stat_item_raw Msg_r('{') async def process_blocks(self): @@ -566,14 +574,21 @@ class JSONBlocksInfo(BlocksInfo): def print_header(self): pass + def fmt_stat_item_raw(self,fs,s): + return s + async def output_stats(self,res,sname): + def gen(data): for d in data: if len(d) == 2: for k,v in d[1].items(): - yield (k,v) - elif len(d) == 3: - yield (d[1],d[2]) + yield (k,self.fmt_stat_item(*v)) + elif len(d) == 4: + yield (d[1],self.fmt_stat_item(d[2],d[3])) + elif type(d) != str: + assert False, f'{d}: invalid stats data' + varname,data = await res Msg_r(', "{}_data": {}'.format( varname, json.dumps(dict(gen(data)),cls=json_encoder) ))