fec_results 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fec_results.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Derek Willis
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # FecResults
2
+
3
+ FecResults is a Ruby library that provides access to federal election results as published by the Federal Election Commission. Although it is primarily a campaign finance disclosure agency, the FEC also compiles election results on its site. This library provides ways to access summary and contest-specific information about elections for the U.S. House of Representatives, the U.S. Senate and President from 2000-2012. This data represents regularly-scheduled primary and general elections, plus special elections held on the date of general elections. It does not include special elections held outside the regularly scheduled election calendar. The results are race-wide only; they do not contain any geographic breakdowns such as county.
4
+
5
+ Please be aware that there can be typos in some of the FEC results files, mainly in the FEC candidate IDs.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'fec_results'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install fec_results
20
+
21
+ ## Usage
22
+
23
+ FecResults can be used to retrieve both summary and contest-specific election results. Every instance of FecResults must include a year passed into the `new` method. For summary totals:
24
+
25
+ ```ruby
26
+ require 'fec_results'
27
+ s = FecResults::Summary.new(:year => 2012)
28
+ general_votes = s.general_election_votes
29
+ => [<OpenStruct state="AL", presidential_votes=2074338, senate_votes=nil, house_votes=1933630>, <OpenStruct state="AK", presidential_votes=300495, senate_votes=nil, house_votes=289804>,...]
30
+ general_votes.
31
+ alabama = general_votes.first
32
+ => <OpenStruct state="AL", presidential_votes=2074338, senate_votes=nil, house_votes=1933630>
33
+ alabama.house_votes
34
+ => 1933630
35
+ ```
36
+ For specific congressional results, the file can take awhile to load, so try not to call `results` more than once, but rather save the output locally:
37
+
38
+ ```ruby
39
+ c = FecResults::Congress.new(:year => 2012)
40
+ results = c.results
41
+ results.first
42
+ => <FecResults::Result:0x007fb46e297870 @year=2012, @chamber="H", @state="AL", @district="01", @fec_id="H2AL01077", @incumbent=true, @candidate_last="Bonner", @candidate_first="Jo", @candidate_name="Bonner, Jo", @party="R", @primary_votes=48702, @primary_pct=55.54959907839358, @primary_unopposed=false, @runoff_votes=nil, @runoff_pct=nil, @general_votes=196374, @general_pct=97.85624588889553, @general_unopposed=false, @general_runoff_votes=nil, @general_runoff_pct=nil, @general_combined_party_votes=nil, @general_combined_party_pct=nil, @general_winner=true, @notes=nil>
43
+ ```
44
+
45
+ To filter either summary or results items by state, pass in the state in a hash:
46
+
47
+ ```ruby
48
+ c = FecResults::Congress.new(:year => 2012)
49
+ results = c.results({:state => 'AL'})
50
+ results.first
51
+ => <FecResults::Result:0x007fb46e297870 @year=2012, @chamber="H", @state="AL", @district="01", @fec_id="H2AL01077", @incumbent=true, @candidate_last="Bonner", @candidate_first="Jo", @candidate_name="Bonner, Jo", @party="R", @primary_votes=48702, @primary_pct=55.54959907839358, @primary_unopposed=false, @runoff_votes=nil, @runoff_pct=nil, @general_votes=196374, @general_pct=97.85624588889553, @general_unopposed=false, @general_runoff_votes=nil, @general_runoff_pct=nil, @general_combined_party_votes=nil, @general_combined_party_pct=nil, @general_winner=true, @notes=nil>
52
+ ```
53
+
54
+
55
+
56
+
57
+ ## Contributing
58
+
59
+ 1. Fork it
60
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
61
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
62
+ 4. Push to the branch (`git push origin my-new-feature`)
63
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/api_routes.csv ADDED
@@ -0,0 +1 @@
1
+ class,method,path,container,object,arg example
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'fec_results/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "fec_results"
8
+ spec.version = FecResults::VERSION
9
+ spec.authors = ["Derek Willis"]
10
+ spec.email = ["dwillis@gmail.com"]
11
+ spec.description = %q{Parses FEC federal election results into Ruby objects}
12
+ spec.summary = %q{House, Senate, Presidential results}
13
+ spec.homepage = ""
14
+ spec.license = "Apache"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_dependency "remote_table"
24
+ spec.add_dependency "american_date"
25
+ end
@@ -0,0 +1,40 @@
1
+ require 'rubygems'
2
+ require 'remote_table'
3
+ require 'american_date'
4
+ require 'ostruct'
5
+
6
+ require "fec_results/version"
7
+ require "fec_results/congress"
8
+ require "fec_results/result"
9
+ require "fec_results/summary"
10
+ require "fec_results/president"
11
+
12
+ module FecResults
13
+
14
+ SUMMARY_URLS = {
15
+ '2012' => 'http://www.fec.gov/pubrec/fe2012/tables2012.xls',
16
+ '2010' => 'http://www.fec.gov/pubrec/fe2010/tables10.xls',
17
+ '2008' => 'http://www.fec.gov/pubrec/fe2008/tables2008.xls',
18
+ '2006' => 'http://www.fec.gov/pubrec/fe2006/tables06.xls',
19
+ '2004' => 'http://www.fec.gov/pubrec/fe2004/tables.xls',
20
+ '2002' => 'http://www.fec.gov/pubrec/fe2002/2002fedresults.xls',
21
+ '2000' => 'http://www.fec.gov/pubrec/fe2000/tables.xls'
22
+ }
23
+
24
+ CONGRESS_URLS = {
25
+ '2012' => 'http://www.fec.gov/pubrec/fe2012/2012congresults.xls',
26
+ '2010' => 'http://www.fec.gov/pubrec/fe2010/results10.xls',
27
+ '2008' => 'http://www.fec.gov/pubrec/fe2008/2008congresults.xls',
28
+ '2006' => 'http://www.fec.gov/pubrec/fe2006/results06.xls',
29
+ '2004' => 'http://www.fec.gov/pubrec/fe2004/2004congresults.xls',
30
+ '2002' => 'http://www.fec.gov/pubrec/fe2002/2002fedresults.xls',
31
+ '2000' => [{'http://www.fec.gov/pubrec/fe2000/senate.xls' => 'Senate (with Totals & Percent) '}, {'http://www.fec.gov/pubrec/fe2000/house.xls' => 'House (with Totals & Percents)'}]
32
+ }
33
+
34
+ PRESIDENT_URLS = {
35
+ '2012' => 'http://www.fec.gov/pubrec/fe2012/2012pres.xls',
36
+ '2008' => 'http://www.fec.gov/pubrec/fe2008/2008pres.xls',
37
+ '2004' => 'http://www.fec.gov/pubrec/fe2004/2004pres.xls',
38
+ '2000' => ['http://www.fec.gov/pubrec/fe2000/presge.xls', 'http://www.fec.gov/pubrec/fe2000/presprim.xls']
39
+ }
40
+ end
@@ -0,0 +1,323 @@
1
+ module FecResults
2
+ class Congress
3
+
4
+ attr_reader :year, :url
5
+
6
+ # given a year and an optional chamber ('house' or 'senate') and state ('ar', 'az', etc.)
7
+ # retrieves election results that fit the criteria
8
+ def initialize(params={})
9
+ params.each_pair do |k,v|
10
+ instance_variable_set("@#{k}", v)
11
+ end
12
+ @url = FecResults::CONGRESS_URLS[year.to_s]
13
+ end
14
+
15
+ def results(options={})
16
+ send("process_#{year}", options)
17
+ end
18
+
19
+ def process_2012(options)
20
+ results = []
21
+ t = RemoteTable.new(url, :sheet => "2012 US House & Senate Resuts")
22
+ rows = t.entries
23
+ rows = rows.select{|r| r['D'] == options[:chamber]} if options[:chamber]
24
+ rows = rows.select{|r| r['STATE ABBREVIATION'] == options[:state]} if options[:state]
25
+ rows.each do |candidate|
26
+ c = {:year => year}
27
+ next if candidate['CANDIDATE NAME (Last)'].blank?
28
+ next if candidate['D'].blank?
29
+ # find the office_type
30
+ if candidate['FEC ID#'].first != 'n'
31
+ c[:chamber] = candidate['FEC ID#'].first
32
+ elsif candidate['D'].first == 'S'
33
+ c[:chamber] = "S"
34
+ else
35
+ c[:chamber] = 'H'
36
+ end
37
+ c[:state] = candidate['STATE ABBREVIATION']
38
+ c[:district] = candidate['D']
39
+ c[:party] = candidate['PARTY']
40
+ c[:incumbent] = candidate['(I)'] == '(I)' ? true : false
41
+ c[:fec_id] = candidate['FEC ID#']
42
+ c[:candidate_first] = candidate['CANDIDATE NAME (First)']
43
+ c[:candidate_last] = candidate['CANDIDATE NAME (Last)']
44
+ c[:candidate_name] = candidate['CANDIDATE NAME']
45
+
46
+ c = update_vote_tallies(c, candidate, 'PRIMARY VOTES', 'PRIMARY %', 'RUNOFF VOTES', 'RUNOFF %', 'GENERAL VOTES ', 'GENERAL %')
47
+ c = update_general_runoff(c, candidate, 'GE RUNOFF ELECTION VOTES (LA)', 'GE RUNOFF ELECTION % (LA)') if c[:state] == 'LA'
48
+ c = update_combined_totals(c, candidate, 'COMBINED GE PARTY TOTALS (CT, NY, SC)', 'COMBINED % (CT, NY, SC)') if ['CT', 'NY', 'SC'].include?(c[:state])
49
+
50
+ c[:general_winner] = candidate['GE WINNER INDICATOR'] == "W" ? true : false unless c[:general_pct].nil?
51
+
52
+ results << c
53
+ end
54
+ Result.create_from_results(results)
55
+ end
56
+
57
+ def process_2010(options)
58
+ results = []
59
+ t = RemoteTable.new(url, :sheet => "2010 US House & Senate Results")
60
+ rows = t.entries
61
+ rows = rows.select{|r| r['DISTRICT'] == options[:chamber]} if options[:chamber]
62
+ rows = rows.select{|r| r['STATE ABBREVIATION'] == options[:state]} if options[:state]
63
+ rows.each do |candidate|
64
+ c = {:year => year}
65
+ next if candidate['CANDIDATE NAME (Last)'].blank?
66
+ next if candidate['DISTRICT'].blank?
67
+ # find the office_type
68
+ if candidate['FEC ID#'].first != 'n'
69
+ c[:chamber] = candidate['FEC ID#'].first
70
+ elsif candidate['DISTRICT'].first == 'S'
71
+ c[:chamber] = "S"
72
+ else
73
+ c[:chamber] = 'H'
74
+ end
75
+ c[:state] = candidate['STATE ABBREVIATION']
76
+ c[:district] = candidate['DISTRICT']
77
+ c[:party] = candidate['PARTY']
78
+ c[:incumbent] = candidate['INCUMBENT INDICATOR (I)'] == '(I)' ? true : false
79
+ c[:fec_id] = candidate['FEC ID#']
80
+ c[:candidate_first] = candidate['CANDIDATE NAME (First)']
81
+ c[:candidate_last] = candidate['CANDIDATE NAME (Last)']
82
+ c[:candidate_name] = candidate['CANDIDATE NAME (Last, First)']
83
+
84
+ c = update_vote_tallies(c, candidate, 'PRIMARY', 'PRIMARY %', 'RUNOFF', 'RUNOFF %', 'GENERAL ', 'GENERAL %')
85
+ c = update_combined_totals(c, candidate) if ['CT', 'NY', 'SC'].include?(c[:state])
86
+
87
+ results << c
88
+ end
89
+ Result.create_from_results(results)
90
+ end
91
+
92
+ def process_2008(options)
93
+ results = []
94
+ t = RemoteTable.new(url, :sheet => "2008 House and Senate Results")
95
+ rows = t.entries
96
+ rows = rows.select{|r| r['DISTRICT'] == options[:chamber]} if options[:chamber]
97
+ rows = rows.select{|r| r['STATE ABBREVIATION'] == options[:state]} if options[:state]
98
+ rows.each do |candidate|
99
+ c = {:year => year}
100
+ next if candidate['Candidate Name (Last)'].blank?
101
+ next if candidate['DISTRICT'].blank?
102
+ # find the office_type
103
+ if candidate['FEC ID#'].first != 'n'
104
+ c[:chamber] = candidate['FEC ID#'].first
105
+ elsif candidate['DISTRICT'].first == 'S'
106
+ c[:chamber] = "S"
107
+ else
108
+ c[:chamber] = 'H'
109
+ end
110
+ c[:state] = candidate['STATE ABBREVIATION']
111
+ c[:district] = candidate['DISTRICT']
112
+ c[:party] = candidate['PARTY']
113
+ c[:incumbent] = candidate['INCUMBENT INDICATOR (I)'] == '(I)' ? true : false
114
+ c[:fec_id] = candidate['FEC ID#']
115
+ c[:candidate_first] = candidate['CANDIDATE NAME (First)']
116
+ c[:candidate_last] = candidate['CANDIDATE NAME (Last)']
117
+ c[:candidate_name] = candidate['CANDIDATE NAME']
118
+
119
+ c = update_vote_tallies(c, candidate, 'PRIMARY', 'PRIMARY %', 'RUNOFF', 'RUNOFF %', 'GENERAL ', 'GENERAL %')
120
+ c = update_general_runoff(c, candidate, 'GE RUNOFF', 'GE RUNOFF %') if c[:state] == 'LA'
121
+ c = update_combined_totals(c, candidate, 'COMBINED GE PARTY TOTALS (CT, NY)', 'COMBINED % (CT, NY)') if ['CT', 'NY'].include?(c[:state])
122
+
123
+ results << c
124
+ end
125
+ Result.create_from_results(results)
126
+ end
127
+
128
+ def process_2006(options)
129
+ results = []
130
+ t = RemoteTable.new(url, :sheet => "2006 US House & Senate Results")
131
+ rows = t.entries
132
+ rows = rows.select{|r| r['DISTRICT'] == options[:chamber]} if options[:chamber]
133
+ rows = rows.select{|r| r['STATE ABBREVIATION'] == options[:state]} if options[:state]
134
+ rows.each do |candidate|
135
+ c = {:year => year}
136
+ next if candidate['LAST NAME'].blank?
137
+ next if candidate['DISTRICT'].blank?
138
+ # find the office_type
139
+ if candidate['FEC ID'].first != 'n'
140
+ c[:chamber] = candidate['FEC ID'].first
141
+ elsif candidate['DISTRICT'].first == 'S'
142
+ c[:chamber] = "S"
143
+ else
144
+ c[:chamber] = 'H'
145
+ end
146
+ c[:state] = candidate['STATE ABBREVIATION']
147
+ c[:district] = candidate['DISTRICT']
148
+ c[:party] = candidate['PARTY']
149
+ c[:incumbent] = candidate['INCUMBENT INDICATOR'] == '(I)' ? true : false
150
+ c[:fec_id] = candidate['FEC ID#']
151
+ c[:candidate_first] = candidate['FIRST NAME']
152
+ c[:candidate_last] = candidate['LAST NAME']
153
+ c[:candidate_name] = candidate['LAST NAME, FIRST']
154
+
155
+ c = update_vote_tallies(c, candidate, 'PRIMARY', 'PRIMARY %', 'RUNOFF', 'RUNOFF %', 'GENERAL', 'GENERAL %')
156
+ c = update_general_runoff(c, candidate, 'GE RUNOFF', 'GE RUNOFF %') if c[:state] == 'LA'
157
+ c = update_combined_totals(c, candidate, 'COMBINED GE PARTY TOTALS (NY, SC)', 'COMBINED % (NY, SC)') if ['SC', 'NY'].include?(c[:state])
158
+
159
+ results << c
160
+ end
161
+ Result.create_from_results(results)
162
+ end
163
+
164
+ def process_2004(options)
165
+ results = []
166
+ t = RemoteTable.new(url, :sheet => "2004 US HOUSE & SENATE RESULTS")
167
+ rows = t.entries
168
+ rows = rows.select{|r| r['DISTRICT'] == options[:chamber]} if options[:chamber]
169
+ rows = rows.select{|r| r['STATE ABBREVIATION'] == options[:state]} if options[:state]
170
+ rows.each do |candidate|
171
+ c = {:year => year}
172
+ next if candidate['LAST NAME'].blank?
173
+ next if candidate['DISTRICT'].blank?
174
+ # find the office_type
175
+ if candidate['FEC ID'].first != 'n'
176
+ c[:chamber] = candidate['FEC ID'].first
177
+ elsif candidate['DISTRICT'].first == 'S'
178
+ c[:chamber] = "S"
179
+ else
180
+ c[:chamber] = 'H'
181
+ end
182
+ c[:state] = candidate['STATE ABBREVIATION']
183
+ c[:district] = candidate['DISTRICT']
184
+ c[:party] = candidate['PARTY']
185
+ c[:incumbent] = candidate['INCUMBENT INDICATOR'] == '(I)' ? true : false
186
+ c[:fec_id] = candidate['FEC ID#']
187
+ c[:candidate_first] = candidate['FIRST NAME']
188
+ c[:candidate_last] = candidate['LAST NAME']
189
+ c[:candidate_name] = candidate['LAST NAME, FIRST']
190
+
191
+ c = update_vote_tallies(c, candidate, 'PRIMARY', 'PRIMARY %', 'RUNOFF', 'RUNOFF %', 'GENERAL', 'GENERAL %')
192
+ c = update_general_runoff(c, candidate, 'GE RUNOFF', 'GE RUNOFF %') if c[:state] == 'LA'
193
+
194
+ results << c
195
+ end
196
+ Result.create_from_results(results)
197
+ end
198
+
199
+ def process_2002(options={})
200
+ results = []
201
+ t = RemoteTable.new(url, :sheet => "2002 House & Senate Results")
202
+ rows = t.entries
203
+ rows = rows.select{|r| r['DISTRICT'] == options[:chamber]} if options[:chamber]
204
+ rows = rows.select{|r| r['STATE'] == options[:state]} if options[:state]
205
+ rows.each do |candidate|
206
+ c = {:year => year}
207
+ next if candidate['LAST NAME'].blank?
208
+ next if candidate['DISTRICT'].blank?
209
+ # find the office_type
210
+ if candidate['FEC ID'].first != 'n'
211
+ c[:chamber] = candidate['FEC ID'].first
212
+ elsif candidate['DISTRICT'].first == 'S'
213
+ c[:chamber] = "S"
214
+ else
215
+ c[:chamber] = 'H'
216
+ end
217
+ c[:state] = candidate['STATE']
218
+ c[:district] = candidate['DISTRICT']
219
+ c[:party] = candidate['PARTY']
220
+ c[:incumbent] = candidate['INCUMBENT INDICATOR'] == '(I)' ? true : false
221
+ c[:fec_id] = candidate['FEC ID#']
222
+ c[:candidate_first] = candidate['FIRST NAME']
223
+ c[:candidate_last] = candidate['LAST NAME']
224
+ c[:candidate_name] = candidate['LAST NAME, FIRST']
225
+
226
+ c = update_vote_tallies(c, candidate, 'PRIMARY RESULTS', 'PRIMARY %', 'RUNOFF RESULTS', 'RUNOFF %', 'GENERAL RESULTS', 'GENERAL %')
227
+ c = update_combined_totals(c, candidate, 'COMBINED GE PARTY TOTALS (NY, SC)', 'COMBINED % (NY, SC)') if ['SC', 'NY'].include?(c[:state])
228
+
229
+ results << c
230
+ end
231
+ Result.create_from_results(results)
232
+ end
233
+
234
+ def process_2000(options={})
235
+ results = []
236
+ url.each do |u|
237
+ t = RemoteTable.new(u.keys.first, :sheet => u.values.first)
238
+ rows = t.entries
239
+ rows = rows.select{|r| r['STATE'] == options[:state]} if options[:state]
240
+ rows.each do |candidate|
241
+ c = {:year => year}
242
+ next if candidate['NAME'][0..4] == 'Total'
243
+ next if candidate['DISTRICT'].blank?
244
+ if candidate['DISTRICT'].first == 'S'
245
+ c[:chamber] = "S"
246
+ else
247
+ c[:chamber] = 'H'
248
+ end
249
+ c[:state] = candidate['STATE']
250
+ c[:district] = candidate['DISTRICT']
251
+ c[:party] = candidate['PARTY']
252
+ c[:incumbent] = candidate['INCUMBENT INDICATOR'] == '(I)' ? true : false
253
+ c[:candidate_first], c[:candidate_last] = candidate['NAME'].split(', ')
254
+ c[:candidate_name] = candidate['NAME']
255
+
256
+ c = update_vote_tallies(c, candidate, 'PRIMARY RESULTS', 'PRIMARY %', 'RUNOFF RESULTS', 'RUNOFF %', 'GENERAL RESULTS', 'GENERAL %')
257
+ c = update_general_runoff(c, candidate, 'GENERAL RUNOFF RESULTS', 'GENERAL RUNOFF %') if c[:state] == 'LA'
258
+
259
+ results << c
260
+ end
261
+ end
262
+ if options[:chamber] == 'H'
263
+ results = results.select{|r| r[:chamber] != 'S'}
264
+ elsif options[:chamber] == 'S'
265
+ results = results.select{|r| r[:chamber] == 'S'}
266
+ end
267
+ Result.create_from_results(results)
268
+ end
269
+
270
+
271
+ def update_vote_tallies(c, candidate, primary_votes, primary_pct, runoff_votes, runoff_pct, general_votes, general_pct)
272
+ if candidate[primary_votes] == 'Unopposed'
273
+ c[:primary_unopposed] = true
274
+ c[:primary_votes] = nil
275
+ c[:primary_pct] = 100.0
276
+ else
277
+ c[:primary_unopposed] = false
278
+ c[:primary_votes] = candidate[primary_votes].to_i
279
+ c[:primary_pct] = candidate[primary_pct].to_f*100.0
280
+ end
281
+
282
+ if candidate[runoff_votes].blank?
283
+ c[:runoff_votes] = nil
284
+ c[:runoff_pct] = nil
285
+ else
286
+ c[:runoff_votes] = candidate[runoff_votes].to_i
287
+ c[:runoff_pct] = candidate[runoff_pct].to_f*100.0
288
+ end
289
+
290
+ if candidate[general_votes] == 'Unopposed'
291
+ c[:general_unopposed] = true
292
+ c[:general_votes] = nil
293
+ c[:general_pct] = 100.0
294
+ elsif candidate[general_votes].blank?
295
+ c[:general_unopposed] = false
296
+ c[:general_votes] = nil
297
+ c[:general_pct] = nil
298
+ else
299
+ c[:general_unopposed] = false
300
+ c[:general_votes] = candidate[general_votes].to_i
301
+ c[:general_pct] = candidate[general_pct].to_f*100.0
302
+ end
303
+ c
304
+ end
305
+
306
+ def update_general_runoff(c, candidate, general_runoff_votes, general_runoff_pct)
307
+ unless candidate[general_runoff_votes].blank?
308
+ c[:general_runoff_votes] = candidate[general_runoff_votes].to_i
309
+ c[:general_runoff_pct] = candidate[general_runoff_pct].to_f*100.0
310
+ end
311
+ c
312
+ end
313
+
314
+ def update_combined_totals(c, candidate, general_combined_party_votes, general_combined_party_pct)
315
+ unless candidate[general_combined_party_votes].blank?
316
+ c[:general_combined_party_votes] = candidate[general_combined_party_votes].to_i
317
+ c[:general_combined_party_pct] = candidate[general_combined_party_pct].to_f*100.0
318
+ end
319
+ c
320
+ end
321
+
322
+ end
323
+ end