Skip to content

Commit

Permalink
- Add endpoint for external stats display
Browse files Browse the repository at this point in the history
  • Loading branch information
Mebibyte committed Nov 27, 2018
1 parent 3c70cf9 commit ee0cba9
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 2 deletions.
31 changes: 31 additions & 0 deletions app/controllers/admin_controller.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
include ActionView::Helpers::NumberHelper

class AdminController < ApplicationController

def index
Expand Down Expand Up @@ -128,4 +130,33 @@ def culled_games
def about
end

def stats
curr_event = Event.current
games = curr_event.top_games()
titles_count = Game.active.count
active_checkouts_count = Checkout.for_current_event.active.count
checked_out = number_to_percentage(active_checkouts_count.to_f / titles_count, precision: 0)
titles_played_count = Checkout.for_current_event.joins(game: [:title]).group(:title).count.size
total_checkouts_count = Checkout.for_current_event.count
longest_checkout = Checkout.longest_checkout_game_today(curr_event.utc_offset)
total_hours_played = Checkout.for_current_event.to_a.sum(&:hours_played) / 1.hour
random_game = Game.random_game()

render json: {
current_event: curr_event.short_name,
games: games,
random_game: random_game,
stats: {
titles: titles_count,
active_checkouts: active_checkouts_count,
checked_out: checked_out,
titles_played: titles_played_count,
total_checkouts: total_checkouts_count,
longest_checkout: longest_checkout,
hours_played: total_hours_played,
},
current_offset: curr_event.utc_offset
}
end

end
33 changes: 31 additions & 2 deletions app/models/checkout.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ class Checkout < ActiveRecord::Base
end
end

scope :for_current_event, -> { where(event: Event.current) }
scope :closed, -> { where(closed: true) }
scope :active, -> { where(closed: false) }

APPROVAL_MAP = {
# 'normalizedtitle' => 'name',
'roborally' => {
Expand All @@ -39,11 +43,13 @@ class Checkout < ActiveRecord::Base
}
}

HALF_DAY = 15.hours

def self.longest_checkout_time_today(offset)
start_time = (Time.now - 15.hours).strftime('%Y-%m-%d %H:%M:%S')
start_time = (Time.now - HALF_DAY).strftime('%Y-%m-%d %H:%M:%S')
minimum_time = self.where(closed: false)
.where(
"(check_out_time - '#{offset} hours'::interval) > ?",
"(check_out_time - '#{Checkout.connection.quote(offset)} hours'::interval) > ?",
start_time
).minimum(:check_out_time).to_i

Expand All @@ -52,6 +58,21 @@ def self.longest_checkout_time_today(offset)
Time.at(difference).utc.strftime('%H:%M:%S')
end

def self.longest_checkout_game_today(offset)
start_time = (Time.now - HALF_DAY).strftime('%Y-%m-%d %H:%M:%S')
min_checkout = self.where(closed: false).where(
"(check_out_time - '#{Checkout.connection.quote(offset)} hours'::interval) > ?",
start_time
).order(:check_out_time).first
if min_checkout
min_game = Game.find(min_checkout.game_id)
min_game_checkout = {
min_checkout: min_checkout,
min_game: min_game.name
}
end
end

def fill_in_fields
self.event = Event.current
self.check_out_time = Time.now.utc
Expand Down Expand Up @@ -92,6 +113,14 @@ def approval_tag
end
end

def hours_played
if return_time
(return_time - check_out_time).to_i
else
DateTime.now.to_i - check_out_time.to_i
end
end

def self.current_as_csv
placeholder = SecureRandom.uuid.downcase.gsub('-', '')
csv = ['CheckedOut,Returned,AttendeeId,Title,Publisher,GameBarcode']
Expand Down
44 changes: 44 additions & 0 deletions app/models/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -281,4 +281,48 @@ def event_checkout_summary
)
end

# Returns the most checked-out games for an event
#
# @note
# This doesn't return fully-hydrated game objects. You'll need
# to add extra data to the query inside of here if you need
# all the data typically accessible on a game.
#
# @example Get the top games for the current event
# Event.current.top_games(1) #=> [
# Game<# id: 73, name: "Monopoly", times_checked_out: 20 >
# ]
#
# @param limit [Integer] how many top games to return. Defaults to 10.
#
# @returns [Array<Game>] array of games with id, name, and times_checked_out
def top_games(limit=10)
placeholder = SecureRandom.uuid.downcase.gsub('-', '')
games = Event.connection.execute(
<<-SQL
select * from (
select
regexp_replace(initcap(regexp_replace(lower(t.title), '''', '#{placeholder}')), '#{placeholder}', '''', 'i' ) as title
,t.id as title_id
,count(distinct c.id) as checkouts
from games g
left join (select * from checkouts where event_id = #{self.id}) c on g.id = c.game_id
inner join titles t on t.id = g.title_id
where
g.status = #{Game::STATUS[:active]}
or (g.status = #{Game::STATUS[:culled]} and g.updated_at::date between '#{self.start_date}' and '#{self.end_date}')
or (g.status = #{Game::STATUS[:stored]} and g.updated_at::date between '#{self.start_date}' and '#{self.end_date}')
group by 2
order by 3 desc,1
) c
where checkouts > 0
limit '#{Event.connection.quote(limit)}'
SQL
)
games.map do |game|
game[:available] = Game.copy_available(game["title_id"])
game
end
end

end
15 changes: 15 additions & 0 deletions app/models/game.rb
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,20 @@ def self.storage_copies_as_csv
csv.concat(games).join("\n")
end

def self.copy_available(title)
self.where(title: title).any?(&:checked_in?)
end

def self.random_game()
game = self.active.order("RANDOM()").first

{
title: game.name,
available: self.copy_available(game.title.id),
checkouts: game.checkouts.for_current_event.count
}
end

def self.count_remaining_from(table)
connection.execute(<<-SQL
select count(*) as games_left from (#{sql_remaining_from(table)}) g
Expand Down Expand Up @@ -305,4 +319,5 @@ def self.missing_games
SQL
)
end

end
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@

post '/store', to: 'admin#store_game'

get '/admin/stats', to: 'admin#stats'

# Example of regular route:
# get 'products/:id' => 'catalog#view'

Expand Down

0 comments on commit ee0cba9

Please sign in to comment.