Add poll stats by age and channel
This commit is contained in:
@@ -33,20 +33,7 @@ module Statisticable
|
||||
end
|
||||
|
||||
def participants_by_age
|
||||
age_groups.map do |start, finish|
|
||||
users = participants.where("date_of_birth > ? AND date_of_birth < ?",
|
||||
finish.years.ago.beginning_of_year,
|
||||
start.years.ago.end_of_year)
|
||||
|
||||
[
|
||||
"#{start} - #{finish}",
|
||||
{
|
||||
range: range_description(start, finish),
|
||||
count: users.count,
|
||||
percentage: calculate_percentage(users.count, total_participants)
|
||||
}
|
||||
]
|
||||
end.to_h
|
||||
participants_by_age_for(participants)
|
||||
end
|
||||
|
||||
def participants_by_geozone
|
||||
@@ -92,6 +79,30 @@ module Statisticable
|
||||
]
|
||||
end
|
||||
|
||||
def participants_by_age_for(users, relative_to: :participants)
|
||||
age_groups.map do |start, finish|
|
||||
group_count = users.between_ages(start, finish).count
|
||||
total_count = if relative_to == :participants
|
||||
total_participants
|
||||
else
|
||||
send(relative_to, start, finish).count
|
||||
end
|
||||
|
||||
[
|
||||
"#{start} - #{finish}",
|
||||
{
|
||||
range: range_description(start, finish),
|
||||
count: group_count,
|
||||
percentage: calculate_percentage(group_count, total_count)
|
||||
}
|
||||
]
|
||||
end.to_h
|
||||
end
|
||||
|
||||
def participants_between_ages(from, to)
|
||||
participants.between_ages(from, to)
|
||||
end
|
||||
|
||||
def calculate_percentage(fraction, total)
|
||||
return 0.0 if total.zero?
|
||||
|
||||
|
||||
@@ -18,9 +18,11 @@ class Poll::Stats
|
||||
total_male_web total_male_booth total_male_mail
|
||||
total_female_web total_female_booth total_female_mail
|
||||
male_web_percentage male_booth_percentage male_mail_percentage
|
||||
female_web_percentage female_booth_percentage female_mail_percentage]
|
||||
female_web_percentage female_booth_percentage female_mail_percentage
|
||||
web_participants_by_age booth_participants_by_age mail_participants_by_age]
|
||||
end
|
||||
|
||||
|
||||
def total_participants
|
||||
total_participants_web + total_participants_booth
|
||||
end
|
||||
@@ -40,6 +42,11 @@ class Poll::Stats
|
||||
User.where(id: voters.where(origin: channel).pluck(:user_id))
|
||||
end
|
||||
|
||||
define_method :"#{channel}_participants_by_age" do
|
||||
participants_by_age_for(send(:"#{channel}_participants"),
|
||||
relative_to: :participants_between_ages)
|
||||
end
|
||||
|
||||
%i[male female].each do |gender|
|
||||
define_method :"total_#{gender}_#{channel}" do
|
||||
send(:"#{channel}_participants").public_send(gender).count
|
||||
|
||||
@@ -72,6 +72,13 @@ class User < ApplicationRecord
|
||||
string = "%#{search_string}%"
|
||||
where("username ILIKE ? OR email ILIKE ? OR document_number ILIKE ?", string, string, string)
|
||||
end
|
||||
scope :between_ages, -> (from, to) do
|
||||
where(
|
||||
"date_of_birth > ? AND date_of_birth < ?",
|
||||
to.years.ago.beginning_of_year,
|
||||
from.years.ago.end_of_year
|
||||
)
|
||||
end
|
||||
|
||||
before_validation :clean_document_number
|
||||
|
||||
|
||||
@@ -15,7 +15,10 @@
|
||||
<%= link_to t("stats.polls.by_channel"), "#stats_by_channel" %>
|
||||
</li>
|
||||
<li>
|
||||
<%= link_to t("stats.polls.by_gender_and_channel"), "#stats_by_gender_and_channel" %>
|
||||
<%= link_to t("stats.polls.by_gender_and_channel"), "#stats_by_gender_and_channel"%>
|
||||
</li>
|
||||
<li>
|
||||
<%= link_to t("stats.polls.by_age_and_channel"), "#stats_by_age_and_channel" %>
|
||||
</li>
|
||||
<li>
|
||||
<%= link_to t("stats.polls.vote_by_channel"), "#vote_stats_by_channel" %>
|
||||
@@ -71,6 +74,39 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="stats_by_age_and_channel" class="stats-group">
|
||||
<h4><%= t("stats.polls.by_age_and_channel") %></h4>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th><%= t("stats.age") %></th>
|
||||
<% Poll::Stats::CHANNELS.each do |channel| %>
|
||||
<th><%= t("stats.polls.#{channel}") %></th>
|
||||
<% end %>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% @stats[:participants_by_age].keys.each do |age_range| %>
|
||||
<tr>
|
||||
<td><%= @stats[:participants_by_age][age_range][:range] %></td>
|
||||
|
||||
<% Poll::Stats::CHANNELS.each do |channel| %>
|
||||
<% group = @stats[:"#{channel}_participants_by_age"][age_range] %>
|
||||
<td>
|
||||
<div class="progress" tabindex="0">
|
||||
<span class="progress-meter" style="width: <%= group[:percentage] %>%">
|
||||
</span>
|
||||
</div>
|
||||
<%= "#{group[:count]} (#{number_to_stats_percentage(group[:percentage])})" %>
|
||||
</td>
|
||||
<% end %>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="vote_stats_by_channel" class="stats-group">
|
||||
<h4><%= t("stats.polls.vote_by_channel") %></h4>
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ en:
|
||||
polls:
|
||||
by_channel: "Participants by channel"
|
||||
by_gender_and_channel: "Participants by gender and channel"
|
||||
by_age_and_channel: "Participants by age and channel"
|
||||
vote_by_channel: "Vote type by channel"
|
||||
web: "Web"
|
||||
booth: "Booths"
|
||||
|
||||
@@ -19,6 +19,7 @@ es:
|
||||
polls:
|
||||
by_channel: "Participación por medio"
|
||||
by_gender_and_channel: "Participación por género y medio"
|
||||
by_age_and_channel: "Participación por edad y medio"
|
||||
vote_by_channel: "Votos emitidos por medio"
|
||||
web: "Web"
|
||||
booth: "Urnas"
|
||||
|
||||
@@ -221,6 +221,45 @@ describe Poll::Stats do
|
||||
expect(stats.male_booth_percentage).to eq(25.0)
|
||||
end
|
||||
end
|
||||
|
||||
describe "participants by age and channel" do
|
||||
before do
|
||||
4.times do
|
||||
create :poll_voter, :from_web, poll: poll,
|
||||
user: create(:user, :level_two, date_of_birth: 37.years.ago)
|
||||
end
|
||||
|
||||
3.times do
|
||||
create :poll_voter, :from_web, poll: poll,
|
||||
user: create(:user, :level_two, date_of_birth: 52.years.ago)
|
||||
end
|
||||
|
||||
2.times do
|
||||
create :poll_voter, :from_booth, poll: poll,
|
||||
user: create(:user, :level_two, date_of_birth: 37.years.ago)
|
||||
end
|
||||
|
||||
1.times do
|
||||
create :poll_voter, :from_booth, poll: poll,
|
||||
user: create(:user, :level_two, date_of_birth: 52.years.ago)
|
||||
end
|
||||
end
|
||||
|
||||
it "calculates the count of users by channel and age" do
|
||||
expect(stats.web_participants_by_age["35 - 39"][:count]).to eq(4)
|
||||
expect(stats.web_participants_by_age["50 - 54"][:count]).to eq(3)
|
||||
expect(stats.booth_participants_by_age["35 - 39"][:count]).to eq(2)
|
||||
expect(stats.booth_participants_by_age["50 - 54"][:count]).to eq(1)
|
||||
end
|
||||
|
||||
it "calculates percentage relative to the participants for that age" do
|
||||
expect(stats.web_participants_by_age["35 - 39"][:percentage]).to eq(66.667)
|
||||
expect(stats.booth_participants_by_age["35 - 39"][:percentage]).to eq(33.333)
|
||||
|
||||
expect(stats.web_participants_by_age["50 - 54"][:percentage]).to eq(75.0)
|
||||
expect(stats.booth_participants_by_age["50 - 54"][:percentage]).to eq(25.0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#generate" do
|
||||
|
||||
Reference in New Issue
Block a user