www/incubator/podlings/by-age.cgi (116 lines of code) (raw):
#!/usr/bin/env ruby
PAGETITLE = "Incubator Podlings By Age" # Wvisible:incubator historical
$LOAD_PATH.unshift '/srv/whimsy/lib'
require 'nokogiri'
require 'date'
require 'net/http'
require 'wunderbar'
require 'wunderbar/bootstrap'
require 'whimsy/asf'
projects = URI.parse('https://incubator.apache.org/projects/')
table = Nokogiri::HTML(Net::HTTP.get(projects)).at('table')
# Hack to skip processing if cannot get the data
unless table
_text do
_ "Could not fetch and parse http://incubator.apache.org/projects/"
end
exit
end
# extract a list of [podling names, table row]
podlings = table.search('tr').map do |tr|
tds = tr.search('td')
next if tds.empty?
[tds.last.text, tr]
end
# extract sorted list of durations, tally counts of podlings by years
duration = []
by_age = {}
podlings.compact.sort.each do |date, tr|
# NOTE this makes the stats inaccurate if you don't have valid inputs
begin
date_started = Date.parse(date)
rescue ArgumentError
next
end
duration << Date.today - date_started
years = (duration.last / 365.25).to_i
by_age[years] = 1 + (by_age[years] or 0)
end
_html do
_head_ do
_style %{
svg { float: right; width: 8em; height: 8em; padding-right: 5%; }
}
end
_body? do
_whimsy_body(
title: PAGETITLE,
related: {
'https://incubator.apache.org/images/incubator_feather_egg_logo_sm.png' => 'Apache Incubator Egg Logo',
'https://incubator.apache.org/' => 'Apache Incubator Homepage',
'https://incubator.apache.org/projects/index.html' => 'List Of Incubator Podlings'
},
helpblock: -> {
_ 'This shows a sorted list of all active Incubator podlings by age since joining.'
# pie chart
theta = 0
colors = ['0F0', 'FF0', 'F80', 'F50', 'F00', '800']
_svg_ viewBox: '-500 -500 1000 1000' do
_circle r: 480, stroke: "#000", fill: "#000"
by_age.keys.sort.each do |age|
p1 = [Math.sin(theta)*475, -Math.cos(theta)*475].map(&:round).join(',')
theta += Math::PI*2 * by_age[age]/duration.length
p2 = [Math.sin(theta)*475, -Math.cos(theta)*475].map(&:round).join(',')
_path d: "M0,0 L#{p1} A475,475 0 0 1 #{p2} Z",
fill: "##{colors[age]}", title: "#{by_age[age]} PMCs aged " +
"#{age} to #{age+1} year#{'s' if age>0}"
end
end
}
) do
# statistics
if duration.length % 2 == 0
mean = (duration[duration.length/2-1] + duration[duration.length/2])/2
else
mean = duration[duration.length/2]
end
_whimsy_panel_table(
title: 'Incubator Podlings By Age',
helpblock: -> {
_ul do
_li! do
_ "Count: #{duration.length} PPMCs ("
_a 'history', href: 'https://projects.apache.org/'
_ ') ('
_a 'source data', href: 'https://incubator.apache.org/projects/#current'
_ ')'
end
_li "Mean age: #{(mean+0.5).to_i} days"
_li "Median age: #{(duration.reduce(:+)/duration.length + 0.5).to_i} days"
_li "Oldest podling: #{(duration.first).to_i} days"
end
}
) do
_table.table.table_hover.table_striped do
_tr do
table.at('tr').search('th').each do |th|
_th th.text
end
end
podlings.compact.sort.each do |date, tr|
_tr_ do
tr.search('td').each do |td|
a = td.at('a')
if a
_td! {_a a.text, href: (projects + a['href']).to_s}
else
_td td.text
end
end
end
end
end
end
end
end
end