Add Elo rating system with match entry and CSV upload

- Implement EloCalculator service for 2v2 Euchre matches
- Create background job processing with GoodJob
- Add single match entry form
- Add CSV upload for batch match entry
- Create player rankings view
- Add database schema for matches and elo snapshots
This commit is contained in:
2026-03-26 16:28:24 -07:00
parent 1a9b3496e1
commit 1268889a78
31 changed files with 865 additions and 2 deletions
+5
View File
@@ -1,8 +1,13 @@
# frozen_string_literal: true
require "hanami"
require "good_job"
module EuchreCamp
class App < Hanami::App
config.root = File.expand_path("..", __dir__)
# Enable sessions
config.actions.sessions = :cookie, {secret: ENV.fetch("SESSION_SECRET", "change_me_in_production")}
end
end
+6
View File
@@ -0,0 +1,6 @@
# frozen_string_literal: true
require "active_job"
# Configure Active Job to use GoodJob
ActiveJob::Base.queue_adapter = :good_job
+21
View File
@@ -0,0 +1,21 @@
# frozen_string_literal: true
require "good_job"
# GoodJob configuration for Hanami
# Since GoodJob is primarily designed for Rails, we configure it directly
GoodJob.preserve_job_records = true
GoodJob.retry_on_unhandled_error = false
GoodJob.on_thread_error = ->(exception) { puts "GoodJob error: #{exception.message}" }
# Set execution mode based on environment
if ENV["GOOD_JOB_EXECUTION_MODE"]
GoodJob.execution_mode = ENV["GOOD_JOB_EXECUTION_MODE"].to_sym
elsif ENV["RACK_ENV"] == "test"
GoodJob.execution_mode = :inline
elsif ENV["RACK_ENV"] == "development"
GoodJob.execution_mode = :async
else
GoodJob.execution_mode = :external
end
+10
View File
@@ -4,6 +4,7 @@ module EuchreCamp
class Routes < Hanami::Routes
# Add your routes here. See https://guides.hanamirb.org/routing/overview/ for details.
get "/players/:id", to: "players.show"
get "/rankings", to: "players.rankings"
get "/admin/players/new", to: "admin.players.new"
post "/admin/players", to: "admin.players.create"
@@ -11,5 +12,14 @@ module EuchreCamp
get "/admin/players/:id/edit", to: "admin.players.edit"
patch "/admin/players/:id", to: "admin.players.update"
delete "/admin/players/:id", to: "admin.players.destroy"
# Match routes
get "/admin/matches/new", to: "admin.matches.new"
post "/admin/matches", to: "admin.matches.create"
get "/admin/matches", to: "admin.matches.index"
# CSV Upload routes
get "/admin/matches/upload", to: "admin.matches.upload"
post "/admin/matches/process_upload", to: "admin.matches.process_upload"
end
end