Extract class to manage GeozoneStats
Even if this class looks very simple now, we're trying a few things related to these stats. Having a class for it makes future changes easier and, if there weren't any future changes, at least it makes current experiments easier. Note we keep the method `participants_by_geozone` to return a hash because we're caching the stats and storing GeozoneStats objects would need a lot more memory and we would get an error.
This commit is contained in:
@@ -69,19 +69,21 @@ module Statisticable
|
|||||||
end
|
end
|
||||||
|
|
||||||
def participants_by_geozone
|
def participants_by_geozone
|
||||||
geozones.map do |geozone|
|
geozone_stats.map do |stats|
|
||||||
count = participants.where(geozone: geozone).count
|
|
||||||
|
|
||||||
[
|
[
|
||||||
geozone.name,
|
stats.name,
|
||||||
{
|
{
|
||||||
count: count,
|
count: stats.count,
|
||||||
percentage: calculate_percentage(count, total_participants)
|
percentage: stats.percentage
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
end.to_h
|
end.to_h
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def calculate_percentage(fraction, total)
|
||||||
|
PercentageCalculator.calculate(fraction, total)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def base_stats_methods
|
def base_stats_methods
|
||||||
@@ -124,10 +126,8 @@ module Statisticable
|
|||||||
Geozone.all.order("name")
|
Geozone.all.order("name")
|
||||||
end
|
end
|
||||||
|
|
||||||
def calculate_percentage(fraction, total)
|
def geozone_stats
|
||||||
return 0.0 if total.zero?
|
geozones.map { |geozone| GeozoneStats.new(geozone, participants) }
|
||||||
|
|
||||||
(fraction * 100.0 / total).round(3)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def range_description(start, finish)
|
def range_description(start, finish)
|
||||||
|
|||||||
24
lib/geozone_stats.rb
Normal file
24
lib/geozone_stats.rb
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
class GeozoneStats
|
||||||
|
attr_reader :geozone, :participants
|
||||||
|
|
||||||
|
def initialize(geozone, participants)
|
||||||
|
@geozone = geozone
|
||||||
|
@participants = participants
|
||||||
|
end
|
||||||
|
|
||||||
|
def geozone_participants
|
||||||
|
participants.where(geozone: geozone)
|
||||||
|
end
|
||||||
|
|
||||||
|
def name
|
||||||
|
geozone.name
|
||||||
|
end
|
||||||
|
|
||||||
|
def count
|
||||||
|
geozone_participants.count
|
||||||
|
end
|
||||||
|
|
||||||
|
def percentage
|
||||||
|
PercentageCalculator.calculate(count, participants.count)
|
||||||
|
end
|
||||||
|
end
|
||||||
7
lib/percentage_calculator.rb
Normal file
7
lib/percentage_calculator.rb
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
module PercentageCalculator
|
||||||
|
def self.calculate(fraction, total)
|
||||||
|
return 0.0 if total.zero?
|
||||||
|
|
||||||
|
(fraction * 100.0 / total).round(3)
|
||||||
|
end
|
||||||
|
end
|
||||||
44
spec/lib/geozone_stats_spec.rb
Normal file
44
spec/lib/geozone_stats_spec.rb
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
require "rails_helper"
|
||||||
|
|
||||||
|
describe GeozoneStats do
|
||||||
|
let(:winterfell) { create(:geozone, name: "Winterfell") }
|
||||||
|
let(:riverlands) { create(:geozone, name: "Riverlands") }
|
||||||
|
|
||||||
|
describe "#name" do
|
||||||
|
let(:stats) { GeozoneStats.new(winterfell, []) }
|
||||||
|
|
||||||
|
it "returns the geozone name" do
|
||||||
|
expect(stats.name).to eq "Winterfell"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#count" do
|
||||||
|
before do
|
||||||
|
2.times { create(:user, geozone: winterfell) }
|
||||||
|
1.times { create(:user, geozone: riverlands) }
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:winterfell_stats) { GeozoneStats.new(winterfell, User.all) }
|
||||||
|
let(:riverlands_stats) { GeozoneStats.new(riverlands, User.all) }
|
||||||
|
|
||||||
|
it "counts participants from the geozone" do
|
||||||
|
expect(winterfell_stats.count).to eq 2
|
||||||
|
expect(riverlands_stats.count).to eq 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#percentage" do
|
||||||
|
before do
|
||||||
|
2.times { create(:user, geozone: winterfell) }
|
||||||
|
1.times { create(:user, geozone: riverlands) }
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:winterfell_stats) { GeozoneStats.new(winterfell, User.all) }
|
||||||
|
let(:riverlands_stats) { GeozoneStats.new(riverlands, User.all) }
|
||||||
|
|
||||||
|
it "calculates percentage relative to the amount of participants" do
|
||||||
|
expect(winterfell_stats.percentage).to eq 66.667
|
||||||
|
expect(riverlands_stats.percentage).to eq 33.333
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user