This is an automated email from the ASF dual-hosted git repository.

rubys pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/whimsy.git


The following commit(s) were added to refs/heads/master by this push:
     new 51136af  move meeting-util to lib/whimsy
51136af is described below

commit 51136af09f206a954692464b4c392771f57f2a79
Author: Sam Ruby <[email protected]>
AuthorDate: Wed Mar 23 15:07:44 2022 -0400

    move meeting-util to lib/whimsy
---
 lib/whimsy/asf/meeting-util.rb    | 223 ++++++++++++++++++++++++++++++++++++++
 www/members/board-nominations.cgi |   4 +-
 www/members/inactive.cgi          |  10 +-
 www/members/list-traffic.cgi      |   4 +-
 www/members/meeting-util.rb       | 221 -------------------------------------
 www/members/meeting.cgi           |  26 ++---
 www/members/nominations.cgi       |   4 +-
 www/members/non-participants.cgi  |  10 +-
 www/members/proxy.cgi             |  10 +-
 9 files changed, 257 insertions(+), 255 deletions(-)

diff --git a/lib/whimsy/asf/meeting-util.rb b/lib/whimsy/asf/meeting-util.rb
new file mode 100644
index 0000000..3376875
--- /dev/null
+++ b/lib/whimsy/asf/meeting-util.rb
@@ -0,0 +1,223 @@
+#!/usr/bin/env ruby
+# Utility methods and structs related to Member's Meetings
+# NOTE: Assumes 21st century '2*'
+$LOAD_PATH.unshift '/srv/whimsy/lib' if __FILE__ == $PROGRAM_NAME
+require 'whimsy/asf'
+require 'json'
+
+module ASF
+  class MeetingUtil
+    RECORDS = ASF::SVN.svnurl!('Meetings')
+    MEETING_FILES = { # Filename in meeting dir, pathname to another deployed 
tool, or URL
+      'README.txt' => 'README For Meeting Process And Roll Call',
+      'nomination_of_board.txt' => 'How To Nominate Someone For Board',
+      'nomination_of_members.txt' => 'How To Nominate A New Member',
+      '/members/proxy.cgi' => 'How To Submit A Proxy/Check Your Proxies',
+      'https://www.apache.org/foundation/governance/meetings' => 'How Voting 
Via Email Works',
+      'agenda.txt' => 'Official Meeting Agenda',
+      'board_ballot.txt' => 'Official Board Candidate Ballots',
+      'nominated-members.txt' => 'Official New Member Nominees/Seconds',
+      'proxies' => 'Official List Of Meeting Proxies',
+      'record' => 'Official List Of Voting Members',
+      'attend' => 'Official List Of Meeting Attendees (afterwards)',
+      'voter-tally' => 'Official List Of Who Voted (afterwards)',
+      'raw_board_votes.txt' => 'Official List Of Votes For Board (afterwards)',
+      'raw-irc-log' => 'ASFBot logs all postings on #asfmembers during meeting'
+    }
+
+    # Calculate how many members required to attend first half for quorum
+    def self.calculate_quorum(mtg_dir)
+      begin
+        begin
+          num_members = File.read(File.join(mtg_dir, 'record')).each_line.count
+        rescue
+          num_members = ASF::Member.list.length - ASF::Member.status.length
+        end
+        quorum_need = (num_members + 2) / 3
+        num_proxies = Dir[File.join(mtg_dir, 'proxies-received', '*')].count
+        attend_irc = quorum_need - num_proxies
+      rescue StandardError => e
+        # Ensure we can't break rest of script
+        puts "ERROR: #{e}"
+        return 0, 0, 0, 0
+      end
+      return num_members, quorum_need, num_proxies, attend_irc
+    end
+
+    # get list of proxy volunteers
+    def self.getVolunteers(mtg_dir)
+      lines = IO.read(File.join(mtg_dir, 'proxies'))
+      # split by ---- underlines, then by blank lines; pick second para and 
drop leading spaces
+      lines.split(/^-----------/)[1].split(/\n\n/)[1].scan(/^\ 
+(\S.*$)/).flatten
+    end
+    # Get info about current users's proxying
+    # @return "help text", ["id | name (proxy)", ...] if they are a proxy for 
other(s)
+    # @return "You have already submitted a proxy form" to someone else
+    # @return nil otherwise
+    def self.is_user_proxied(mtg_dir, id)
+      user = ASF::Person.find(id)
+      lines = IO.read(File.join(mtg_dir, 'proxies'))
+      proxylist = lines.scan(/\s\s(.{25})(.*?)\((.*?)\)/) # [["Shane Curcuru   
 ", "David Fisher ", "wave"], ...]
+      help = nil
+      copypasta = [] # theiravailid | Their Name in Rolls (proxy)
+      begin
+        proxylist.each do |arr|
+          if user.cn == arr[0].strip
+            copypasta << "#{arr[2].ljust(12)} | #{arr[1].strip} (proxy)"
+          elsif user.id == arr[2]
+            help = "NOTE: You have already submitted a proxy form for 
#{arr[0].strip} to mark your attendance (be sure they know to mark you at Roll 
Call)! "
+          end
+        end
+      rescue StandardError => e
+        (help ||= "") << "ERROR, could not read LDAP, proxy data may not be 
correct: #{e.message}"
+      end
+      if copypasta.empty?
+        return help
+      else
+        (help ||= "") << "During the meeting, to mark your proxies' 
attendance, AFTER the 2. Roll Call is called, you may copy/paste the below 
lines to mark your and your proxies attendance."
+        copypasta.unshift("#{user.id.ljust(12)} | #{user.cn}")
+        return help, copypasta
+      end
+    end
+
+    # Get the latest available Meetings dir
+    def self.get_latest(mtg_root)
+      return Dir[File.join(mtg_root, '2*')].max
+    end
+    # Get the second latest available Meetings dir
+    def self.get_previous(mtg_root)
+      return Dir[File.join(mtg_root, '2*')].sort[-2]
+    end
+    # Read attendance.json file
+    def self.get_attendance(mtg_root)
+      return JSON.parse(IO.read(File.join(mtg_root, 'attendance.json')))
+    end
+
+    # Parse all memapp-received.txt files to get better set of names
+    # @see whimsy/www/members/attendance-xcheck.cgi
+    def self.read_memapps(dir)
+      memapps = Hash.new('unknown')
+      Dir[File.join(dir, '*', 'memapp-received.txt')].each do |received|
+        meeting = File.basename(File.dirname(received))
+        next if meeting.include? 'template'
+        text = File.read(received)
+        list = text.scan(/(.+)\s<(.*)@.*>.*Yes/i)
+        if list.empty?
+          list = text.scan(/^(?:no\s*)*(?:yes\s+)+(\w\S*)\s+(.*)\s*/)
+        else
+          # reverse order of id name type files
+          list.each {|a| a[0], a[1] = a[1], a[0] }
+        end
+        list.each { |itm| memapps[itm[1].strip] = [itm[0], meeting] }
+      end
+      return memapps
+    end
+
+    # Annotate the attendance.json file with cohorts by id
+    # This allows easy use by other tools
+    def self.annotate_attendance(dir)
+      attendance = JSON.parse(IO.read(File.join(dir, 'attendance.json')))
+      memapps = read_memapps(dir)
+      iclas = ASF::ICLA.preload
+      memapp_map = JSON.parse(IO.read(File.join(dir, 'memapp-map.json')))
+      attendance['cohorts'] = {}
+      attendance['unmatched'] = []
+      attendance['members'].each do |date, ary|
+        next unless date.start_with? '20' # exclude 'active'
+        ary.each do |nam|
+          found = iclas.select{|i| i.icla.legal_name == nam}
+          found = iclas.select{|i| i.icla.name == nam} if found.empty?
+          if found.empty?
+            if memapps.has_key?(nam)
+              attendance['cohorts'][memapps[nam][0]] = date
+            elsif memapp_map.has_key?(nam)
+              attendance['cohorts'][memapp_map[nam]] = date
+            else
+              attendance['unmatched'] << nam
+            end
+          else
+            attendance['cohorts'][found[0].icla.id] = date
+          end
+        end
+      end
+      File.open(File.join(dir, 'attendance-cohorts.json'), 'w') do |f| # Do 
not overwrite blindly; manual copy if desired
+        f.puts JSON.pretty_generate(attendance)
+      end
+    end
+
+    # Precompute matrix and dates from attendance
+    def self.get_attend_matrices(dir)
+      attendance = MeetingUtil.get_attendance(dir)
+
+      # extract and format dates
+      dates = attendance['dates'].sort.
+        map {|date| Date.parse(date).strftime('%Y-%b')}
+
+      # compute mappings of names to ids
+      members = ASF::Member.list
+      active = Hash[members.select {|_id, data| not data['status']}]
+      nameMap = Hash[members.map {|id, data| [id, data[:name]]}]
+      idMap = Hash[nameMap.to_a.map(&:reverse)]
+
+      # analyze attendance
+      matrix = attendance['matrix'].map do |name, meetings|
+        id = idMap[name]
+        next unless id and active[id]
+
+        # exclude 'active entry'
+        data = meetings.select {|key, value| key.start_with? '20'}.
+          sort.reverse.map(&:last)
+
+        first = data.length
+        missed = (data.index {|datum| datum != '-'} || data.length)
+
+        [id, name, first, missed]
+      end
+
+      return attendance, matrix.compact, dates, nameMap
+    end
+
+    # return a function to determine the current status of a member by id
+    def self.current_status(cur_mtg_dir)
+      proxies = Dir["#{cur_mtg_dir}/proxies-received/*"].
+        map {|file| File.basename(file, '.*')}
+
+      _tag,emeritus = ASF::SVN.getlisting('emeritus-requests-received')
+      emeritus.map! {|file| File.basename(file, '.*')}
+
+      lambda do |id|
+        if emeritus.include? id
+          'Emeritus request received'
+        elsif proxies.include? id
+          'Proxy received'
+        else
+          'No response'
+        end
+      end
+    end
+
+    # return the current status of all inactive members
+    def self.tracker(meetingsMissed)
+      cur_mtg_dir = MeetingUtil.get_latest(ASF::SVN['Meetings'])
+      current_status = self.current_status(cur_mtg_dir)
+
+      _attendance, matrix, _dates, _nameMap = 
MeetingUtil.get_attend_matrices(MEETINGS)
+      inactive = matrix.select do |id, _name, _first, missed|
+        id and missed >= meetingsMissed
+      end
+    
+      Hash[inactive.map {|id, name, _first, missed|
+        [id, {'name' => name, 'missed' => missed, 'status' => 
current_status[id]}]
+        }]
+    end
+  end
+end
+
+# ## ### #### ##### ######
+# Main method for command line use
+if __FILE__ == $PROGRAM_NAME
+  dir = ARGV[0]
+  dir ||= '.'
+  ASF::MeetingUtil.annotate_attendance(dir)
+  puts "DONE, check attendance-cohorts.json"
+end
diff --git a/www/members/board-nominations.cgi 
b/www/members/board-nominations.cgi
index f9b7529..b6742e3 100755
--- a/www/members/board-nominations.cgi
+++ b/www/members/board-nominations.cgi
@@ -7,7 +7,7 @@ require 'mail'
 require 'wunderbar/bootstrap'
 require 'whimsy/asf'
 require 'whimsy/asf/member-files'
-require_relative 'meeting-util'
+require 'whimsy/asf/meeting-util'
 
 # link to members private-arch
 MBOX = 'https://mail-search.apache.org/members/private-arch/members/'
@@ -92,7 +92,7 @@ _html do
         _ 'Entries are highlighted if they are not present in both lists.'
       }
     ) do
-      cur_mtg_dir = File.basename(MeetingUtil.get_latest(MEETINGS))
+      cur_mtg_dir = File.basename(ASF::MeetingUtil.get_latest(MEETINGS))
       nominations, emails = setup_data
       _div.flexbox do
         _div.flexitem do
diff --git a/www/members/inactive.cgi b/www/members/inactive.cgi
index 276c856..01b32de 100755
--- a/www/members/inactive.cgi
+++ b/www/members/inactive.cgi
@@ -7,7 +7,7 @@ require 'wunderbar/bootstrap'
 require 'date'
 require 'json'
 require 'tmpdir'
-require_relative 'meeting-util'
+require 'whimsy/asf/meeting-util'
 
 # produce HTML
 _html do
@@ -29,8 +29,8 @@ _html do
   end
   _body? do
     MEETINGS = ASF::SVN['Meetings']
-    attendance = MeetingUtil.get_attendance(MEETINGS)
-    latest = MeetingUtil.get_latest(MEETINGS)
+    attendance = ASF::MeetingUtil.get_attendance(MEETINGS)
+    latest = ASF::MeetingUtil.get_latest(MEETINGS)
 
     @user ||= $USER
     @meetingsMissed = (@meetingsMissed || 3).to_i
@@ -62,7 +62,7 @@ _html do
     begin
       tracker = JSON.parse(IO.read(File.join(latest, 'non-participants.json')))
     rescue Errno::ENOENT => err
-      tracker = MeetingUtil.tracker(@meetingsMissed)
+      tracker = ASF::MeetingUtil.tracker(@meetingsMissed)
     end
 
     # determine user's name as found in members.txt
@@ -84,7 +84,7 @@ _html do
         '/members/proxy' => 'Assign A Proxy For Next Meeting',
         '/members/non-participants' => 'Members Not Participating',
         ASF::SVN.svnpath!('foundation','members.txt') => 'See Official 
Members.txt File',
-        MeetingUtil::RECORDS => 'Official Past Meeting Records'
+        ASF::MeetingUtil::RECORDS => 'Official Past Meeting Records'
       },
       helpblock: -> {
         _p "This page shows your personal attendance record at past Member's 
meetings, as of meeting #{latest}."
diff --git a/www/members/list-traffic.cgi b/www/members/list-traffic.cgi
index 59024c8..6fc9519 100755
--- a/www/members/list-traffic.cgi
+++ b/www/members/list-traffic.cgi
@@ -10,7 +10,7 @@ require 'whimsy/asf/agenda'
 require 'date'
 require 'mail'
 require '../../tools/mboxhdr2csv.rb'
-require_relative 'meeting-util'
+require 'whimsy/asf/meeting-util'
 
 user = ASF::Person.new($USER)
 unless user.asf_member?
@@ -180,7 +180,7 @@ _html do
       }
     ) do
       months = Dir["#{SRV_MAIL}/*"].map {|path| 
File.basename(path)}.grep(/^\d+$/)
-      attendance = MeetingUtil.get_attendance(ASF::SVN['Meetings'])
+      attendance = ASF::MeetingUtil.get_attendance(ASF::SVN['Meetings'])
       style_cohorts(attendance) if attendance.has_key?('cohorts') # Allow to 
fail silently if data missing
       # if ENV['QUERY_STRING'].include? 'Clear-Cache-No-Really'
       #   _p do # Danger, Will Robinson!
diff --git a/www/members/meeting-util.rb b/www/members/meeting-util.rb
deleted file mode 100644
index da6eae5..0000000
--- a/www/members/meeting-util.rb
+++ /dev/null
@@ -1,221 +0,0 @@
-#!/usr/bin/env ruby
-# Utility methods and structs related to Member's Meetings
-# NOTE: Assumes 21st century '2*'
-$LOAD_PATH.unshift '/srv/whimsy/lib'
-require 'whimsy/asf'
-require 'json'
-
-class MeetingUtil
-  RECORDS = ASF::SVN.svnurl!('Meetings')
-  MEETING_FILES = { # Filename in meeting dir, pathname to another deployed 
tool, or URL
-    'README.txt' => 'README For Meeting Process And Roll Call',
-    'nomination_of_board.txt' => 'How To Nominate Someone For Board',
-    'nomination_of_members.txt' => 'How To Nominate A New Member',
-    '/members/proxy.cgi' => 'How To Submit A Proxy/Check Your Proxies',
-    'https://www.apache.org/foundation/governance/meetings' => 'How Voting Via 
Email Works',
-    'agenda.txt' => 'Official Meeting Agenda',
-    'board_ballot.txt' => 'Official Board Candidate Ballots',
-    'nominated-members.txt' => 'Official New Member Nominees/Seconds',
-    'proxies' => 'Official List Of Meeting Proxies',
-    'record' => 'Official List Of Voting Members',
-    'attend' => 'Official List Of Meeting Attendees (afterwards)',
-    'voter-tally' => 'Official List Of Who Voted (afterwards)',
-    'raw_board_votes.txt' => 'Official List Of Votes For Board (afterwards)',
-    'raw-irc-log' => 'ASFBot logs all postings on #asfmembers during meeting'
-  }
-
-  # Calculate how many members required to attend first half for quorum
-  def self.calculate_quorum(mtg_dir)
-    begin
-      begin
-        num_members = File.read(File.join(mtg_dir, 'record')).each_line.count
-      rescue
-        num_members = ASF::Member.list.length - ASF::Member.status.length
-      end
-      quorum_need = (num_members + 2) / 3
-      num_proxies = Dir[File.join(mtg_dir, 'proxies-received', '*')].count
-      attend_irc = quorum_need - num_proxies
-    rescue StandardError => e
-      # Ensure we can't break rest of script
-      puts "ERROR: #{e}"
-      return 0, 0, 0, 0
-    end
-    return num_members, quorum_need, num_proxies, attend_irc
-  end
-
-  # get list of proxy volunteers
-  def self.getVolunteers(mtg_dir)
-    lines = IO.read(File.join(mtg_dir, 'proxies'))
-    # split by ---- underlines, then by blank lines; pick second para and drop 
leading spaces
-    lines.split(/^-----------/)[1].split(/\n\n/)[1].scan(/^\ +(\S.*$)/).flatten
-  end
-  # Get info about current users's proxying
-  # @return "help text", ["id | name (proxy)", ...] if they are a proxy for 
other(s)
-  # @return "You have already submitted a proxy form" to someone else
-  # @return nil otherwise
-  def self.is_user_proxied(mtg_dir, id)
-    user = ASF::Person.find(id)
-    lines = IO.read(File.join(mtg_dir, 'proxies'))
-    proxylist = lines.scan(/\s\s(.{25})(.*?)\((.*?)\)/) # [["Shane Curcuru    
", "David Fisher ", "wave"], ...]
-    help = nil
-    copypasta = [] # theiravailid | Their Name in Rolls (proxy)
-    begin
-      proxylist.each do |arr|
-        if user.cn == arr[0].strip
-          copypasta << "#{arr[2].ljust(12)} | #{arr[1].strip} (proxy)"
-        elsif user.id == arr[2]
-          help = "NOTE: You have already submitted a proxy form for 
#{arr[0].strip} to mark your attendance (be sure they know to mark you at Roll 
Call)! "
-        end
-      end
-    rescue StandardError => e
-      (help ||= "") << "ERROR, could not read LDAP, proxy data may not be 
correct: #{e.message}"
-    end
-    if copypasta.empty?
-      return help
-    else
-      (help ||= "") << "During the meeting, to mark your proxies' attendance, 
AFTER the 2. Roll Call is called, you may copy/paste the below lines to mark 
your and your proxies attendance."
-      copypasta.unshift("#{user.id.ljust(12)} | #{user.cn}")
-      return help, copypasta
-    end
-  end
-
-  # Get the latest available Meetings dir
-  def self.get_latest(mtg_root)
-    return Dir[File.join(mtg_root, '2*')].max
-  end
-  # Get the second latest available Meetings dir
-  def self.get_previous(mtg_root)
-    return Dir[File.join(mtg_root, '2*')].sort[-2]
-  end
-  # Read attendance.json file
-  def self.get_attendance(mtg_root)
-    return JSON.parse(IO.read(File.join(mtg_root, 'attendance.json')))
-  end
-
-  # Parse all memapp-received.txt files to get better set of names
-  # @see whimsy/www/members/attendance-xcheck.cgi
-  def self.read_memapps(dir)
-    memapps = Hash.new('unknown')
-    Dir[File.join(dir, '*', 'memapp-received.txt')].each do |received|
-      meeting = File.basename(File.dirname(received))
-      next if meeting.include? 'template'
-      text = File.read(received)
-      list = text.scan(/(.+)\s<(.*)@.*>.*Yes/i)
-      if list.empty?
-        list = text.scan(/^(?:no\s*)*(?:yes\s+)+(\w\S*)\s+(.*)\s*/)
-      else
-        # reverse order of id name type files
-        list.each {|a| a[0], a[1] = a[1], a[0] }
-      end
-      list.each { |itm| memapps[itm[1].strip] = [itm[0], meeting] }
-    end
-    return memapps
-  end
-
-  # Annotate the attendance.json file with cohorts by id
-  # This allows easy use by other tools
-  def self.annotate_attendance(dir)
-    attendance = JSON.parse(IO.read(File.join(dir, 'attendance.json')))
-    memapps = read_memapps(dir)
-    iclas = ASF::ICLA.preload
-    memapp_map = JSON.parse(IO.read(File.join(dir, 'memapp-map.json')))
-    attendance['cohorts'] = {}
-    attendance['unmatched'] = []
-    attendance['members'].each do |date, ary|
-      next unless date.start_with? '20' # exclude 'active'
-      ary.each do |nam|
-        found = iclas.select{|i| i.icla.legal_name == nam}
-        found = iclas.select{|i| i.icla.name == nam} if found.empty?
-        if found.empty?
-          if memapps.has_key?(nam)
-            attendance['cohorts'][memapps[nam][0]] = date
-          elsif memapp_map.has_key?(nam)
-            attendance['cohorts'][memapp_map[nam]] = date
-          else
-            attendance['unmatched'] << nam
-          end
-        else
-          attendance['cohorts'][found[0].icla.id] = date
-        end
-      end
-    end
-    File.open(File.join(dir, 'attendance-cohorts.json'), 'w') do |f| # Do not 
overwrite blindly; manual copy if desired
-      f.puts JSON.pretty_generate(attendance)
-    end
-  end
-
-  # Precompute matrix and dates from attendance
-  def self.get_attend_matrices(dir)
-    attendance = MeetingUtil.get_attendance(dir)
-
-    # extract and format dates
-    dates = attendance['dates'].sort.
-      map {|date| Date.parse(date).strftime('%Y-%b')}
-
-    # compute mappings of names to ids
-    members = ASF::Member.list
-    active = Hash[members.select {|_id, data| not data['status']}]
-    nameMap = Hash[members.map {|id, data| [id, data[:name]]}]
-    idMap = Hash[nameMap.to_a.map(&:reverse)]
-
-    # analyze attendance
-    matrix = attendance['matrix'].map do |name, meetings|
-      id = idMap[name]
-      next unless id and active[id]
-
-      # exclude 'active entry'
-      data = meetings.select {|key, value| key.start_with? '20'}.
-        sort.reverse.map(&:last)
-
-      first = data.length
-      missed = (data.index {|datum| datum != '-'} || data.length)
-
-      [id, name, first, missed]
-    end
-
-    return attendance, matrix.compact, dates, nameMap
-  end
-
-  # return a function to determine the current status of a member by id
-  def self.current_status(cur_mtg_dir)
-    proxies = Dir["#{cur_mtg_dir}/proxies-received/*"].
-      map {|file| File.basename(file, '.*')}
-
-    _tag,emeritus = ASF::SVN.getlisting('emeritus-requests-received')
-    emeritus.map! {|file| File.basename(file, '.*')}
-
-    lambda do |id|
-      if emeritus.include? id
-        'Emeritus request received'
-      elsif proxies.include? id
-        'Proxy received'
-      else
-        'No response'
-      end
-    end
-  end
-
-  # return the current status of all inactive members
-  def self.tracker(meetingsMissed)
-    cur_mtg_dir = MeetingUtil.get_latest(ASF::SVN['Meetings'])
-    current_status = self.current_status(cur_mtg_dir)
-
-    _attendance, matrix, _dates, _nameMap = 
MeetingUtil.get_attend_matrices(MEETINGS)
-    inactive = matrix.select do |id, _name, _first, missed|
-      id and missed >= meetingsMissed
-    end
-  
-    Hash[inactive.map {|id, name, _first, missed|
-      [id, {'name' => name, 'missed' => missed, 'status' => 
current_status[id]}]
-      }]
-  end
-end
-
-# ## ### #### ##### ######
-# Main method for command line use
-if __FILE__ == $PROGRAM_NAME
-  dir = ARGV[0]
-  dir ||= '.'
-  MeetingUtil.annotate_attendance(dir)
-  puts "DONE, check attendance-cohorts.json"
-end
diff --git a/www/members/meeting.cgi b/www/members/meeting.cgi
index b95211b..d1813cc 100755
--- a/www/members/meeting.cgi
+++ b/www/members/meeting.cgi
@@ -7,7 +7,7 @@ require 'wunderbar/bootstrap'
 require 'date'
 require 'json'
 require 'wunderbar/jquery/stupidtable'
-require_relative 'meeting-util'
+require 'whimsy/asf/meeting-util'
 DTFORMAT = '%A, %d %B %Y at %H:%M %z'
 TADFORMAT = '%Y%m%dT%H%M%S'
 ERROR_DATE = DateTime.new(1970, 1, 1) # An obvious error value 8-)
@@ -57,7 +57,7 @@ def emit_meeting(cur_mtg_dir, svn_mtg_dir, dt, num_members, 
quorum_need, num_pro
       _p "Live links to the upcoming meeting records/ballots/how-tos are 
below."
     end
     _ul do
-      MeetingUtil::MEETING_FILES.each do |f, desc|
+      ASF::MeetingUtil::MEETING_FILES.each do |f, desc|
         _li do
           emit_link(svn_mtg_dir, f, desc)
         end
@@ -70,13 +70,13 @@ end
 _html do
   _body? do
     MEETINGS = ASF::SVN['Meetings']
-    cur_mtg_dir = MeetingUtil.get_latest(MEETINGS)
+    cur_mtg_dir = ASF::MeetingUtil.get_latest(MEETINGS)
     meeting = File.basename(cur_mtg_dir)
-    svn_mtg_dir = File.join(MeetingUtil::RECORDS, meeting)
+    svn_mtg_dir = File.join(ASF::MeetingUtil::RECORDS, meeting)
     mtg_date = Date.parse(meeting)
     today = Date.today
     # Calculate quorum
-    num_members, quorum_need, num_proxies, attend_irc = 
MeetingUtil.calculate_quorum(cur_mtg_dir)
+    num_members, quorum_need, num_proxies, attend_irc = 
ASF::MeetingUtil.calculate_quorum(cur_mtg_dir)
     # Use ics files for accurate times; see create-meeting.rb
     nom_date = ics2dtstart(File.join(cur_mtg_dir, 
"ASF-members-#{mtg_date.strftime('%Y')}-nominations-close.ics"))
     m1_date = ics2dtstart(File.join(cur_mtg_dir, 
"ASF-members-#{mtg_date.strftime('%Y')}.ics"))
@@ -94,7 +94,7 @@ _html do
         '/members/whatif' => 'Explore Past Board STV Results',
         '/members/non-participants' => 'Members Not Participating Recntly',
         '/members/inactive' => 'Inactive Member Feedback Form',
-        MeetingUtil::RECORDS => 'Official Past Meeting Records',
+        ASF::MeetingUtil::RECORDS => 'Official Past Meeting Records',
         'https://lists.apache.org/[email protected]' => 'Read 
members@ List Archives'
       },
       helpblock: -> {
@@ -148,7 +148,7 @@ _html do
         end
       }
     ) do
-      help, copypasta = MeetingUtil.is_user_proxied(cur_mtg_dir, $USER)
+      help, copypasta = ASF::MeetingUtil.is_user_proxied(cur_mtg_dir, $USER)
       # attendance = JSON.parse(IO.read(File.join(MEETINGS, 
'attendance.json')))
       user = ASF::Person.find($USER)
       _div id: 'personal'
@@ -187,7 +187,7 @@ _html do
           _ul do
             ['nomination_of_board.txt', 'nomination_of_members.txt', 
'/members/proxy.cgi'].each do |f|
               _li do
-                emit_link(svn_mtg_dir, f, MeetingUtil::MEETING_FILES[f])
+                emit_link(svn_mtg_dir, f, ASF::MeetingUtil::MEETING_FILES[f])
               end
             end
           end
@@ -206,7 +206,7 @@ _html do
           _ul do
             ['nominated-members.txt', '/members/proxy.cgi'].each do |f|
               _li do
-                emit_link(svn_mtg_dir, f, MeetingUtil::MEETING_FILES[f])
+                emit_link(svn_mtg_dir, f, ASF::MeetingUtil::MEETING_FILES[f])
               end
             end
           end
@@ -234,13 +234,13 @@ _html do
           _ ' channel.'
           _br
           _ 'During the First Half of Meeting, the Board Chair will do Roll 
call - please see instructions on how to mark present: '
-          emit_link(svn_mtg_dir, 'README.txt', 
MeetingUtil::MEETING_FILES['README.txt'])
+          emit_link(svn_mtg_dir, 'README.txt', 
ASF::MeetingUtil::MEETING_FILES['README.txt'])
           _ 'Once a quorum is reached, the Board Chair will lead the meeting, 
with various officers presenting their reports in the Agenda.txt, which you can 
read ahead of time.'
           _ 'Expect the First Half to last about an hour; then the Board Chair 
will call for a recess.  Remember: there is no voting in IRC.'
           _ul do
             ['agenda.txt', 'README.txt', 
'https://www.apache.org/foundation/governance/meetings'].each do |f|
               _li do
-                emit_link(svn_mtg_dir, f, MeetingUtil::MEETING_FILES[f])
+                emit_link(svn_mtg_dir, f, ASF::MeetingUtil::MEETING_FILES[f])
               end
             end
           end
@@ -280,7 +280,7 @@ _html do
           _ul do
             ['record', 'attend', 'voter-tally', 'raw_board_votes.txt', 
'raw-irc-log'].each do |f|
               _li do
-                emit_link(svn_mtg_dir, f, MeetingUtil::MEETING_FILES[f])
+                emit_link(svn_mtg_dir, f, ASF::MeetingUtil::MEETING_FILES[f])
               end
             end
             _li do
@@ -331,7 +331,7 @@ _html do
           _ul do
             all_mtg.each do |mtg|
               _li do
-                tmp = File.join(MeetingUtil::RECORDS, File.basename(mtg))
+                tmp = File.join(ASF::MeetingUtil::RECORDS, File.basename(mtg))
                 _a tmp, href: tmp
               end
             end
diff --git a/www/members/nominations.cgi b/www/members/nominations.cgi
index 76d18cf..66c3484 100755
--- a/www/members/nominations.cgi
+++ b/www/members/nominations.cgi
@@ -7,7 +7,7 @@ require 'mail'
 require 'wunderbar/bootstrap'
 require 'whimsy/asf'
 require 'whimsy/asf/member-files'
-require_relative 'meeting-util'
+require 'whimsy/asf/meeting-util'
 
 # link to members private-arch
 MBOX = 'https://mail-search.apache.org/members/private-arch/members/'
@@ -93,7 +93,7 @@ _html do
         _ 'Entries are highlighted if they are not present in both lists.'
       }
     ) do
-      cur_mtg_dir = File.basename(MeetingUtil.get_latest(MEETINGS))
+      cur_mtg_dir = File.basename(ASF::MeetingUtil.get_latest(MEETINGS))
       nominations, emails = setup_data
       _div.flexbox do
         _div.flexitem do
diff --git a/www/members/non-participants.cgi b/www/members/non-participants.cgi
index bec9235..a263069 100755
--- a/www/members/non-participants.cgi
+++ b/www/members/non-participants.cgi
@@ -7,17 +7,17 @@ require 'wunderbar/bootstrap'
 require 'date'
 require 'json'
 require 'wunderbar/jquery/stupidtable'
-require_relative 'meeting-util'
+require 'whimsy/asf/meeting-util'
 
 # Find latest meeting and check if it's in the future yet
 MEETINGS = ASF::SVN['Meetings']
-cur_mtg_dir = MeetingUtil.get_latest(MEETINGS)
+cur_mtg_dir = ASF::MeetingUtil.get_latest(MEETINGS)
 meeting = File.basename(cur_mtg_dir)
 today = Date.today.strftime('%Y%m%d')
 
 # look for recent activity if there is an upcoming meeting
 if meeting > today
-  current_status = MeetingUtil.current_status(cur_mtg_dir)
+  current_status = ASF::MeetingUtil.current_status(cur_mtg_dir)
 else
   current_status = lambda {'No response'}
 end
@@ -31,7 +31,7 @@ end
 # produce HTML
 _html do
   _body? do
-    attendance, matrix, dates, nameMap = 
MeetingUtil.get_attend_matrices(MEETINGS)
+    attendance, matrix, dates, nameMap = 
ASF::MeetingUtil.get_attend_matrices(MEETINGS)
     _whimsy_body(
       title: PAGETITLE,
       subtitle: 'Select A Date:',
@@ -126,5 +126,5 @@ _html do
 end
 
 _json do
-  MeetingUtil.tracker((@meetingsMissed || 3).to_i)
+  ASF::MeetingUtil.tracker((@meetingsMissed || 3).to_i)
 end
diff --git a/www/members/proxy.cgi b/www/members/proxy.cgi
index ec7e053..20d28af 100755
--- a/www/members/proxy.cgi
+++ b/www/members/proxy.cgi
@@ -8,7 +8,7 @@ require 'wunderbar/bootstrap'
 require 'wunderbar/jquery'
 require 'date'
 require 'tmpdir'
-require_relative 'meeting-util'
+require 'whimsy/asf/meeting-util'
 
 # Emit basic instructions and details on quorum
 def emit_instructions(today, cur_mtg_dir, meeting)
@@ -68,7 +68,7 @@ def emit_instructions(today, cur_mtg_dir, meeting)
     _ ' file.  The great majority of proxies assigned are for attendance only; 
not for voting.'
   end
   end
-  num_members, quorum_need, num_proxies, attend_irc = 
MeetingUtil.calculate_quorum(cur_mtg_dir)
+  num_members, quorum_need, num_proxies, attend_irc = 
ASF::MeetingUtil.calculate_quorum(cur_mtg_dir)
   if num_members
     _p do
       _ 'Currently, we must have '
@@ -81,7 +81,7 @@ end
 
 # Emit meeting data and form for user to select a proxy - GET
 def emit_form(cur_mtg_dir, meeting, volunteers, disabled)
-  help, copypasta = MeetingUtil.is_user_proxied(cur_mtg_dir, $USER)
+  help, copypasta = ASF::MeetingUtil.is_user_proxied(cur_mtg_dir, $USER)
   user_is_proxy = help && copypasta
   _whimsy_panel(user_is_proxy ? "You Are Proxying For Others" : "Select A 
Proxy For Upcoming Meeting", style: 'panel-success') do
     _div do
@@ -292,7 +292,7 @@ _html do
   _body? do
     # Find latest meeting and check if it's in the future yet
     MEETINGS = ASF::SVN['Meetings']
-    cur_mtg_dir = MeetingUtil.get_latest(MEETINGS)
+    cur_mtg_dir = ASF::MeetingUtil.get_latest(MEETINGS)
     meeting = File.basename(cur_mtg_dir)
     today = Date.today.strftime('%Y%m%d')
     _whimsy_body(
@@ -310,7 +310,7 @@ _html do
       }
     ) do
       if _.get?
-        emit_form(cur_mtg_dir, meeting, 
MeetingUtil::getVolunteers(cur_mtg_dir), today > meeting)
+        emit_form(cur_mtg_dir, meeting, 
ASF::MeetingUtil::getVolunteers(cur_mtg_dir), today > meeting)
       else # POST
         emit_post(cur_mtg_dir, meeting, _)
       end

Reply via email to