| class Minutes |
| def self.draft(agenda_txt, minutes_yaml) |
| minutes = File.read(agenda_txt) |
| @@notes = YAML.load_file(minutes_yaml) rescue {} |
| |
| minutes.mreplace(/\n\s1\.\sCall\sto\sorder\n+(.*?:)\n\n |
| ((?:^\s{12}[^\n]*\n+)+\n) |
| (.*?)\n\n\s2\.\sRoll\sCall/mx) do |meeting, number, backup| |
| start = notes('Call to order') || '??:??' |
| meeting.gsub! "is scheduled", "was scheduled" |
| meeting.gsub! "will begin as", "began at" |
| meeting.gsub! "soon thereafter that", "#{start} when" |
| meeting.gsub! "quorum is", "quorum was" |
| meeting.gsub! "will be", "was" |
| meeting.gsub! /:\z/, "." |
| backup.gsub! "will be", "was" |
| [meeting.reflow(4,64), '', backup.reflow(4, 68)] |
| end |
| |
| minutes.sub! /^ +ASF members are welcome to attend board meetings.*?\n\n/m, |
| '' |
| |
| minutes.mreplace(/\n\s2\.\sRoll\sCall\n\n |
| (.*?)\n\n+\s3.\sMinutes |
| /mx) do |rollcall| |
| if notes('Roll Call') |
| notes('Roll Call').gsub(/\r\n/,"\n").gsub(/\n*\Z/,''). |
| gsub(/^([^\n])/, ' \1') |
| else |
| rollcall.gsub(/ \(expected.*?\)/, '') |
| end |
| end |
| |
| minutes.mreplace(/\n\s3\.\sMinutes\sfrom\sprevious\smeetings\n\n |
| (.*?\n\n) |
| \s4\.\sExecutive\sOfficer\sReports |
| /mx) do |prior_minutes| |
| prior_minutes.mreplace(/\n\s+(\w)\.\sThe\smeeting\sof\s(.*?)\n.*?\n |
| (\s{7}\[.*?\])\n\n |
| /mx) do |attach, title, pub_minutes| |
| notes = notes(title) |
| if notes and !notes.empty? |
| notes = 'Approved by General Consent.' if notes == 'approved' |
| notes = 'Tabled.' if notes == 'tabled' |
| [attach, title, notes.reflow(7,62)] |
| else |
| [attach, title, ' Tabled.'] |
| end |
| end |
| end |
| |
| minutes.mreplace(/\n\s4\.\sExecutive\sOfficer\sReports\n |
| (\n.*?\n\n) |
| \s5\.\sAdditional\sOfficer\sReports |
| /mx) do |reports| |
| reports.mreplace(/\n\s\s\s\s(\w)\.\s(.*?)\[.*?\](.*?) |
| ()(?:\n+\s\s\s\s\w\.|\n\n\z) |
| /mx) do |section, title, report, comments| |
| notes = notes(title) |
| if notes and !notes.empty? |
| [section, title, report, "\n\n" + notes.reflow(7,62)] |
| elsif report.strip.empty? |
| [section, title, report, "\n\n No report was submitted."] |
| else |
| [section, title, report, ""] |
| end |
| end |
| end |
| |
| minutes.mreplace(/\n\s5\.\sAdditional\sOfficer\sReports\n |
| (\n.*?\n\n) |
| \s7\.\sSpecial\sOrders |
| /mx) do |reports| |
| reports.mreplace(/ |
| \n\s\s\s\s\s?(\w+)\.\s([^\n]*?) # section, title |
| \[([^\n]+)\]\n\n # owners |
| \s{7}See\s\s?Attachment\s\s?(\w+)[^\n]* # attach (title) |
| (\s+\[\s.*?approved:\s*?.*? # approved |
| \s*comments:.*?\n\s{9}\]) # comments |
| /mx) do |section, title, owners, attach, comments| |
| notes = notes(title.sub('VP of','').strip) |
| if notes and !notes.empty? |
| comments = "\n\n" + notes.to_s.reflow(7,62) |
| else |
| comments = '' |
| end |
| [section, title, owners, attach, comments] |
| end |
| end |
| |
| minutes.mreplace(/\n\s7\.\sSpecial\sOrders\n |
| (.*?) |
| \n\s8\.\sDiscussion\sItems |
| /mx) do |reports| |
| break if reports.empty? |
| reports.mreplace(/\n\s\s\s\s(\w)\.(.*?)\n(.*?)()\s+(?:\s*\n\s\s\s\s\w\.|\z) |
| /mx) do |section, title, order, comments| |
| order.sub! /\n \[.*?\n +\]\n/m, '' |
| notes = notes(title.strip) |
| if !notes or notes.empty? or notes.strip == 'tabled' |
| notes = "was tabled." |
| elsif notes == 'unanimous' |
| notes = "was approved by Unanimous Vote of the directors present." |
| end |
| notes = "Special Order 7#{section}, #{title}, " + notes |
| order += "\n" unless order =~ /\n\Z/ |
| [section, title, order, "\n" + notes.reflow(7,62)] |
| end |
| end |
| |
| minutes.mreplace(/\n\s8\.\sDiscussion\sItems |
| (.*?) |
| \n\s9\.\s.*Action\sItems |
| /mx) do |reports| |
| break unless reports =~ /\n\s{3,5}[A-Z]\.\s/ |
| reports.mreplace(/\n\s\s\s\s(\w)\.(.*?)\n(.*?)()\s+(?:\s*\n\s\s\s\s\w\.|\z) |
| /mx) do |section, title, item, comments| |
| item.sub! /\n \[.*?\n +\]\n/m, '' |
| item += "\n" unless item =~ /\n\Z/ |
| notes = notes(title.strip) || '' |
| [section, title, item, "\n" + notes.reflow(7,70)] |
| end |
| end |
| |
| minutes.mreplace(/ |
| ^((?:\s[89]|1\d)\.)\s |
| (.*?)\n |
| (.*?) |
| (?=\n[\s1]\d\.|\n===) |
| /mx) do |attach, title, comments| |
| notes = notes(title) |
| |
| if notes and !notes.empty? |
| if title =~ /Action Items/ |
| comments = notes.gsub(/\r\n/,"\n").gsub(/^/,' ') |
| elsif title == 'Adjournment' |
| comments = "\n Adjourned at #{notes} UTC\n" |
| else |
| comments += "\n" + notes.to_s.reflow(4,68) + "\n" |
| end |
| elsif title == 'Adjournment' |
| comments = "\n Adjourned at ??:?? UTC\n" |
| end |
| [attach, title, comments] |
| end |
| |
| missing = minutes.scan(/^Attachment (\w\w?):.*\s*\n---/).flatten |
| missing.each do |attach| |
| minutes.sub! /^(\s+)See Attachment #{attach}$/, '\1No report was submitted.' |
| end |
| |
| minutes.sub! 'Minutes (in Subversion) are found under the URL:', |
| 'Published minutes can be found at:' |
| |
| minutes.sub! ASF::SVN.svnpath!('foundation_board'), |
| 'http://www.apache.org/foundation/board/calendar.html' |
| |
| minutes.sub!(/ \d\. Committee Reports.*?\n\s+A\./m) do |heading| |
| heading.sub('reports require further', 'reports required further') |
| end |
| |
| minutes[/^() 5. Additional Officer Reports/,1] = |
| " Executive officer reports approved as submitted by General Consent.\n\n" |
| |
| minutes[/^() 6. Committee Reports/,1] = |
| " Additional officer reports approved as submitted by General Consent.\n\n" |
| |
| minutes[/^() 7. Special Orders/,1] = |
| " Committee reports approved as submitted by General Consent.\n\n" |
| |
| minutes.sub! 'Meeting Agenda', 'Meeting Minutes' |
| minutes.sub! /^End of agenda/, 'End of minutes' |
| |
| # remove block of lines (and preceding whitespace including blank lines) |
| # where the first line starts with <private> and the last line ends with |
| # </private>. |
| minutes.gsub! /^\s*<private>.*?<\/private>\s*?\n/mi, '' |
| |
| # remove inline <private>...</private> sections (and preceding spaces |
| # and tabs) where the <private> and </private> are on the same line. |
| minutes.gsub! /[ \t]*<private>.*?<\/private>/i, '' |
| |
| minutes.gsub! /\n( *)\[ comments:.*?\n\1 ? ?\]/m, '' |
| |
| minutes |
| end |
| |
| def self.notes(index) |
| index = index.strip |
| return @@notes[index] if @@notes[index] |
| |
| index.sub! /^Report from the VP of /, '' |
| index.sub! /^Report from the /, '' |
| index.sub! /^Status report for the /, '' |
| index.sub! /^Resolution to /, '' |
| index.sub! /^Apache /, '' |
| index.sub! /\sTeam$/, '' |
| index.sub! /\sCommittee$/, '' |
| index.sub! /\sthe\s/, ' ' |
| index.sub! /\sApache\s/, ' ' |
| index.sub! /\sCommittee\s/, ' ' |
| index.sub! /\sProject$/, '' |
| index.sub! /\sPMC$/, '' |
| index.sub! /\sProject\s/, ' ' |
| |
| @@notes[index] |
| end |
| end |