Merge pull request #5533 from consuldemocracy/age_stats
Calculate age stats based on the participation date
This commit is contained in:
@@ -37,6 +37,10 @@ class Budget::Stats
|
|||||||
budget.finished?
|
budget.finished?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def participation_date
|
||||||
|
send("#{phases.last}_phase_participation_date")
|
||||||
|
end
|
||||||
|
|
||||||
def total_participants
|
def total_participants
|
||||||
participants.distinct.count
|
participants.distinct.count
|
||||||
end
|
end
|
||||||
@@ -98,6 +102,14 @@ class Budget::Stats
|
|||||||
phases.map { |phase| self.class.send("#{phase}_phase_methods") }.flatten
|
phases.map { |phase| self.class.send("#{phase}_phase_methods") }.flatten
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def support_phase_participation_date
|
||||||
|
budget.phases.selecting.ends_at
|
||||||
|
end
|
||||||
|
|
||||||
|
def vote_phase_participation_date
|
||||||
|
budget.phases.balloting.ends_at
|
||||||
|
end
|
||||||
|
|
||||||
def participant_ids
|
def participant_ids
|
||||||
phases.map { |phase| send("participant_ids_#{phase}_phase") }.flatten.uniq
|
phases.map { |phase| send("participant_ids_#{phase}_phase") }.flatten.uniq
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -63,7 +63,11 @@ module Statisticable
|
|||||||
end
|
end
|
||||||
|
|
||||||
def age?
|
def age?
|
||||||
participants.between_ages(age_groups.flatten.min, age_groups.flatten.max).any?
|
participants.between_ages(
|
||||||
|
age_groups.flatten.min,
|
||||||
|
age_groups.flatten.max,
|
||||||
|
at_time: participation_date
|
||||||
|
).any?
|
||||||
end
|
end
|
||||||
|
|
||||||
def geozone?
|
def geozone?
|
||||||
@@ -96,7 +100,7 @@ module Statisticable
|
|||||||
|
|
||||||
def participants_by_age
|
def participants_by_age
|
||||||
age_groups.to_h do |start, finish|
|
age_groups.to_h do |start, finish|
|
||||||
count = participants.between_ages(start, finish).count
|
count = participants.between_ages(start, finish, at_time: participation_date).count
|
||||||
|
|
||||||
[
|
[
|
||||||
"#{start} - #{finish}",
|
"#{start} - #{finish}",
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ class Poll::Stats
|
|||||||
total_participants_web + total_participants_booth
|
total_participants_web + total_participants_booth
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def participation_date
|
||||||
|
poll.ends_at
|
||||||
|
end
|
||||||
|
|
||||||
def channels
|
def channels
|
||||||
CHANNELS.select { |channel| send(:"total_participants_#{channel}") > 0 }
|
CHANNELS.select { |channel| send(:"total_participants_#{channel}") > 0 }
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -119,12 +119,8 @@ class User < ApplicationRecord
|
|||||||
search = "%#{search_string.strip}%"
|
search = "%#{search_string.strip}%"
|
||||||
where("username ILIKE ? OR email ILIKE ? OR document_number ILIKE ?", search, search, search)
|
where("username ILIKE ? OR email ILIKE ? OR document_number ILIKE ?", search, search, search)
|
||||||
end
|
end
|
||||||
scope :between_ages, ->(from, to) do
|
scope :between_ages, ->(from, to, at_time: Time.current) do
|
||||||
where(
|
where(date_of_birth: (at_time - to.years).beginning_of_year..(at_time - from.years).end_of_year)
|
||||||
"date_of_birth > ? AND date_of_birth < ?",
|
|
||||||
to.years.ago.beginning_of_year,
|
|
||||||
from.years.ago.end_of_year
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
before_validation :clean_document_number
|
before_validation :clean_document_number
|
||||||
|
|||||||
@@ -157,27 +157,79 @@ describe Budget::Stats do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe "#participants_by_age" do
|
describe "#participants_by_age" do
|
||||||
before do
|
it "returns the age groups hash" do
|
||||||
[21, 22, 23, 23, 34, 42, 43, 44, 50, 51].each do |age|
|
[21, 22, 23, 23, 34, 42, 43, 44, 50, 51].each do |age|
|
||||||
create(:user, date_of_birth: age.years.ago)
|
create(:user, date_of_birth: age.years.ago)
|
||||||
end
|
end
|
||||||
|
|
||||||
allow(stats).to receive(:participants).and_return(User.all)
|
allow(stats).to receive(:participants).and_return(User.all)
|
||||||
|
|
||||||
|
expect(stats.participants_by_age["16 - 19"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["20 - 24"][:count]).to eq 4
|
||||||
|
expect(stats.participants_by_age["25 - 29"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["30 - 34"][:count]).to eq 1
|
||||||
|
expect(stats.participants_by_age["35 - 39"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["40 - 44"][:count]).to eq 3
|
||||||
|
expect(stats.participants_by_age["45 - 49"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["50 - 54"][:count]).to eq 2
|
||||||
|
expect(stats.participants_by_age["55 - 59"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["60 - 64"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["65 - 69"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["70 - 74"][:count]).to eq 0
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns the age groups hash" do
|
it "returns stats based on what happened when the voting took place" do
|
||||||
expect(stats.participants_by_age["16 - 19"][:count]).to be 0
|
travel_to(50.years.ago) do
|
||||||
expect(stats.participants_by_age["20 - 24"][:count]).to be 4
|
[21, 22, 23, 23, 34, 42, 43, 44, 50, 51].each do |age|
|
||||||
expect(stats.participants_by_age["25 - 29"][:count]).to be 0
|
create(:user, date_of_birth: age.years.ago)
|
||||||
expect(stats.participants_by_age["30 - 34"][:count]).to be 1
|
end
|
||||||
expect(stats.participants_by_age["35 - 39"][:count]).to be 0
|
|
||||||
expect(stats.participants_by_age["40 - 44"][:count]).to be 3
|
create(:budget, :finished)
|
||||||
expect(stats.participants_by_age["45 - 49"][:count]).to be 0
|
end
|
||||||
expect(stats.participants_by_age["50 - 54"][:count]).to be 2
|
|
||||||
expect(stats.participants_by_age["55 - 59"][:count]).to be 0
|
stats = Budget::Stats.new(Budget.last)
|
||||||
expect(stats.participants_by_age["60 - 64"][:count]).to be 0
|
allow(stats).to receive(:participants).and_return(User.all)
|
||||||
expect(stats.participants_by_age["65 - 69"][:count]).to be 0
|
|
||||||
expect(stats.participants_by_age["70 - 74"][:count]).to be 0
|
expect(stats.participants_by_age["16 - 19"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["20 - 24"][:count]).to eq 4
|
||||||
|
expect(stats.participants_by_age["25 - 29"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["30 - 34"][:count]).to eq 1
|
||||||
|
expect(stats.participants_by_age["35 - 39"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["40 - 44"][:count]).to eq 3
|
||||||
|
expect(stats.participants_by_age["45 - 49"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["50 - 54"][:count]).to eq 2
|
||||||
|
expect(stats.participants_by_age["55 - 59"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["60 - 64"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["65 - 69"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["70 - 74"][:count]).to eq 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#participation_date", :with_frozen_time do
|
||||||
|
let(:budget) do
|
||||||
|
create(:budget).tap do |budget|
|
||||||
|
budget.phases.informing.update!(starts_at: 10.months.ago, ends_at: 9.months.ago)
|
||||||
|
budget.phases.accepting.update!(starts_at: 9.months.ago, ends_at: 8.months.ago)
|
||||||
|
budget.phases.reviewing.update!(starts_at: 8.months.ago, ends_at: 7.months.ago)
|
||||||
|
budget.phases.selecting.update!(starts_at: 7.months.ago, ends_at: 6.months.ago)
|
||||||
|
budget.phases.valuating.update!(starts_at: 6.months.ago, ends_at: 5.months.ago)
|
||||||
|
budget.phases.publishing_prices.update!(starts_at: 5.months.ago, ends_at: 4.months.ago)
|
||||||
|
budget.phases.balloting.update!(starts_at: 4.months.ago, ends_at: 3.months.ago)
|
||||||
|
budget.phases.reviewing_ballots.update!(starts_at: 3.months.ago, ends_at: 2.months.ago)
|
||||||
|
budget.phases.finished.update!(starts_at: 2.months.ago, ends_at: 1.month.ago)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the date when balloting ended on finished budgets" do
|
||||||
|
budget.update!(phase: "finished")
|
||||||
|
|
||||||
|
expect(stats.participation_date).to eq 3.months.ago
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the date when selecting ended on unfinished budgets" do
|
||||||
|
budget.update!(phase: "reviewing_ballots")
|
||||||
|
|
||||||
|
expect(stats.participation_date).to eq 6.months.ago
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -165,6 +165,46 @@ describe Poll::Stats do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#participants_by_age" do
|
||||||
|
it "returns stats based on what happened when the voting took place" do
|
||||||
|
travel_to(100.years.ago) do
|
||||||
|
[16, 18, 32, 32, 33, 34, 64, 65, 71, 73, 90, 99, 105].each do |age|
|
||||||
|
create(:user, date_of_birth: age.years.ago)
|
||||||
|
end
|
||||||
|
|
||||||
|
create(:poll, starts_at: 1.minute.from_now, ends_at: 2.minutes.from_now)
|
||||||
|
end
|
||||||
|
|
||||||
|
stats = Poll::Stats.new(Poll.last)
|
||||||
|
allow(stats).to receive(:participants).and_return(User.all)
|
||||||
|
|
||||||
|
expect(stats.participants_by_age["16 - 19"][:count]).to eq 2
|
||||||
|
expect(stats.participants_by_age["20 - 24"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["25 - 29"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["30 - 34"][:count]).to eq 4
|
||||||
|
expect(stats.participants_by_age["35 - 39"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["40 - 44"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["45 - 49"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["50 - 54"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["55 - 59"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["60 - 64"][:count]).to eq 1
|
||||||
|
expect(stats.participants_by_age["65 - 69"][:count]).to eq 1
|
||||||
|
expect(stats.participants_by_age["70 - 74"][:count]).to eq 2
|
||||||
|
expect(stats.participants_by_age["75 - 79"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["80 - 84"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["85 - 89"][:count]).to eq 0
|
||||||
|
expect(stats.participants_by_age["90 - 300"][:count]).to eq 3
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#participation_date", :with_frozen_time do
|
||||||
|
let(:poll) { create(:poll, starts_at: 3.years.ago, ends_at: 2.years.ago) }
|
||||||
|
|
||||||
|
it "returns the date when the poll finishes" do
|
||||||
|
expect(stats.participation_date).to eq 2.years.ago
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "#participants_by_geozone" do
|
describe "#participants_by_geozone" do
|
||||||
it "groups by geozones in alphabetic order" do
|
it "groups by geozones in alphabetic order" do
|
||||||
%w[Oceania Eurasia Eastasia].each { |name| create(:geozone, name: name) }
|
%w[Oceania Eurasia Eastasia].each { |name| create(:geozone, name: name) }
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ describe Statisticable do
|
|||||||
def participants
|
def participants
|
||||||
User.all
|
User.all
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def participation_date
|
||||||
|
Time.current
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
stub_const("DummyStats", dummy_stats)
|
stub_const("DummyStats", dummy_stats)
|
||||||
@@ -80,6 +84,17 @@ describe Statisticable do
|
|||||||
expect(stats.age?).to be true
|
expect(stats.age?).to be true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "Partipation took place a long time ago" do
|
||||||
|
before do
|
||||||
|
create(:user, date_of_birth: 2000.years.ago)
|
||||||
|
allow(stats).to receive(:participation_date).and_return(1900.years.ago)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is true" do
|
||||||
|
expect(stats.age?).to be true
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#geozone?" do
|
describe "#geozone?" do
|
||||||
|
|||||||
@@ -423,6 +423,41 @@ describe User do
|
|||||||
expect(User.by_username_email_or_document_number(" 12345678Z ")).to eq [larry]
|
expect(User.by_username_email_or_document_number(" 12345678Z ")).to eq [larry]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe ".between_ages" do
|
||||||
|
it "returns users between certain ages, including both" do
|
||||||
|
[21, 22, 23, 23, 42, 43, 44, 51].each do |age|
|
||||||
|
create(:user, date_of_birth: age.years.ago)
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(User.between_ages(0, 20).count).to eq 0
|
||||||
|
expect(User.between_ages(0, 21).count).to eq 1
|
||||||
|
expect(User.between_ages(21, 23).count).to eq 4
|
||||||
|
expect(User.between_ages(24, 41).count).to eq 0
|
||||||
|
expect(User.between_ages(41, 45).count).to eq 3
|
||||||
|
expect(User.between_ages(51, 100).count).to eq 1
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns users between certain ages on a reference date" do
|
||||||
|
reference_date = 20.years.ago
|
||||||
|
|
||||||
|
travel_to(reference_date) do
|
||||||
|
[21, 22, 23, 23, 34, 42, 43, 44, 50, 51].each do |age|
|
||||||
|
create(:user, date_of_birth: age.years.ago)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(User.between_ages(0, 20, at_time: reference_date).count).to eq 0
|
||||||
|
expect(User.between_ages(21, 25, at_time: reference_date).count).to eq 4
|
||||||
|
expect(User.between_ages(25, 30, at_time: reference_date).count).to eq 0
|
||||||
|
expect(User.between_ages(30, 34, at_time: reference_date).count).to eq 1
|
||||||
|
expect(User.between_ages(35, 39, at_time: reference_date).count).to eq 0
|
||||||
|
expect(User.between_ages(40, 44, at_time: reference_date).count).to eq 3
|
||||||
|
expect(User.between_ages(45, 49, at_time: reference_date).count).to eq 0
|
||||||
|
expect(User.between_ages(50, 54, at_time: reference_date).count).to eq 2
|
||||||
|
expect(User.between_ages(55, 100, at_time: reference_date).count).to eq 0
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "self.search" do
|
describe "self.search" do
|
||||||
|
|||||||
Reference in New Issue
Block a user