diff --git a/app/models/concerns/statisticable.rb b/app/models/concerns/statisticable.rb index a19d9d962..5e62e31a2 100644 --- a/app/models/concerns/statisticable.rb +++ b/app/models/concerns/statisticable.rb @@ -69,19 +69,21 @@ module Statisticable end def participants_by_geozone - geozones.map do |geozone| - count = participants.where(geozone: geozone).count - + geozone_stats.map do |stats| [ - geozone.name, + stats.name, { - count: count, - percentage: calculate_percentage(count, total_participants) + count: stats.count, + percentage: stats.percentage } ] end.to_h end + def calculate_percentage(fraction, total) + PercentageCalculator.calculate(fraction, total) + end + private def base_stats_methods @@ -124,10 +126,8 @@ module Statisticable Geozone.all.order("name") end - def calculate_percentage(fraction, total) - return 0.0 if total.zero? - - (fraction * 100.0 / total).round(3) + def geozone_stats + geozones.map { |geozone| GeozoneStats.new(geozone, participants) } end def range_description(start, finish) diff --git a/lib/geozone_stats.rb b/lib/geozone_stats.rb new file mode 100644 index 000000000..6b7971610 --- /dev/null +++ b/lib/geozone_stats.rb @@ -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 diff --git a/lib/percentage_calculator.rb b/lib/percentage_calculator.rb new file mode 100644 index 000000000..bb8f3d355 --- /dev/null +++ b/lib/percentage_calculator.rb @@ -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 diff --git a/spec/lib/geozone_stats_spec.rb b/spec/lib/geozone_stats_spec.rb new file mode 100644 index 000000000..570315406 --- /dev/null +++ b/spec/lib/geozone_stats_spec.rb @@ -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