How to determine the average position for a certain period

I am trying to show some statistics for a dummy game.

There is a Team model, a Player model, and a Run model.

I can get runs for a specific month in the player model:

def count_runs(date)
 self.runs.count(:conditions => {:created_at => (date.beginning_of_month..date.end_of_month)})
end

I can get them in the correct order in the controller and Team model:

@players = @team.players_by_count(Date.today)

def players_by_count(date)
 @date = date
 self.players.all.sort_by{|p| [-p.count_runs(@date)]}
end

I show that the table shows their position:

<table>
  <% @players.each_with_index do |player, index| %>
  <tr>
    <td><%= (index+1).ordinalize %></td>
    <td><%= player.name %></td>
    <td><%= player.count_runs(Date.today) %></td>
  </tr>
  <% end %>
</table>

My diagram is as follows:

create_table "teams", :force => true do |t|
    t.string   "name"
    t.datetime "created_at",    :null => false
    t.datetime "updated_at",    :null => false
  end

  create_table "players", :force => true do |t|
    t.string   "name"
    t.integer  "team_id"
    t.datetime "created_at",   :null => false
    t.datetime "updated_at",   :null => false
  end

  create_table "runs", :force => true do |t|
    t.integer  "player_id"
    t.datetime "created_at",               :null => false
    t.datetime "updated_at",               :null => false
  end

I want to be able to determine what the average position is at the end of the month. Thus, at the end of each month they were in the positions (1st, 3rd, 1st, 5th / 4th month) = Average position = 2.5

I am also trying to figure out how I will get the winner (player placed on top) for each month.

Any ideas?

+3
source share
4 answers

, :

create_table "placements", :force => true do |t|
  t.integer  "player_id"
  t.date "month"
  t.integer "runs_count", :default => 0
end

, , , : ( - , )

def aggregate!
  # Many different ways to accomplish this, this is just the first I thought of.
  Placements.where(player_id: self.player_id, month: self.created_at.beginning_of_month).first_or_create do |placement|
    placement.runs_count += 1
  end
end

:

class Player < ActiveRecord::Base
  has_many :placements
  belongs_to :team
end

class Team < ActiveRecord::Base
  has_many :players
  has_many :placements, through: game
end

class Placement < ActiveRecord::Base
  belongs_to :player
end

:

@players = @team.players_by_count(Date.today)

@placements = @team.placements.includes(:player).where(month: Date.today.beginning_of_month).order('runs_count DESC')

Player, run_count .

, :

<table>
  <% @placements.each_with_index do |placement, index| %>
  <tr>
    <td><%= (index+1).ordinalize %></td>
    <td><%= placement.player.name %></td>
    <td><%= placement.runs_count %></td>
  </tr>
  <% end %>
</table>

, , , :

positions = player.placements.pluck(:position)
average = positions.sum / positions.size.to_f

, , , , . 10 , @team.players_by_count(Date.today) 11 (1 + player_count). @team.placements.includes(:player).where(month: Date.today.beginning_of_month).order('runs_count DESC') - 2 .

, !

+2

, :

def avg
    positions = runs.map(&:position)
    avg = positions.inject(:+) / positions.size
    return avg
end

SQL :

   def avg
      runs.average(:positions)
   end
+1

, , .

IMHO , , , . , , :)

, ( "" ), , , .

- , , , .

, , ( ).

, , , .

, , , Podium .

class Podium

    def self.monthly players, date
        MonthlyPodium.new players, date
    end

    def self.average podia
        AveragePodium.new podia
    end

    def players
        fail 'subclass responsibility'
    end

    def place_of a_player
        fail 'subclass responsibility'
    end

    def winner
        fail 'subclass responsibility'
    end

end

MonthlyPodium, , :

class MonthlyPodium < Podium

    attr_reader :players    

    def initialize players, a_date
        @players = players
        @time_period = a_date.beginning_of_month..a_date.end_of_month
    end

    def place_of a_player
        players_by_descending_runs.index(a_player) + 1
    end

    def winner
        players_by_descending_runs.first
    end

    def players_by_descending_runs
        @players.
            sort_by { |player| player.runs_in @time_period }.
            reverse
    end

end

/ , AveragePodium :

class AveragePodium < Podium

    def initialize podia
        @podia = podia
    end

    def players
        @podia.
            collect(&:players).
            flatten.
            uniq
    end     

    def place_of a_player
        places = @podia.collect { |podium| podium.place_of a_player }
        places.inject(:+) / places.size
    end

    def winner
        players.max_by { |player| place_of player }
    end

end

Podium.
, , .

, .

, :runs_in, . OO, , .

, , . Podium , , , .

/

. , , Team/Player/Run. ( , , AR ).

, . (.. , ).

, , . . .

, Ruby . , beginning_of_month/end_of_month. /, , MonthlyPodium.

Podium . , .

, , Podium. ( ) / , .

, / , , .

, // :)

+1

group, having order avg() select, SQL, .

ActiveRecord , , .

+1
source

All Articles