#!/usr/bin/env python3 from dataclasses import dataclass from typing import Iterable import json import numpy from . import parse_numberdealers @dataclass class TimeAnalysis: avg: float stdev: float min: float perc5 : float med: float perc95: float max: float midrange: float def analyze_times(numbers: Iterable[parse_numberdealers.Message]) -> TimeAnalysis: times = [] prev_time = None for msg in numbers: if prev_time is not None: times.append((msg.create_at - prev_time) / 1000) prev_time = msg.create_at times.sort() min_ = min(times) max_ = max(times) return TimeAnalysis( avg=numpy.mean(times), stdev=numpy.std(times), min=min_, perc5 =numpy.percentile(times, 5), med=numpy.median(times), perc95=numpy.percentile(times, 95), max=max_, midrange=(min_ + max_) / 2 ) def format_time(total_seconds: float): if total_seconds < 1: return f"{total_seconds:.3f} s" if total_seconds < 10: return f"{total_seconds:.2f} s" if total_seconds < 60: return f"{total_seconds:.1f} s" formatted = None seconds_str = f"{total_seconds:.0f} s" total_minutes, seconds = divmod(total_seconds, 60) total_hours, minutes, = divmod(total_minutes, 60) total_days, hours, = divmod(total_hours, 24) total_years, days, = divmod(total_days, 365) if total_minutes < 60: formatted = f"{total_minutes:.0f} min {seconds:.0f} sec" elif total_hours < 24: formatted = f"{total_hours:.0f} hr {minutes:.0f} min" elif total_days < 365: formatted = f"{total_days:.0f} days {hours:.0f} hr" else: formatted = f"{total_years:.0f} yr {days:.0f} days" assert formatted return f"{seconds_str} ({formatted})" def report_times(numbers): a = analyze_times(numbers) print(f""" μ = {format_time(a.avg)} σ = {format_time(a.stdev)} min = {format_time(a.min)} P5 = {format_time(a.perc5)} median = {format_time(a.med)} P95 = {format_time(a.perc95)} max = {format_time(a.max)}""") def main(): import sys numbers, errors = parse_numberdealers.parse(sys.stdin) if numbers == [] and errors == []: print("No input data") else: if numbers == []: print("No valid number messages!") else: print(f"Checked from {numbers[0].recognized_number} up to {numbers[-1].recognized_number}") report_times(numbers) if __name__ == '__main__': main()