From 2c0539d29e8d79358a4809affd83a15955cfddf3 Mon Sep 17 00:00:00 2001 From: Adrian Short Date: Mon, 20 Aug 2018 13:33:57 +0100 Subject: [PATCH] Reorganise page generating blocks into separate functions --- bin/build | 377 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 198 insertions(+), 179 deletions(-) diff --git a/bin/build b/bin/build index 60265dc..515f48e 100755 --- a/bin/build +++ b/bin/build @@ -13,13 +13,6 @@ OUTPUT_DIR = '_site' VIEWS_DIR = File.join('..', 'views') LAYOUT_FN = File.join(VIEWS_DIR, 'layout.haml') -@log = Logger.new($stdout) -@log.level = Logger::INFO -@log.info "Build starts." -@log.info "Output directory is: #{OUTPUT_DIR}" - -@pages = 0 - def write_page(path_items, template, locals = {}) dir = File.join(path_items) FileUtils.mkdir_p(dir) @@ -38,211 +31,237 @@ def write_page(path_items, template, locals = {}) # https://support.google.com/webmasters/answer/183668?hl=en&ref_topic=4581190 end -working_dir = File.join(Dir.pwd, OUTPUT_DIR) -# Recursively delete working directory to ensure no redundant files are left behind from previous builds. -FileUtils.rm_rf(working_dir) -Dir.mkdir(working_dir) unless File.directory?(working_dir) -Dir.chdir(working_dir) - -# Copy `public` dir to output dir -FileUtils.copy_entry(File.join('..', 'public'), '.') - -# Home page -locals = { - future_elections: Election.future, - past_elections: Election.past -} -write_page('.', 'index', locals) - -# Election pages -Election.each do |e| - locals = { - body: Body.first(:slug => e.body.slug), - election: Election.first(:body => e.body, :d => e.d), - elections_for_this_body: Election.all(:body => e.body, :order => [:d]), - total_seats: Candidacy.sum(:seats, :election => e), - total_votes: Candidacy.sum(:votes, :election => e) - } - - # There's got to be a better way to do this, either with SQL or Datamapper - locals['total_districts'] = repository(:default).adapter.select(" - SELECT district_id - FROM candidacies - WHERE election_id = ? - GROUP BY district_id - ORDER BY district_id - ", e.id).count - - locals['results_by_party'] = repository(:default).adapter.select(" - SELECT - p.colour, - p.name, - SUM(c.votes) AS votez, - SUM(c.seats) AS seatz, - COUNT(*) AS cands - - FROM candidacies c - - LEFT JOIN parties p ON p.id = c.party_id - - WHERE c.election_id = ? - - GROUP BY c.party_id, p.colour, p.name +def gen_info_pages + write_page('about', 'about') + write_page('guides', 'guides') + write_page(%w(guides how-the-parliament-election-works), 'parliament') + write_page(%w(guides how-the-council-election-works), 'election') +end - ORDER BY seatz DESC, votez DESC - ", e.id) +def gen_bodies_pages + # Bodies index + dir = 'bodies' + FileUtils.mkdir_p(dir) + @log.debug dir + fn = File.join(dir, 'index.html') + FileUtils.touch(fn) # empty file + @log.info fn - write_page(['bodies', e.body.slug, 'elections', e.d.to_s], 'electionsummary', locals) + # Body detail pages + Body.each do |b| + locals = { + body: b, + districts: District.all(:body => b, :order => [:name]) + } + + locals['elections'] = repository(:default).adapter.select(" + SELECT + e.id, + e.kind, + e.d, + SUM(p.ballot_papers_issued)::float / SUM(p.electorate) * 100 AS turnout_percent + + FROM elections e + + LEFT JOIN polls p + ON e.id = p.election_id + + WHERE e.body_id = ? + + GROUP BY p.election_id, e.id + ORDER BY e.d DESC + ", b.id) + + write_page(['bodies', b.slug], 'body', locals) + + # Districts for this body + b.districts.each do |d| + locals = { + district: d, + body: b + } + write_page(['bodies', b.slug, b.districts_name, d.slug], 'district', locals) + end + end +end +def gen_candidates_pages + # Candidate index + locals = { candidates: Candidate.all(:order => [ :surname, :forenames ]) } + write_page('candidates', 'candidates', locals) - # District results for this election (resultsdistrict) - # Loop through all districts in this election - e.candidacies.districts.each do |d| - total_seats = Candidacy.sum(:seats, :district => d, :election => e) - total_votes = Candidacy.sum(:votes, :district => d, :election => e) - poll = Poll.get(d.id, e.id) - + # Candidate pages + # FIXME: What do we do about deleted candidates/redirects? + Candidate.each do |c| locals = { - district: d, - body: d.body, - election: e, - candidacies: Candidacy.all(:district => d, :election => e, :order => [:position]), - total_votes: total_votes, - total_candidates: Candidacy.count(:district => d, :election => e), - total_seats: total_seats, - districts_in_this_election: e.candidacies.districts, - poll: poll + candidate: c } - locals['share_message'] = nil - if total_seats == 1 - locals['share_denominator'] = total_votes - elsif poll && poll.valid_ballot_papers - locals['share_denominator'] = poll.valid_ballot_papers - else - locals['share_denominator'] = total_votes / total_seats - locals['share_message'] = "The vote share percentages have been estimated as we don't have data for the number of valid ballot papers in this poll." - end - - # Postgres: All the columns selected when using GROUP BY must either be aggregate functions or appear in the GROUP BY clause - locals['results_by_party'] = repository(:default).adapter.select(" + locals['candidacies'] = repository(:default).adapter.select(" SELECT + e.d, + c.*, p.name AS party_name, p.colour AS party_colour, - COUNT(c.id) AS num_candidates, - SUM(c.seats) AS num_seats, - SUM(c.votes) AS total_votes + b.name AS body_name, + b.slug AS body_slug, + b.districts_name AS districts_name, + d.name AS district_name, + d.slug AS district_slug FROM candidacies c - LEFT JOIN parties p + INNER JOIN elections e + ON c.election_id = e.id + + INNER JOIN parties p ON c.party_id = p.id - WHERE c.district_id = ? - AND c.election_id = ? + INNER JOIN bodies b + ON e.body_id = b.id + + INNER JOIN districts d + ON c.district_id = d.id - GROUP BY p.name, p.colour + WHERE c.candidate_id = ? - ORDER BY total_votes DESC - ", d.id, e.id) + ORDER BY d + ", c.id) - write_page(['bodies', e.body.slug, 'elections', e.d.to_s, e.body.districts_name, d.slug], 'resultsdistrict', locals) + write_page(['candidates', c.id.to_s], 'candidate', locals) end end -# Candidate index -locals = { candidates: Candidate.all(:order => [ :surname, :forenames ]) } -write_page('candidates', 'candidates', locals) - -# Candidate pages -# FIXME: What do we do about deleted candidates/redirects? -Candidate.each do |c| - locals = { - candidate: c - } - - locals['candidacies'] = repository(:default).adapter.select(" - SELECT - e.d, - c.*, - p.name AS party_name, - p.colour AS party_colour, - b.name AS body_name, - b.slug AS body_slug, - b.districts_name AS districts_name, - d.name AS district_name, - d.slug AS district_slug - - FROM candidacies c - - INNER JOIN elections e - ON c.election_id = e.id - - INNER JOIN parties p - ON c.party_id = p.id - - INNER JOIN bodies b - ON e.body_id = b.id +def gen_elections_pages + # Election pages + Election.each do |e| + locals = { + body: Body.first(:slug => e.body.slug), + election: Election.first(:body => e.body, :d => e.d), + elections_for_this_body: Election.all(:body => e.body, :order => [:d]), + total_seats: Candidacy.sum(:seats, :election => e), + total_votes: Candidacy.sum(:votes, :election => e) + } - INNER JOIN districts d - ON c.district_id = d.id + # There's got to be a better way to do this, either with SQL or Datamapper + locals['total_districts'] = repository(:default).adapter.select(" + SELECT district_id + FROM candidacies + WHERE election_id = ? + GROUP BY district_id + ORDER BY district_id + ", e.id).count - WHERE c.candidate_id = ? + locals['results_by_party'] = repository(:default).adapter.select(" + SELECT + p.colour, + p.name, + SUM(c.votes) AS votez, + SUM(c.seats) AS seatz, + COUNT(*) AS cands - ORDER BY d - ", c.id) + FROM candidacies c - write_page(['candidates', c.id.to_s], 'candidate', locals) + LEFT JOIN parties p ON p.id = c.party_id + + WHERE c.election_id = ? + + GROUP BY c.party_id, p.colour, p.name + + ORDER BY seatz DESC, votez DESC + ", e.id) + + write_page(['bodies', e.body.slug, 'elections', e.d.to_s], 'electionsummary', locals) + + + # District results for this election (resultsdistrict) + # Loop through all districts in this election + e.candidacies.districts.each do |d| + total_seats = Candidacy.sum(:seats, :district => d, :election => e) + total_votes = Candidacy.sum(:votes, :district => d, :election => e) + poll = Poll.get(d.id, e.id) + + locals = { + district: d, + body: d.body, + election: e, + candidacies: Candidacy.all(:district => d, :election => e, :order => [:position]), + total_votes: total_votes, + total_candidates: Candidacy.count(:district => d, :election => e), + total_seats: total_seats, + districts_in_this_election: e.candidacies.districts, + poll: poll + } + + locals['share_message'] = nil + if total_seats == 1 + locals['share_denominator'] = total_votes + elsif poll && poll.valid_ballot_papers + locals['share_denominator'] = poll.valid_ballot_papers + else + locals['share_denominator'] = total_votes / total_seats + locals['share_message'] = "The vote share percentages have been estimated as we don't have data for the number of valid ballot papers in this poll." + end + + # Postgres: All the columns selected when using GROUP BY must either be aggregate functions or appear in the GROUP BY clause + locals['results_by_party'] = repository(:default).adapter.select(" + SELECT + p.name AS party_name, + p.colour AS party_colour, + COUNT(c.id) AS num_candidates, + SUM(c.seats) AS num_seats, + SUM(c.votes) AS total_votes + + FROM candidacies c + + LEFT JOIN parties p + ON c.party_id = p.id + + WHERE c.district_id = ? + AND c.election_id = ? + + GROUP BY p.name, p.colour + + ORDER BY total_votes DESC + ", d.id, e.id) + + write_page(['bodies', e.body.slug, 'elections', e.d.to_s, e.body.districts_name, d.slug], 'resultsdistrict', locals) + end + end end -# Bodies index -dir = 'bodies' -FileUtils.mkdir_p(dir) -@log.debug dir -fn = File.join(dir, 'index.html') -FileUtils.touch(fn) # empty file -@log.info fn - -# Body detail pages -Body.each do |b| +def gen_homepage locals = { - body: b, - districts: District.all(:body => b, :order => [:name]) + future_elections: Election.future, + past_elections: Election.past } - - locals['elections'] = repository(:default).adapter.select(" - SELECT - e.id, - e.kind, - e.d, - SUM(p.ballot_papers_issued)::float / SUM(p.electorate) * 100 AS turnout_percent - - FROM elections e - - LEFT JOIN polls p - ON e.id = p.election_id + write_page('.', 'index', locals) +end - WHERE e.body_id = ? +def create_output_dir + working_dir = File.join(Dir.pwd, OUTPUT_DIR) + # Recursively delete working directory to ensure no redundant files are left behind from previous builds. + FileUtils.rm_rf(working_dir) + Dir.mkdir(working_dir) unless File.directory?(working_dir) + Dir.chdir(working_dir) + + # Copy `public` dir to output dir + FileUtils.copy_entry(File.join('..', 'public'), '.') +end - GROUP BY p.election_id, e.id - ORDER BY e.d DESC - ", b.id) +@log = Logger.new($stdout) +@log.level = Logger::INFO +@log.info "Build starts." +@log.info "Output directory is: #{OUTPUT_DIR}" - write_page(['bodies', b.slug], 'body', locals) +@pages = 0 # count the number of pages generated - # Districts for this body - b.districts.each do |d| - locals = { - district: d, - body: b - } - write_page(['bodies', b.slug, b.districts_name, d.slug], 'district', locals) - end -end +create_output_dir -write_page('about', 'about') -write_page('guides', 'guides') -write_page(%w(guides how-the-parliament-election-works), 'parliament') -write_page(%w(guides how-the-council-election-works), 'election') +gen_homepage +gen_elections_pages +gen_bodies_pages +gen_info_pages +gen_candidates_pages @log.info "Build complete. %d pages generated in %0.2f seconds." % [ @pages, Process.clock_gettime(Process::CLOCK_MONOTONIC) - t_start ]