Переглянути джерело

Reorganise page generating blocks into separate functions

tags/v2.0.0
Adrian Short 6 роки тому
джерело
коміт
2c0539d29e
1 змінених файлів з 198 додано та 179 видалено
  1. +198
    -179
      bin/build

+ 198
- 179
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 ]

Завантаження…
Відмінити
Зберегти