Preamble
- The GNU Affero General Public License is a free, copyleft license
-for software and other kinds of works, specifically designed to ensure
+ The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
- The licenses for most software and other practical works are
-designed to take away your freedom to share and change the works. By
-contrast, our General Public Licenses are intended to guarantee your
-freedom to share and change all versions of a program--to make sure it
-remains free software for all its users.
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
0. Definitions.
- "This License" refers to version 3 of the GNU Affero General Public
-License.
+ "This License" refers to version 3 of the GNU Affero General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
- "Copyright" also means copyright-like laws that apply to other kinds
-of works, such as semiconductor masks.
-
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further restriction,
-you may remove that term. If a license document contains a further
-restriction but permits relicensing or conveying under this License, you
-may add to a covered work material governed by the terms of that license
-document, provided that the further restriction does not survive such
-relicensing or conveying.
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
- Notwithstanding any other provision of this License, you have permission
-to link or combine any covered work with a work licensed under version 3
-of the GNU General Public License into a single combined work, and to
-convey the resulting work. The terms of this License will continue to
-apply to the part which is the covered work, but the work with which it is
-combined will remain governed by version 3 of the GNU General Public
-License.
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the work with which it is combined will remain governed by version
+3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
-the GNU Affero General Public License from time to time. Such new
-versions will be similar in spirit to the present version, but may differ
-in detail to address new problems or concerns.
+the GNU Affero General Public License from time to time. Such new versions
+will be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU Affero
-General Public License "or any later version" applies to it, you have
-the option of following the terms and conditions either of that
-numbered version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number
-of the GNU Affero General Public License, you may choose any version
-ever published by the Free Software Foundation.
+Program specifies that a certain numbered version of the GNU Affero General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU Affero General Public License, you may choose any version ever published
+by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
-versions of the GNU Affero General Public License can be used, that
-proxy's public statement of acceptance of a version permanently
-authorizes you to choose that version for the Program.
+versions of the GNU Affero General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
- END OF TERMS AND CONDITIONS
+ END OF TERMS AND CONDITIONS
- How to Apply These Terms to Your New Programs
+ How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
course, we'd sure like it if you would send fixes back to us and tell us
about cool stuff you do with our software!
-The best way to get Selectricity is just to download it from our source
-tree. At the moment, we're hosting our code at Gitorious which is a
-free software hosting provider. You can download Gitorious at the
-project page by following detailed instructions at Gitorious:
+The best way to get Selectricity is just to download it from our
+source repository. You'll need the Git version control system or
+source control manager to check it. You can get it here:
- http://gitorious.org/selectricity
+ http://git-scm.com/
+
+Once you have it, getting the source code is pretty easy. You just need
+to check out a branch with a command like this:
+
+ git clone http://projects.mako.cc/source/selectricity/.git
+
+By default, this will create a working copy with the latest
+*development* version of our code. If you want the latest production
+version (i.e., what we're running on the site), you need to switch to
+the live version of the software which is kept in a branch called
+"live." Once you cloned the repository above, you can switch into the
+directory (i.e., run "cd selectricity") and then run the following
+command:
+
+ git checkout -b live origin/live
===============================================
http://mailman.mit.edu/mailman/listinfo/selectricity
-In terms of bugs and documentation, we current plan to build this out in
-our Gitorious wiki so feel free to get started with your own efforts
-along these lines there:
-
- http://gitorious.org/selectricity/pages/Home
-
===============================================
=== Dependencies ==============================
provides '/usr/bin/sendmail' should work.
-
===============================================
=== Contributors to Selectricity Include ======
===============================================
data, labels = get_borda_points(@election.borda_result)
size = "400x300"
- size = "580x300" if @election.candidates.size >= 5
+ #size = "580x300" if @election.candidates.size >= 5
+ size = sprintf "580x%d", @election.candidates.size*22 \
+ if @election.candidates.size >= 5
if @election.candidates.size >= 5
marker_font_size = 17
marker_font_size = 20
end
- graph = GruffGraff.new( :graph_type => Gruff::Bar,
+ graph = GruffGraff.new( :graph_type => Gruff::SideBar,
:data_name => @election.name,
:data => data,
:interval_labels => labels,
:title => "Points Per Candidate",
:marker_color => '#999999',
:marker_font_size => marker_font_size,
- :y_axis_label => "Points",
- :x_axis_label => "Candidates")
+ :x_axis_label => "Points",
+ :y_axis_label => "Candidates")
send_data(*graph.output)
end
#Acording to Tufte, small, concomparitive, highly labeled data sets usually
else
# record the ip address for posterity
- @voter.ipaddress = request.env["REMOTE_ADDR"]
+ @voter.ipaddress = request.env["HTTP_X_FORWARDED_FOR"]
@voter.save
# toggle the confirmation bit
- @voter.vote.confirm!
-
- @voter.reload
- render :action => 'thanks'
+ if @voter.vote.confirm!
+ @voter.reload
+ render :action => 'thanks'
+ else
+ redirect_to :action => 'index'
+ end
end
end
@election=QuickVote.ident_to_quickvote(params[:id])
@election.voters.each do |voter|
next unless voter.ipaddress
+
location=nil
- if defined? Cache and location=Cache.get("GEO:#{voter.ipaddress}")
- elsif defined? Cache
+ if Cache and location=Cache.get("GEO:#{voter.ipaddress}")
+ elsif Cache
location = GeoKit::Geocoders::IpGeocoder.geocode(voter.ipaddress)
Cache.set "GEO:#{voter.ipaddress}", location
else
end
def confirm
- @voter.vote.confirm!
-
- if @voter.election.embeddable? and params[:embed] == "true" \
- and @voter.election.early_results?
- redirect_to :action => :results, :id => @password, :embed => 'true'
- elsif not(@voter.election.verifiable) \
- and @voter.election.kiosk and params[:kiosk] == "true"
- redirect_to :action => "kiosk_ready", :id => @password, :kiosk => true
+ if @voter.vote.confirm!
+ if @voter.election.embeddable? and params[:embed] == "true" \
+ and @voter.election.early_results?
+ redirect_to :action => :results, :id => @password, :embed => 'true'
+ elsif not(@voter.election.verifiable) \
+ and @voter.election.kiosk and params[:kiosk] == "true"
+ redirect_to :action => "kiosk_ready", :id => @password, :kiosk => true
+ else
+ render :action => 'thanks'
+ end
else
- render :action => 'thanks'
+ redirect_to :action => 'index'
end
end
# skip if the voter has not voted or has an unconfirmed vote
next unless voter.voted?
- plurality_tally << voter.vote.rankings.sort[0].candidate.id
+ plurality_tally << voter.vote.rankings.sort[0].candidate_id
approval_tally << voter.vote.rankings.sort[0..1].collect \
- { |ranking| ranking.candidate.id }
+ { |ranking| ranking.candidate_id }
preference_tally << voter.vote.rankings.sort.collect \
- { |ranking| ranking.candidate.id }
+ { |ranking| ranking.candidate_id }
end
@plurality_result = PluralityVote.new(plurality_tally).result
end
end
+ def just_before_midnight(datetime)
+ if datetime.instance_of? DateTime
+ off = datetime.offset
+ else
+ off = Rational(datetime.utc_offset, 60*60*24)
+ end
+ return DateTime.new(datetime.year, datetime.month, datetime.day,
+ 23, 59, 59, off)
+ end
+
private
def enforce_constraints
+ # elections end just before midnight
+ self.enddate = just_before_midnight(self.enddate)
# kiosks can't be authenticated
self.authenticated = false if kiosk?
return true
end
end
-
-
end
def confirm!
- self.confirmed = 1
- self.time = Time.now
- self.save
-
- unless self.voter.election.quickvote?
- token.destroy and token.reload if token
- self.token = Token.new
+ if self.voter.election.candidates.length == self.rankings.length
+ self.confirmed = 1
+ self.time = Time.now
self.save
+
+ unless self.voter.election.quickvote?
+ token.destroy and token.reload if token
+ self.token = Token.new
+ self.save
+ end
+ return false
+ else
+ return true
end
end
<% end -%>
</table>
</p>
+<p><%= link_to "Create a new election", :controller => 'election', :action => 'new' %>.</p>
<br />
</tr>
<% end %>
</table>
+<p><%= link_to( "Create a new QuickVote", :controller => 'quickvote', :action => 'create') %>.</p>
tables.
<% if not @election.class == QuickVote %>
- <%= link_to "Click here", { :action => 'pref_tables', :id => @voter.password }, :popup => [] %>
+ <%= link_to "Click here", { :action => 'pref_tables', :id => @election.id }, :popup => [] %>
to view details.
<% end %>
tables.
<% if not @election.class == QuickVote %>
- <%= link_to "Click here", { :action => 'pref_tables', :id => @voter.password }, :popup => [] %>
+ <%= link_to "Click here", { :action => 'pref_tables', :id => @election.id }, :popup => [] %>
to view details.
<% end %>
<%= sortable_element 'rankings-list',
:url => { :action => "sort_candidates", :id => @voter.vote.id },
+ :method => "get",
:complete => visual_effect(:highlight, 'rankings-list') %>
<p><label for="election_enddate">Election End Date</label><br />
<font size="-1"><em>All elections end at 23:59.</em></font><br />
-<%= date_select :election, :enddate %></p>
+<%= datetime_select :election, :enddate, {:discard_hour=>true, :discard_minute=>true} %></p>
<p><label for="election_election_method">Election Method</label><br />
<% type_hash = {}; ELECTION_TYPES.each {|k,v| type_hash[v] = k} %>
<div id="footer">
Copyleft 2006-2010
(<a href="http://projects.mako.cc/source/selectricity/README">Source Available</a>)
- <a href="http://civic.mit.edu">MIT Center for Future Civic Media</a>,
+ <a href="http://civic.mit.edu">MIT Center for Civic Media</a>,
<a href="http://www.media.mit.edu">MIT Media Lab</a>,
<%= link_to("Selectricity Team", :controller => 'about', :action => 'team') %> ::
<a href="http://blog.selectricity.org/">Selectricity News Blog</a>
<p>Drag and drop the items on <strong>list in the left column</strong>
until they are in order from most preferred at the top to least
-preferred at the bottom. When you are done, press confirm to record your
+preferred at the bottom. When you are done, press the 'Submit Vote'
+button at the bottom of the left column to record your
vote.</p>
<div class="normal-header">
<p>Your vote has been recorded for the <strong><%= @voter.election.name
%></strong>.</p>
+<% if @voter.election.verifiable %>
<p>Your unique token for this vote is: <strong><%= @voter.vote.token %></strong></p>
<p>Please record this token for your records and keep it secret. This is
end of the election, you will be able to use this token to verify that
your vote was used in the election and that your vote was recorded
correctly.</p>
+<% end %>
<% if @voter.election.kiosk? and params[:kiosk] == 'true' %>
# Settings specified here will take precedence over those in config/environment.rb
#disable memcache
Cache=nil
+
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the webserver when you make code changes.
# Settings specified here will take precedence over those in config/environment.rb
#
#Enable memcache
-#require('memcache')
-#Cache=MemCache.new('localhost', :compression => true)
-Cache=nil
+require('memcache')
+Cache=MemCache.new('localhost', :compression => true)
+
# The production environment is meant for finished, "live" apps.
# Code is not reloaded between requests
config.cache_classes = true
# Settings specified here will take precedence over those in config/environment.rb
#disable memcache
Cache=nil
+
# The test environment is used exclusively to run your application's
# test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped
----
cwd: /org/selectricity/selectricity-live
log_file: log/mongrel.log
port: "8000"