blob: a541fef3c8eae4ed348b5ef701d1d2f55f30612a [file] [log] [blame]
#!/usr/bin/env ruby
PAGETITLE = "Board Meeting Statistics since 2007" # Wvisible:meeting
$LOAD_PATH.unshift '/srv/whimsy/lib'
require 'whimsy/asf'
require 'whimsy/asf/agenda'
require 'whimsy/public'
require 'wunderbar/bootstrap'
require 'json'
require 'set'
BOARD = ASF::SVN['foundation_board']
REPO = 'https://svn.apache.org/repos/private/foundation/board/'
# Hash keys returned by summarize
ERRORS = 'errors'
PEOPLE = 'people'
OFFICERS = 'officers'
PMCS = 'pmcs'
ACTIONS = 'actions'
# produce HTML
_html do
_whimsy_body(
title: PAGETITLE,
related: {
'/board/minutes' => 'Monthly Board Meeting Minutes (categorized)',
'https://www.apache.org/foundation/board/calendar.html' => 'Monthly Board Meeting Minutes (by date)',
'/roster/group/board' => 'Current List of Directors'
},
helpblock: -> {
_ 'This summarizes statistics about monthly board meetings since 2007. Before 2007, the data collected below isn\'t easily parseable or wasn\'t consistently stored in meeting agendas.'
}
) do
datums = JSON.parse(File.read(File.join(BOARD, 'scripts', 'meeting-summary.json')))
_whimsy_panel_table(
title: "Monthly Board Meeting Statistics",
helpblock: -> {
_p do
_ "Some months' minutes are skipped because data can't be easily parsed ("
_a! "see below for list", href: "#skips"
_ "). Most data is generated from public board meeting minutes, however some is "
_strong.text_warning "PRIVATE DATA: "
_ "The numbers of Average Preapprovals and Report Comments Length are private, and must not be shared outside the Membership."
end
_p "Note: the text format of board minutes changed over time. Summaries before 2008 may not accurately reflect actual meeting actions due to parsing issues."
}
) do
_table.table.table_hover.table_striped do
_thead_ do
_tr do
_th 'Date'
_th '# Directors Attend'
_th '# Officers/Guests Attend'
_th '# Special Orders'
_th '# Officer Reports'
_th '# PMC Reports'
_th 'Average Report Text Length'
_th.text_warning 'Average Report Comments Length'
_th.text_warning 'Average # Preapprovals'
_th 'Discussion Items Section Text Length'
end
_tbody do
datums.select{ |k,v| !'stats'.eql?(k) && v.has_key?(PEOPLE) }.each.reverse_each do | month, agenda |
directors, others = agenda[PEOPLE].select{ |id, data| data['attending'] }.partition{ |id, data| 'director'.eql?(data['role']) }
_tr_ do
_td do
file = month + '.txt'
if not File.exist? File.join(BOARD, file)
file = File.join('archived_agendas', file)
end
_a month.sub('board_agenda_', '').gsub('_', '-'),
href: File.join(REPO, file)
end
_td.text_center do
dct = directors.length
if 9 == dct
_ dct
else
_span.text_warning dct
end
end
_td.text_center do
_ others.length
end
_td.text_center do
_ agenda['stats']['specialorders']
end
_td.text_center do
_ agenda[OFFICERS].length
end
_td.text_center do
_ agenda[PMCS].length
end
_td.text_center do
_ agenda['stats']['avgreportlen'].round(0) if agenda['stats'].has_key?('avgreportlen')
end
_td.text_center do
_ agenda['stats']['avgcommentlen'].round(0) if agenda['stats'].has_key?('avgcommentlen')
end
_td.text_center do
_ agenda['stats']['avgapprovals'].round(1) if agenda['stats'].has_key?('avgapprovals')
end
_td.text_center do
_ agenda['stats']['discusstextlen']
end
end
end
end
end
end
end
_h3.skips! 'Note: Some Months Are Skipped'
_p "Some month's agendas aren't easily parsed due to different formatting, and are skipped (i.e. not counted here). Current skip list:"
_ul do
datums.select{ |k,v| v.is_a?(Hash) && v.has_key?(ERRORS) }.each do |month, agenda|
_li do
_a href: File.join(REPO, 'archived_agendas', "#{month}.txt") do
_span.text_warning month
_ " - #{agenda[ERRORS].partition(')').last}"
end
end
end
end
end
end