Skip to content

Commit

Permalink
errors and corrections
Browse files Browse the repository at this point in the history
  • Loading branch information
glennj committed Dec 19, 2024
1 parent 3661847 commit 79f05e3
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 167 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def status(exercise)
completed_exercises = completions[exercise[:slug]].to_a
return :in_progress if completed_exercises.blank?

num_completions_in_2024 = completed_exercises.count { |(_, date)| date[0..3] == '2024' || date == '2025-01-01' || date == '2023-12-31' }
num_completions_in_2024 = completed_exercises.count { |(_, date)| date >= '2023-12-31' && date <= '2025-01-01' }
return :in_progress if num_completions_in_2024.zero?
return :bronze if num_completions_in_2024 < 3

Expand All @@ -86,7 +86,7 @@ def completions
user.solutions.completed.
joins(exercise: :track).
where(exercise: { slug: EXERCISES.pluck(:slug) }).
pluck('exercise.slug', 'tracks.slug', "DATE_FORMAT(completed_at, '%Y-%m-%d')").
pluck('exercise.slug', 'tracks.slug', Arel.sql("DATE_FORMAT(completed_at, '%Y-%m-%d')")).
group_by(&:first).
transform_values { |entries| entries.map { |entry| entry[1..] } }
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ class LarisaLatyninaBadge < Badge
'Earned 48 medals in the #48in24 challenge'

def award_to?(user)
def exercises = User::Challenges::FeaturedExercisesProgress48In24.(user)
exercises.none? {|e| e.status == :in_progress}
exercises = User::Challenges::FeaturedExercisesProgress48In24.(user)
exercises.none? { |e| e.status == :in_progress }
end

def send_email_on_acquisition? = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ class PaavoNurmiBadge < Badge
'Earned 48 gold or silver medals in the #48in24 challenge'

def award_to?(user)
def exercises = User::Challenges::FeaturedExercisesProgress48In24.(user)
exercises.none? {|e| e.status == :in_progress} &&
exercises.none? {|e| e.status == :bronze}
exercises = User::Challenges::FeaturedExercisesProgress48In24.(user)
exercises.none? { |e| e.status == :in_progress } &&
exercises.none? { |e| e.status == :bronze }
end

def send_email_on_acquisition? = true
Expand Down
6 changes: 3 additions & 3 deletions app/models/badges/participant_in_48_in_24_badge.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ module Badges
class ParticipantIn48In24Badge < Badge
seed "#48in24 Participant",
:common,
'48in24',
'48_in_24',
'Participated in the #48in24 challenge and achieved a medal'

def award_to?(user)
def exercises = User::Challenges::FeaturedExercisesProgress48In24.(user)
exercises.any? {|e| e.status != :in_progress}
exercises = User::Challenges::FeaturedExercisesProgress48In24.(user)
exercises.any? { |e| e.status != :in_progress }
end

def send_email_on_acquisition? = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ class UsainBoltBadge < Badge
'Earned 48 gold medals in the #48in24 challenge'

def award_to?(user)
def exercises = User::Challenges::FeaturedExercisesProgress48In24.(user)
exercises.all? {|e| e.status == :gold}
exercises = User::Challenges::FeaturedExercisesProgress48In24.(user)
exercises.all? { |e| e.status == :gold }
end

def send_email_on_acquisition? = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,23 @@ class User::Challenges::FeaturedExercisesProgress48In24Test < ActiveSupport::Tes
test "returns completed tracks" do
user = create :user

create_completed_solution(user, 2022, 'reverse-string', 'cpp')
create_completed_solution(user, 2023, 'reverse-string', 'nim')
create_completed_solution(user, 2024, 'leap', 'elixir')
create_completed_solution(user, 2022, 2, 3, 'reverse-string', 'cpp')
create_completed_solution(user, 2023, 4, 5, 'reverse-string', 'nim')
create_completed_solution(user, 2024, 6, 7, 'leap', 'elixir')

progress = User::Challenges::FeaturedExercisesProgress48In24.(user.reload)

exercise_progress = progress_by_exercise(progress)
assert_equal ({ "cpp" => 2022, "nim" => 2023 }), exercise_progress["reverse-string"].completed_tracks
assert_equal ({ "elixir" => 2024 }), exercise_progress["leap"].completed_tracks
assert_equal ({ "cpp" => '2022-02-03', "nim" => '2023-04-05' }), exercise_progress["reverse-string"].completed_tracks
assert_equal ({ "elixir" => '2024-06-07' }), exercise_progress["leap"].completed_tracks
end

test "gold status when user has completed all three featured tracks in 2024" do
user = create :user

create_completed_solution(user, 2024, 'reverse-string', 'cpp')
create_completed_solution(user, 2024, 'reverse-string', 'nim')
create_completed_solution(user, 2024, 'reverse-string', 'javascript')
create_completed_solution(user, 2024, 11, 12, 'reverse-string', 'cpp')
create_completed_solution(user, 2024, 10, 11, 'reverse-string', 'nim')
create_completed_solution(user, 2024, 12, 13, 'reverse-string', 'javascript')

progress = User::Challenges::FeaturedExercisesProgress48In24.(user.reload)

Expand All @@ -50,24 +50,24 @@ class User::Challenges::FeaturedExercisesProgress48In24Test < ActiveSupport::Tes
test "gold status when completed all featured tracks and at least three iterations in 2024" do
user = create :user

create_completed_solution(user, 2021, 'reverse-string', 'cpp')
create_completed_solution(user, 2022, 'reverse-string', 'csharp')
create_completed_solution(user, 2023, 'reverse-string', 'javascript')
create_completed_solution(user, 2021, 4, 5, 'reverse-string', 'cpp')
create_completed_solution(user, 2022, 6, 7, 'reverse-string', 'csharp')
create_completed_solution(user, 2023, 8, 9, 'reverse-string', 'javascript')

progress = User::Challenges::FeaturedExercisesProgress48In24.(user.reload)

exercise_progress = progress_by_exercise(progress)
assert_equal :in_progress, exercise_progress["reverse-string"].status

# Create two iterations in 2024
create_completed_solution(user, 2024, 'reverse-string', 'zig')
create_completed_solution(user, 2024, 'reverse-string', 'nim')
create_completed_solution(user, 2024, 1, 10, 'reverse-string', 'zig')
create_completed_solution(user, 2024, 2, 20, 'reverse-string', 'nim')

exercise_progress = progress_by_exercise(progress)
assert_equal :in_progress, exercise_progress["reverse-string"].status

# Ensure that there are now three iterations in 2024
create_completed_solution(user, 2024, 'reverse-string', 'racket')
create_completed_solution(user, 2024, 3, 30, 'reverse-string', 'racket')

progress = User::Challenges::FeaturedExercisesProgress48In24.(user.reload)
exercise_progress = progress_by_exercise(progress)
Expand All @@ -77,18 +77,18 @@ class User::Challenges::FeaturedExercisesProgress48In24Test < ActiveSupport::Tes
test "silver status when user has completed at least three tracks in 2024 (but not the three featured ones)" do
user = create :user

create_completed_solution(user, 2024, 'reverse-string', 'zig')
create_completed_solution(user, 2024, 'reverse-string', 'csharp')
create_completed_solution(user, 2024, 'reverse-string', 'nim')
create_completed_solution(user, 2024, 1, 1, 'reverse-string', 'zig')
create_completed_solution(user, 2024, 2, 2, 'reverse-string', 'csharp')
create_completed_solution(user, 2024, 3, 3, 'reverse-string', 'nim')

progress = User::Challenges::FeaturedExercisesProgress48In24.(user.reload)

exercise_progress = progress_by_exercise(progress)
assert_equal :silver, exercise_progress["reverse-string"].status

# Even if the user has started all three featured tracks, they don't count if they're not completed
create_non_completed_solution(user, 2024, 'reverse-string', 'python')
create_non_completed_solution(user, 2024, 'reverse-string', 'javascript')
create_non_completed_solution(user, 2024, 4, 4, 'reverse-string', 'python')
create_non_completed_solution(user, 2024, 5, 5, 'reverse-string', 'javascript')

progress = User::Challenges::FeaturedExercisesProgress48In24.(user.reload)

Expand All @@ -98,7 +98,7 @@ class User::Challenges::FeaturedExercisesProgress48In24Test < ActiveSupport::Tes

test "bronze status when user has completed at least one track in 2024" do
user = create :user
create_completed_solution(user, 2024, 'reverse-string', 'kotlin')
create_completed_solution(user, 2024, 6, 6, 'reverse-string', 'kotlin')

progress = User::Challenges::FeaturedExercisesProgress48In24.(user.reload)

Expand All @@ -109,16 +109,16 @@ class User::Challenges::FeaturedExercisesProgress48In24Test < ActiveSupport::Tes
private
def progress_by_exercise(progress) = progress.index_by(&:slug)

def create_completed_solution(user, year, exercise_slug, track_slug)
travel_to Time.utc(year, SecureRandom.random_number(1..12), SecureRandom.random_number(1..28)) do
def create_completed_solution(user, year, month, day, exercise_slug, track_slug)
travel_to Time.utc(year, month, day) do
track = create(:track, slug: track_slug)
exercise = create(:practice_exercise, slug: exercise_slug, track:)
create(:practice_solution, :completed, user:, exercise:)
end
end

def create_non_completed_solution(user, year, exercise_slug, track_slug)
travel_to Time.utc(year, SecureRandom.random_number(1..12), SecureRandom.random_number(1..28)) do
def create_non_completed_solution(user, year, month, day, exercise_slug, track_slug)
travel_to Time.utc(year, month, day) do
track = create(:track, slug: track_slug)
exercise = create(:practice_exercise, slug: exercise_slug, track:)
create(:practice_solution, user:, exercise:)
Expand Down
1 change: 1 addition & 0 deletions test/factories/badges.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
summer_of_sexps jurassic_july apps_august slimline_september
object_oriented_october nibbly_november december_diversions
completed_12_in_23 polyglot
participant_in_48_in_24 larisa_latynina paavo_nurmi usain_bolt
].each do |type|
factory "#{type}_badge", class: "Badges::#{type.to_s.camelize}Badge" do
end
Expand Down
65 changes: 29 additions & 36 deletions test/models/badges/larisa_latynina_badge_test.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require "test_helper"

class Badges::LarisaLatyninaBadgeTest < ActiveSupport::TestCase
class Badge::LarisaLatyninaBadgeTest < ActiveSupport::TestCase
test "attributes" do
badge = create :larisa_latynina_badge
assert_equal "Larisa Latynina", badge.name
Expand All @@ -13,11 +13,11 @@ class Badges::LarisaLatyninaBadgeTest < ActiveSupport::TestCase

test "award_to?" do
badge = create :larisa_latynina_badge
exercises = User::Challenges::FeaturedExercisesProgress48In24.EXERCISES
week1 = exercises.select {|e| e[:week] == 1}
tracks = exercises.map {|e| e[:featured_tracks]}.flatten.uniq
map {|track_slug| [track_slug.to_sym, create(:track, slug: track_slug)]}
.to_h
exercises = User::Challenges::FeaturedExercisesProgress48In24::EXERCISES
week_1 = exercises.find { |e| e[:week] == 1 }
tracks = exercises.map { |e| e[:featured_tracks] }.flatten.uniq.
map { |track_slug| [track_slug.to_sym, create(:track, slug: track_slug)] }.
to_h
user = create :user

# No solutions
Expand All @@ -27,74 +27,67 @@ class Badges::LarisaLatyninaBadgeTest < ActiveSupport::TestCase
refute badge.award_to?(user.reload)

# One bronze all year
exercise = create(:practice_exercise, track: track[:csharp], slug: week1[:slug])
create(:practice_solution, :published, user:, track: track[:csharp], exercise:,
exercise = create(:practice_exercise, track: tracks[:csharp], slug: week_1[:slug])
create(:practice_solution, :published, user:, track: tracks[:csharp], exercise:,
published_at: Time.utc(2024, SecureRandom.rand(1..12), SecureRandom.rand(1..28)))

refute badge.award_to?(user.reload)

# One silver medal: csharp+tcl+wren are never the featured tracks for an exercise
[:tcl, :wren].each do |track_slug|
exercise = create(:practice_exercise, track: track[track_slug], slug: week1[:slug])
create(:practice_solution, :published, user:, track: track[track_slug], exercise:,
%i[tcl wren].each do |track_slug|
exercise = create(:practice_exercise, track: tracks[track_slug], slug: week_1[:slug])
create(:practice_solution, :published, user:, track: tracks[track_slug], exercise:,
published_at: Time.utc(2024, SecureRandom.rand(1..12), SecureRandom.rand(1..28)))
end

refute badge.award_to?(user.reload)

# One gold medal
week1[:featured_tracks].each do |track_slug|
create(:practice_solution, :published, user:, track: track[track_slug.to_sym], exercise:,
week_1[:featured_tracks].each do |track_slug|
exercise = create(:practice_exercise, track: tracks[track_slug.to_sym], slug: week_1[:slug])
create(:practice_solution, :published, user:, track: tracks[track_slug.to_sym], exercise:,
published_at: Time.utc(2024, SecureRandom.rand(1..12), SecureRandom.rand(1..28)))
end

refute badge.award_to?(user.reload)

# in addition to week 1 gold, add 46 bronze medals: 47 medals does not qualify
exercises.select {|e| !(e[:week] == 1 || e[:week] == 48)}.each do |e|
exercise = create(:practice_exercise, track: track[:csharp], slug: e[:slug])
create(:practice_solution, :published, user:, track: track[:csharp], exercise:,
exercises.reject { |e| e[:week] == 1 || e[:week] == 48 }.each do |e|
exercise = create(:practice_exercise, track: tracks[:csharp], slug: e[:slug])
create(:practice_solution, :published, user:, track: tracks[:csharp], exercise:,
published_at: Time.utc(2024, SecureRandom.rand(1..12), SecureRandom.rand(1..28)))
end

refute badge.award_to?(user.reload)

# add week 48 solution, not in 2024
week48 = exercises.select {|e| e[:week] == 48}
exercise = create(:practice_exercise, track: track[:csharp], slug: week48[:slug])
solution = create(:practice_solution, :published, user:, track: track[:csharp], exercise:,
week_48 = exercises.find { |e| e[:week] == 48 }
exercise = create(:practice_exercise, track: tracks[:csharp], slug: week_48[:slug])
solution = create(:practice_solution, :published, user:, track: tracks[:csharp], exercise:,
published_at: Time.utc(2023, SecureRandom.rand(1..12), SecureRandom.rand(1..28)))

refute badge.award_to?(user.reload)

# add an iteration to week 48 to qualify
iteration = create(:iteration, solution:)
iteration.update(created_at: Time.utc(2024, 1, 1, 0, 0, 0)

iteration.update(created_at: Time.utc(2024, 1, 1, 0, 0, 0))
assert badge.award_to?(user.reload)

# 48 gold or silver medals
exercises.select {|e| !(e[:week] == 1}.each do |e|
[:tcl, :wren].each do |t|
exercise = create(:practice_exercise, track: track[t], slug: e[:slug])
create(:practice_solution, :published, user:, track: track[t], exercise:,
exercises.reject { |e| e[:week] == 1 }.each do |e|
%i[tcl wren].each do |t|
exercise = create(:practice_exercise, track: tracks[t], slug: e[:slug])
create(:practice_solution, :published, user:, track: tracks[t], exercise:,
published_at: Time.utc(2024, SecureRandom.rand(1..12), SecureRandom.rand(1..28)))
end
end

assert badge.award_to?(user.reload)

# 48 gold medals
exercises.select {|e| !(e[:week] == 1}.each do |e|
exercises.reject { |e| e[:week] == 1 }.each do |e|
e[:featured_tracks].map(&:to_sym).each do |t|
next if [:csharp, :tcl, :wren].contains(t) # already have these
next if %i[csharp tcl wren].include?(t) # already have these

exercise = create(:practice_exercise, track: track[t], slug: e[:slug])
create(:practice_solution, :published, user:, track: track[t], exercise:,
exercise = create(:practice_exercise, track: tracks[t], slug: e[:slug])
create(:practice_solution, :published, user:, track: tracks[t], exercise:,
published_at: Time.utc(2024, SecureRandom.rand(1..12), SecureRandom.rand(1..28)))
end
end

assert badge.award_to?(user.reload)
end
end
Loading

0 comments on commit 79f05e3

Please sign in to comment.