diff options
author | Florian Effenberger <floeff@documentfoundation.org> | 2017-11-30 09:34:30 +0000 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2017-12-04 17:14:55 +0100 |
commit | 291973a4ddceb988b4027516db35ae0c7c8f7a69 (patch) | |
tree | 4bd90b52d7d360862e765bfed9dd302076d9fd8b | |
parent | fe59b57f12f5f97d071ea5e7aa76e6b42b8ba3e4 (diff) |
2017 board elections created
-rw-r--r-- | vote/2017-board/Makefile.am | 14 | ||||
-rw-r--r-- | vote/2017-board/candidates.wml | 68 | ||||
-rw-r--r-- | vote/2017-board/index.wml | 57 | ||||
-rwxr-xr-x | vote/2017-board/mkical.py | 253 | ||||
-rw-r--r-- | vote/2017-board/rules.wml | 122 | ||||
-rw-r--r-- | vote/2017-board/timeline.ics | 72 | ||||
-rw-r--r-- | vote/2017-board/voting-instructions.txt | 39 |
7 files changed, 625 insertions, 0 deletions
diff --git a/vote/2017-board/Makefile.am b/vote/2017-board/Makefile.am new file mode 100644 index 0000000..56f3ab5 --- /dev/null +++ b/vote/2017-board/Makefile.am @@ -0,0 +1,14 @@ +SUBDIRS = + +urlpath = /vote/2017-board + +page_SCRIPTS = \ + index.html \ + candidates.html\ + rules.html + +page_DATA = \ + timeline.ics + mkical.py + +include $(top_srcdir)/rules.common diff --git a/vote/2017-board/candidates.wml b/vote/2017-board/candidates.wml new file mode 100644 index 0000000..7cc923a --- /dev/null +++ b/vote/2017-board/candidates.wml @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html> + + <head> + <title>The Document Foundation 2017 Board of Directors Election Candidates</title> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> + </head> + + <body> + <h1>Candidates for The Document Foundation 2017 Board of Directors Election</h1> + + <p> + Below you will find a list of candidates who are running for + The Document Foundation Board of Directors. A short summary statement from + each candidate and a link to their full candidacy announcement is + provided to help you learn more about them. We encourage all voters + to read the full candidacy statements and related discussions on + <a href="https://listarchives.documentfoundation.org/www/board-discuss/">board-discuss@documentfoundation.org</a>. + </p> + + <p> When deciding who you should vote for, please carefully + consider the various tasks the Board of Directors must + perform. This <a href="../overview.html">overview</a> may be + helpful. Keep in mind that the board will make a number of + important decisions and will also have to perform many tasks which + might require a significant amount of time and effort and the + ability to work and communicate with other people, companies, and + the media. It is a good idea to strive for a well-balanced board + consisting of people with various backgrounds, skills, and + perspectives. </p> + + <p> + Additional elections details can be found in the + <a href="https://www.documentfoundation.org/satzung.pdf">Document Foundation statutes</a> (and the non-binding + <a href="https://www.documentfoundation.org/statutes.pdf">English version</a>). + </p> + + <p> + If you have any questions, please send them to either + <a href="mailto:board-discuss@documentfoundation.org">board-discuss@documentfoundation.org</a> (public list) + or in private to the Membership Committee at <a + href="mailto:elections@documentfoundation.org">elections@documentfoundation.org</a>. + </p> + + <h2>Candidates for The Document Foundation Board of Directors</h2> + + <p>Will be announced after the nomination phase has ended</p> + + <h2>Additional Elections-related Information</h2> + + <p> + Note, that according to the + <a href="https://www.documentfoundation.org/satzung.pdf">Document Foundation statutes</a> (and the non-binding + <a href="https://www.documentfoundation.org/statutes.pdf">English version</a>), + there is a 1/3 maximum on the number of people affiliated with any one company that can be on the board or + amongst the deputies. For details refer to the statutes. You will be able to vote for up to 10 candidates of your choice, with no + restrictions, except that you cannot vote more than once for the same candidate. + </p> + + <p> + If you have any futher question, please consult the + <a href="rules.html">Rules for this election</a> or write to + <a href="mailto:elections@documentfoundation.org">elections@documentfoundation.org</a>. + </p> + <script src="shuffle.js" /> + </body> +</html> diff --git a/vote/2017-board/index.wml b/vote/2017-board/index.wml new file mode 100644 index 0000000..43e5192 --- /dev/null +++ b/vote/2017-board/index.wml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html> + + <head> + <title>The Document Foundation 2017 Board of Directors Election</title> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + </head> + + <body> + + <h1>The Document Foundation 2017 Board of Directors Election</h1> + + <p> + The Document Foundation Membership currently elects the Board of + Directors every other year. Any member can + nominate themself to run in the elections. The overall elections + process is overseen by the Membership Committee, + which can be reached + at <a href="mailto:elections@documentfoundation.org">elections@documentfoundation.org</a>. + </p> + + <p> + The elections results from the 2017 Board of Directors elections + will be archived here for public access. + </p> + + <h2>2017 Elections Materials:</h2> + <ul> + <li> + <a href="../results.php?election_id=9">Detailed election results</a> + </li> + <li> + <a href="../votes.php?election_id=9">List of all votes</a> + </li> + <li> + <a href="../vote.php?election_id=9">Interface to vote</a> + </li> + <li> + <a href="candidates.html">List of candidates for Board of Directors</a> + </li> + + <li> + <a href="https://www.documentfoundation.org/governance/members/">List of registered voters</a> + </li> + + <li> + <a href="rules.html">Elections Rules and Timeline</a> + </li> + + <li> + <a href="../overview.html">Overview of the Board of Directors role</a> + </li> + </ul> + + </body> +</html> diff --git a/vote/2017-board/mkical.py b/vote/2017-board/mkical.py new file mode 100755 index 0000000..9be841a --- /dev/null +++ b/vote/2017-board/mkical.py @@ -0,0 +1,253 @@ +#!/usr/bin/env python +''' +This Python script creates a simple iCal file based on hardcoded events +in this file. +''' + +import calendar +import datetime +import logging +import math +import os +import vobject + + +#### Configure these variables +YEAR = 2017 +CANDIDATES_OPENED_DATE = (YEAR, 10, 19) +CANDIDATES_CLOSED_DATE = (YEAR, 11, 27) +CANDIDATES_ANNOUNCED_DATE = (YEAR, 11, 28) +VOTING_OPENED_DATE = (YEAR, 12, 05) +VOTING_CLOSED_DATE = (YEAR, 12, 12) +PRELIMINARY_RESULTS_DATE = (YEAR, 12, 13) +CHALLENGE_CLOSED_DATE = (YEAR, 12, 18) + + + +### I'm sorry that these functions clutter your calendar-creating experience +### Please scroll down a bit to edit the description texts + +#### Application Data +def c(multilinestring): + ''' + A helper functions which cleans up a multiline string, so that + it doesn't contain any newlines or multiple whitespaces + ''' + stripped = [l.strip() for l in multilinestring.splitlines()] + ret = " ".join (stripped) + return ret + +def d(year, month, day): + ''' + Just a tiny wrapper around datetime.datetime to create a datetime object + ''' + return datetime.date(year, month, day) + + + +CANDIDATES_OPENED = ( + d(*CANDIDATES_OPENED_DATE), + 'Announcements and list of candidates opens', + c("""If you are a member of The Document Foundation and are interested + in running for election, you may nominate yourself by sending an + e-mail to elections@documentfoundation.org with your name, e-mail + address, corporate affiliation (if any), and a description of why + you'd like to serve, before + %s (23:59 UTC).""" % d(*CANDIDATES_CLOSED_DATE)) + ''' + ''' + c(""" + You should also send a summary of your candidacy announcement + (75 words or less) to discuss@documentfoundation.org. """) + ''' + ''' +) + +CANDIDATES_CLOSED = ( + d(*CANDIDATES_CLOSED_DATE), + 'List of candidates closed', + CANDIDATES_OPENED[2] # Get the same text again +) + +CANDIDATES_ANNOUNCED = ( + d(*CANDIDATES_ANNOUNCED_DATE), + 'List of candidates announced', + 'You may now start to send your questions to the candidates' +) + +VOTING_OPENED = ( + d(*VOTING_OPENED_DATE), + 'Instructions to vote are sent', + 'Please read your email and follow these instructions and submit your vote by %s' % d(*VOTING_CLOSED_DATE) +) +VOTING_CLOSED = ( + d(*VOTING_CLOSED_DATE), + 'Votes must be returned', + 'Preliminary results are announced on %s' % d(*PRELIMINARY_RESULTS_DATE) +) + + +PRELIMINARY_RESULTS = ( + d(*PRELIMINARY_RESULTS_DATE), + 'Preliminary results are announced', + 'The preliminary results can be challenged until %s' % d(*CHALLENGE_CLOSED_DATE) +) + +CHALLENGE_CLOSED = ( + d(*CHALLENGE_CLOSED_DATE), + 'Challenges to the results closed', + "If there weren't any challenges, preliminary results are valid" +) + + + + +def create_ical(eventlist): + '''Generates an ical stream based on the list given as eventlist. + The list shall contain elements with a tuple with a + (date, string, string) object, serving as date when the event takes place, + summary and description respectively. + ''' + log = logging.getLogger('create_ical') + + cal = vobject.iCalendar() + cal.add('method').value = 'PUBLISH' + cal.add('calscale').value = 'GREGORIAN' + cal.add('x-wr-timezone').value = 'UTC' + + for (timestamp, summary, description) in eventlist: + log.debug('creating %s, %s', timestamp, description) + vevent = cal.add('vevent') + vevent.add('dtstart').value = timestamp + vevent.add('dtend').value = timestamp + datetime.timedelta(1) + vevent.add('summary').value = summary + vevent.add('description').value = description + + stream = cal.serialize() + return stream + + +def wraptext(s, width): + '''Wraps a string @s at @width characters. + + >>> wraptext('fooo', 2) + ['fo','oo'] + ''' + l = len(s) + nr_frames = int(math.ceil(float(l)/width)) + print nr_frames + frames = [] + for i in xrange(nr_frames): + start, end = i*width, (i+1) * width + frames.append(s[start:end]) + # One could (and prolly should) yield that + return frames + +def ordinal(n): + n = int(n) + if 10 <= n % 100 < 20: + return str(n) + 'th' + else: + return str(n) + {1 : 'st', 2 : 'nd', 3 : 'rd'}.get(n % 10, "th") + + +def cal_for_month(month, events, width=80, year=datetime.datetime.now().year): + '''Generates a textual calendar for the @month in @year. + It will return a string with the calendar on the left hand side and the + events on the right hand side. + @events shall be a list with tuples: timestamp, summary, description. + + Returns a string with the calendar + ''' + log = logging.getLogger('cal_for_month') + + cal = calendar.TextCalendar() + calstrings = cal.formatmonth(year, month, 3).splitlines() + + for (timestamp, summary, description) in events: + log.debug('creating %s, %s', timestamp, summary) + year, month, day = timestamp.year, timestamp.month, timestamp.day + maxwidth = max([len(cs) for cs in calstrings]) + rightwidth = 80 - maxwidth + for i, line in enumerate(calstrings): + needles = (" %d " % day, + " %d\n" % day) + replacement = "(%d)" % day + # Find the day so that we can highlight it and add a comment + day_in_week = False + for needle in needles: + if needle in line+"\n": + # k, this looks a bit weird but we have that corner + # case with the day being at the end of the line + # which in turn will have been split off + day_in_week = True + break # Set the needle to the found one + if day_in_week == False: # Nothing found, try next week + log.debug('Day (%d) not found in %s', day, line) + continue + else: + log.debug('Day (%d) found in %s', day, line) + new_line = (line+"\n").replace(needle, replacement).rstrip() + new_line += " %s (%s)" % (summary, ordinal(day)) + # Replace in-place for two events in the same week + # FIXME: This has bugs :-( + calstrings[i] = new_line + + return os.linesep.join(calstrings) + +def create_textcal(eventlist): + '''Generates a multiline string containing a calendar with the + events written on the side + The list shall contain elements with a tuple with a + (date, string, string) object, serving as date when the event takes place, + summary and description respectively. + ''' + log = logging.getLogger('textcal') + log.debug('Generating from %s', eventlist) + months = set(map(lambda x: x[0].month, eventlist)) + year = set(map(lambda x: x[0].year, eventlist)).pop() + + final_cal = [] + for month in months: + events = filter(lambda x: x[0].month == month, eventlist) + log.debug('Events for %d: %s', month, events) + month_cal = cal_for_month(month, events, year=year) + final_cal.append(month_cal) + + return os.linesep.join(final_cal) + +if __name__ == "__main__": + from optparse import OptionParser + parser = OptionParser("usage: %prog [options]") + parser.add_option("-l", "--loglevel", dest="loglevel", help="Sets the loglevel to one of debug, info, warn, error, critical", + default=None) + parser.add_option("-i", "--ical", + action="store_true", dest="ical", default=False, + help="print iCal file to stdout") + parser.add_option("-t", "--textcal", + action="store_true", dest="tcal", default=False, + help="print textual calendar to stdout") + (options, args) = parser.parse_args() + + loglevel = {'debug': logging.DEBUG, 'info': logging.INFO, + 'warning': logging.WARNING, 'error': logging.ERROR, + 'critical': logging.CRITICAL}.get(options.loglevel, logging.WARNING) + print loglevel + logging.basicConfig( level=loglevel ) + log = logging.getLogger() + + eventlist = [ + CANDIDATES_OPENED, + CANDIDATES_CLOSED, + CANDIDATES_ANNOUNCED, + VOTING_OPENED, + VOTING_CLOSED, + PRELIMINARY_RESULTS, + CHALLENGE_CLOSED, + ] + + if not any([options.ical, options.tcal]): + parser.error("You want to select either ical or textcal output. See --help for details") + if options.ical: + ical = create_ical( eventlist ) + print ical + if options.tcal: + tcal = create_textcal( eventlist ) + print tcal diff --git a/vote/2017-board/rules.wml b/vote/2017-board/rules.wml new file mode 100644 index 0000000..a938cff --- /dev/null +++ b/vote/2017-board/rules.wml @@ -0,0 +1,122 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html> + + <head> + <title>The Document Foundation 2017 Board of Directors Election Rules</title> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + </head> + + <body> + + <h1>Rules & Timeline for The Document Foundation 2017 Board of Directors Election</h1> + + <h2>Elections Rules</h2> + + <ol> + <li> + See the <a href="https://www.documentfoundation.org/satzung.pdf">Document Foundation statutes</a> (and the non-binding + <a href="https://www.documentfoundation.org/statutes.pdf">English version</a>) + for general rules. + </li> + <li> + There are 7 board positions and 3 deputy roles that are to be filled during these elections. + </li> + + <li> +As per § 7 II of our statues, the Board's term lasts two years. The +current board started its duty on February 18, 2016. Therefore, the old +board remains in charge until the end of Sunday, February 18, 2018, so the new +board will be in charge the day after that, which is Monday, February 19, 2018. + </li> + + <li> +That upcoming term will then (regularly) end on Tuesday, February 18, +2020, so the next elections of the Board of Directors will take place +before. + </li> + + <li> +As per § 6 III, only members of the Board of Trustees of The Document +Foundation, as well as current members of any of its bodies, are +eligible to be elected into the Board of Directors, and the election is +overseen by the Membership Committee (§ 7 II). + </li> + + <li> +The active electoral right is reserved to those who have been members of +the Board of Trustees before this announcement (§ 7 II). + </li> + + <li> +§ 6 III also states that members of the Board of Directors or their +deputies may not be members of the Membership Committee and vice versa. +This means that current members of the Membership Committee are eligible +to be elected, but with the acceptance of their new role they lose their +current role in the MC. For clarification, they would have to step down +from the Membership Committee, with effect no later than to the +beginning of the new term of the Board of Directors, the minute before +accepting to become a member of the Board of Directors. + </li> + + <li> +There is one more notable limitation: Per § 8 IV of the statutes, a +maximum of 1/3 members of the Board of Directors is allowed to work on +an employment basis for the same company, organization, entities, +affiliates or subdivisions. + </li> + + <li> +Nomination of candidates fulfilling the above requirements, as well as +self nomination is welcome. In total, at least seven Board of Directors +members are required, and given there are enough candidates, up to three +deputies can be elected (§ 7 II). As deputies are on duty quite often, +we encourage many candidates to participate. + </li> + + <li> +Re-election of current members of the Board of Directors is explicitly +permitted (§ 7 II). + </li> + + <li> + Votes will be held confidential during the elections, but an + anonymized archive of all submitted votes will be made publicly + accessible at its conclusion. + </li> + <li> + The Document Foundation Membership Committee is + responsible for counting the votes. + </li> + </ol> + + <h2>Timeline</h2> + <ul> + <li> +2017-10-19: announcement of the elections; and start of the nomination phase + </li> + <li> +2017-11-27, 24:00 CET/UTC+1: end of the nomination phase (one week before the election starts, as per § 7 II) + </li> + <li> +2017-12-05, 00:00 CET/UTC+1: official start of the elections (at least 45 days after announcement of the elections, as per § 7 II) + </li> + <li> +2017-12-12, 24:00 CET/UTC+1: end of the elections + </li> + <li> +2017-12-13: announcement of the preliminary results and acknowledgement of role + </li> + <li> +2017-12-14, 00:00 CET/UTC+1: start of the challenging phase + </li> + <li> +2017-12-18, 24:00 CET/UTC+1: end of the challenging phase + </li> + <li> +afterwards: official announcement of the final results + </li> + </ul> + + </body> +</html> diff --git a/vote/2017-board/timeline.ics b/vote/2017-board/timeline.ics new file mode 100644 index 0000000..3068f1c --- /dev/null +++ b/vote/2017-board/timeline.ics @@ -0,0 +1,72 @@ +30 +BEGIN:VCALENDAR +VERSION:2.0 +CALSCALE:GREGORIAN +METHOD:PUBLISH +PRODID:-//PYVOBJECT//NONSGML Version 1//EN +BEGIN:VEVENT +UID:20171127T153026Z-64985@vm200 +DTSTART;VALUE=DATE:20171019 +DTEND;VALUE=DATE:20171020 +DESCRIPTION:If you are a member of The Document Foundation and are interes + ted in running for election\, you may nominate yourself by sending an e-ma + il to elections@documentfoundation.org with your name\, e-mail address\, c + orporate affiliation (if any)\, and a description of why you'd like to ser + ve\, before 2017-11-27 (23:59 UTC).\n You should also send a summary o + f your candidacy announcement (75 words or less) to discuss@documentfounda + tion.org.\n +SUMMARY:Announcements and list of candidates opens +END:VEVENT +BEGIN:VEVENT +UID:20171127T153026Z-80218@vm200 +DTSTART;VALUE=DATE:20171127 +DTEND;VALUE=DATE:20171128 +DESCRIPTION:If you are a member of The Document Foundation and are interes + ted in running for election\, you may nominate yourself by sending an e-ma + il to elections@documentfoundation.org with your name\, e-mail address\, c + orporate affiliation (if any)\, and a description of why you'd like to ser + ve\, before 2017-11-27 (23:59 UTC).\n You should also send a summary o + f your candidacy announcement (75 words or less) to discuss@documentfounda + tion.org.\n +SUMMARY:List of candidates closed +END:VEVENT +BEGIN:VEVENT +UID:20171127T153026Z-64756@vm200 +DTSTART;VALUE=DATE:20171128 +DTEND;VALUE=DATE:20171129 +DESCRIPTION:You may now start to send your questions to the candidates +SUMMARY:List of candidates announced +END:VEVENT +BEGIN:VEVENT +UID:20171127T153026Z-25968@vm200 +DTSTART;VALUE=DATE:20171205 +DTEND;VALUE=DATE:20171206 +DESCRIPTION:Please read your email and follow these instructions and submi + t your vote by 2017-12-12 +SUMMARY:Instructions to vote are sent +END:VEVENT +BEGIN:VEVENT +UID:20171127T153026Z-18131@vm200 +DTSTART;VALUE=DATE:20171212 +DTEND;VALUE=DATE:20171213 +DESCRIPTION:Preliminary results are announced on 2017-12-13 +SUMMARY:Votes must be returned +END:VEVENT +BEGIN:VEVENT +UID:20171127T153026Z-5280@vm200 +DTSTART;VALUE=DATE:20171213 +DTEND;VALUE=DATE:20171214 +DESCRIPTION:The preliminary results can be challenged until 2017-12-18 +SUMMARY:Preliminary results are announced +END:VEVENT +BEGIN:VEVENT +UID:20171127T153026Z-870@vm200 +DTSTART;VALUE=DATE:20171218 +DTEND;VALUE=DATE:20171219 +DESCRIPTION:If there weren't any challenges\, preliminary results are vali + d +SUMMARY:Challenges to the results closed +END:VEVENT +X-WR-TIMEZONE:UTC +END:VCALENDAR + diff --git a/vote/2017-board/voting-instructions.txt b/vote/2017-board/voting-instructions.txt new file mode 100644 index 0000000..9b0e451 --- /dev/null +++ b/vote/2017-board/voting-instructions.txt @@ -0,0 +1,39 @@ +elections@documentfoundation.org +Gabriele Ponzo <elections@documentfoundation.org> +Your Document Foundation 2017 Board Elections Voting Token +Dear $member, + +The election of The Document Foundation Board of Directors will soon +be open. + +Voting will run from 2017-12-05, 00:00 CET/UTC+1 until +2017-12-12, 24:00 CET/UTC+1. + +To vote, please go to +https://elections.documentfoundation.org/vote.php?election_id=9 +and follow the instructions there. + +A list of candidates and their reasons for running is available at +https://elections.documentfoundation.org/2017-board/candidates.html + +When instructed to do so, enter the following details: + + E-mail: $email + Vote token: $token + +The election has 4 steps - first, you must identify yourself using the +voting token above. Then select your preferred candidates in order of +preference. A third step will show you your choice, and ask you to +confirm or return to the previous step. Finally, after confirming your +choice, a unique identifier will be given to you which will allow you to +verify after the election that your vote was counted correctly. To ensure +anonymity, no link will be kept between this token and your identifiers, +so please keep this token safe. Once you have voted, you will not be able +to vote again. + +Thank you for your vote! + +Regards, + Gabriele Ponzo + Chairman of the Membership Committee + The Document Foundation |