#!/usr/bin/env ruby

require 'time'

def ft(t)
  if t >= 86400
    "%.1fd" % (t / 86400.0)
  elsif t >= 3600
    "%.1fh" % (t / 3600.0)
  elsif t >= 60
    "%.1fm" % (t / 60.0)
  else
    "%.0fs" % t
  end
end

history = []
clients = {}
startup = nil

ARGF.each_line do |line|
  prefix, data = line.split('] ', 2)
  ts = Time.iso8601(prefix[/\d+\S+/]) rescue next
  case data
  when /^start,/
    clients.clear
    history.clear
    startup = ts
  when /^disconnect,/
    if line =~ /peer: ([^,]+)/
      if (connect_ts = clients.delete($1))
        history << (ts - connect_ts).to_f
      else
        warn "Can't find #{$1}"
      end
    else
      warn "Can't parse #{line}"
    end
  when /^connect,/
    if line =~ /peer: ([^,]+)/
      clients[$1] = ts
    else
      warn "Can't parse #{line}"
    end
  end
end

now = Time.new
history += clients.values.map {|v| (now - v).to_f }
history.sort!

exit if history.empty?

min = history.first
max = history.last
med = history[history.length / 2]
avg = history.sum.to_f / history.length
stddev = Math.sqrt(history.sum { |i| (i - avg) ** 2 } / (history.length - 1).to_f)

puts "Uptime: %s" % ft((now - startup))
puts "Current Clients: #{clients.size} of #{history.size} total"
puts("Connect Times: %s - %s, median %s, avg %s, stddev %s" % [ft(min), ft(max), ft(med), ft(avg), ft(stddev)])

log_history = history.group_by {|time| Math.log2(time).ceil }

puts "Breakdown:"
log_history.keys.sort.each do |k|
  a, b = 2 ** (k - 1), 2 ** k
  puts("%16s: %d" % ["#{ft(a)} - #{ft(b)}", log_history[k].size])
end

puts
puts "Current clients:"
max = clients.keys.map(&:length).max
ts = clients.values.map(&:to_s).map(&:length).max

puts("%#{max}s | %#{ts}s | %s" % ["Peer", "Timestamp", "Connection time"])
clients.each do |client, timestamp|
  puts("%#{max}s | %s | %s" % [client, timestamp, ft(now - timestamp)])
end

