snip2codewfreelandecon
snip2codewfreelandecon
Reputation Top 10%
WFreelandEcon @ Snip2Code
1 Snippet  (736th place)
Published
1 Channel
Created
1 Channel
Following
Nov 1, 2017
Last Visit
Aug 6, 2017
Registered
31 points  (968th place)
Reputation
Junior Autobiographer
Senior Autobiographer

Recent Snippets See all snippets by snip2codewfreelandecon

public by WFreelandEcon created Jun 23, 2017  78  0  1  0

Command line bar chart from JSON data (for GeekTool, et al)

Command line bar chart from JSON data (for GeekTool, et al): barchart.rb
#!/usr/bin/env ruby
# encoding: utf-8
# Brett Terpstra 2013, WTF license <http://www.wtfpl.net/txt/copying/>

# Outputs a vertical bar chart from date-based JSON data
# Requires the JSON rubygem: `[sudo] gem install json`
require 'date'
require 'open-uri'
require 'rubygems'
require 'json'

# Data source URL (sample output at the end of script)
data_url = "http://api.feedpress.it/feeds/..."
# Parent container key for data object
main_container = 'stats'
# Repeated key for date/stats objects
date_container = 'day'
# keys for amounts to collect
total_containers = ['greader','other','direct']

# How many columns to output
columns = 30
# Total height will be determined by min and max valudes
# scaled to max_rows
max_rows = 15

# If "test" is passed as an argument, load test data from end of script
if ARGV[0] == "test" || !data_url || data_url.strip == ""
    input = DATA.read
    columns = 30
    max_rows = 18
    main_container = 'stats'
    date_container = 'day'
    total_containers = ['greader','other','direct']
else
# Otherwise, read data from the data url
    input = open(URI.parse(data_url)).read
end

json = JSON.parse(input)

# Create two arrays, one for dates and one for totals
dates = []
totals = []
# Step through data objects to populate both arrays sequentially
json[main_container].each { |day|
    dates.push(Time.at(day[date_container]).to_datetime.strftime('%m/%d'))
    total = 0
    for item in total_containers
        total += day[item].to_i
    end

    totals.push(total)
}

# Find the highest and lowest values to determine bar heights
max = totals.sort[-1]
min = totals.sort[0]

# Trim data arrays down to the maximum number of columns 
# defined above
dates = dates.reverse[0..columns]
totals = totals.reverse[0..columns]

# Determine number or rows to generate
topline = max_rows
div = max / topline
bottomline = min/div

# Output each row. If the total for the column is greater
# than or equal to the scaled row counter, output a chunk 
# of the bar
topline.times do
    totals.each { |num|
        if num / div > topline
            print "◼ "
        else
            print "  "
        end
    }
    if topline + (max_rows/10).round == bottomline
        puts
        break
    else
        topline -= 1
        puts
    end
end

# Calculate average across all totals
avg = totals.inject(0.0) { |sum, el| sum + el } / totals.size

# Output a legend with today, peak and average
puts "#{dates[0]} - #{dates[-1]} ⇒Today: #{totals[-1]} | Peak: #{max} | Average: #{avg.round}"
puts

# Sample data for testing
__END__

{
    "stats": [
        {
            "day": 1382914800,
            "greader": 10195,
            "other": 4409,
            "direct": 879,
            "newsletter": 0
        },
        {
            "day": 1382824800,
            "greader": 10174,
            "other": 4327,
            "direct": 843,
            "newsletter": 0
        },
        {
            "day": 1382738400,
            "greader": 10172,
            "other": 4173,
            "direct": 861,
            "newsletter": 0
        },
        {
            "day": 1382652000,
            "greader": 10182,
            "other": 4195,
            "direct": 853,
            "newsletter": 0
        },
        {
            "day": 1382565600,
            "greader": 10163,
            "other": 4207,
            "direct": 851,
            "newsletter": 0
        },
        {
            "day": 1382479200,
            "greader": 10135,
            "other": 4206,
            "direct": 839,
            "newsletter": 0
        },
        {
            "day": 1382392800,
            "greader": 8196,
            "other": 4437,
            "direct": 850,
            "newsletter": 0
        },
        {
            "day": 1382306400,
            "greader": 8181,
            "other": 4482,
            "direct": 819,
            "newsletter": 0
        },
        {
            "day": 1382220000,
            "greader": 9968,
            "other": 4413,
            "direct": 858,
            "newsletter": 0
        },
        {
            "day": 1382133600,
            "greader": 9972,
            "other": 4413,
            "direct": 859,
            "newsletter": 0
        },
        {
            "day": 1382047200,
            "greader": 10050,
            "other": 4375,
            "direct": 842,
            "newsletter": 0
        },
        {
            "day": 1381960800,
            "greader": 10056,
            "other": 4310,
            "direct": 821,
            "newsletter": 0
        },
        {
            "day": 1381874400,
            "greader": 10048,
            "other": 4153,
            "direct": 773,
            "newsletter": 0
        },
        {
            "day": 1381788000,
            "greader": 10052,
            "other": 4108,
            "direct": 733,
            "newsletter": 0
        },
        {
            "day": 1381701600,
            "greader": 10055,
            "other": 4228,
            "direct": 701,
            "newsletter": 0
        },
        {
            "day": 1381615200,
            "greader": 10062,
            "other": 4371,
            "direct": 650,
            "newsletter": 0
        },
        {
            "day": 1381528800,
            "greader": 10079,
            "other": 4474,
            "direct": 623,
            "newsletter": 0
        },
        {
            "day": 1381442400,
            "greader": 10112,
            "other": 4590,
            "direct": 584,
            "newsletter": 0
        },
        {
            "day": 1381356000,
            "greader": 10245,
            "other": 4789,
            "direct": 571,
            "newsletter": 0
        },
        {
            "day": 1381269600,
            "greader": 10150,
            "other": 5101,
            "direct": 585,
            "newsletter": 0
        },
        {
            "day": 1381183200,
            "greader": 10155,
            "other": 5255,
            "direct": 583,
            "newsletter": 0
        },
        {
            "day": 1381096800,
            "greader": 10172,
            "other": 5266,
            "direct": 554,
            "newsletter": 0
        },
        {
            "day": 1381010400,
            "greader": 10201,
            "other": 5247,
            "direct": 585,
            "newsletter": 0
        },
        {
            "day": 1380924000,
            "greader": 10232,
            "other": 5285,
            "direct": 582,
            "newsletter": 0
        },
        {
            "day": 1380837600,
            "greader": 10235,
            "other": 5349,
            "direct": 570,
            "newsletter": 0
        },
        {
            "day": 1380751200,
            "greader": 10267,
            "other": 5288,
            "direct": 556,
            "newsletter": 0
        },
        {
            "day": 1380664800,
            "greader": 10308,
            "other": 5042,
            "direct": 540,
            "newsletter": 0
        },
        {
            "day": 1380578400,
            "greader": 10328,
            "other": 4828,
            "direct": 551,
            "newsletter": 0
        },
        {
            "day": 1380492000,
            "greader": 10364,
            "other": 4630,
            "direct": 574,
            "newsletter": 0
        },
        {
            "day": 1380405600,
            "greader": 10350,
            "other": 4479,
            "direct": 597,
            "newsletter": 0
        }
    ],
    "code": 1
}


;