Topic: Sport Competition Design

Hello,

I'm building a webapplication to manage competitions.
Some background info: A competition is divided into poules and teams are assigned to a poule.
During the competition those teams play matches agains each-other.
A match can only be played between 2 different teams from the same poule.
A team is only bound to the poule in a competition.
A year has 2 competitions (indoor and outdoor).
So over the years a team plays many matches in many poules.
When a team scores more goals than the opponent they receive 2 points for that,
a tie results in 1 point and when you loose, well you loose.. (no points smile ).

The current models:

Competition
    has_many     :poules

Poule
    belongs_to     :competition
    has_many     :matches
    has_and_belongs_to_many    :teams

Match
    belongs_to     :hometeam,
                :class_name => "Team",
                :foreign_key => "hometeam_id"
   
    belongs_to     :awayteam,
                :class_name => "Team",
                :foreign_key => "awayteam_id"

    belongs_to     :poule
   
Team
    has_many    :matches
    belongs_to    :club   
    has_and_belongs_to_many    :poules
   
Club
    has_many    :teams


Some high level features:
    show all the teams in a poule
    show all the matches in a poule
    show the ranking in a poule       
    And more, but that's for version 2 smile

The ranking is the most tricky part, I really have no clue how I should implement this.
Should it be a seperate model?
Or should I implement this from the poule model?

I'm fairly new to all of this, so I hope that some of you can provide me with some insight to solve this.

Re: Sport Competition Design

How are the points/goals stored in the database?

Railscasts - Free Ruby on Rails Screencasts

Re: Sport Competition Design

Hi Ryan,

a match has 2 fields for the goals: home_goals and away_goals

Re: Sport Competition Design

The logic is a little too complicated to do all in one MySQL query, so you need to calculate it in Ruby. Let's start at the interface and work down to the logic. You want to display a list of teams in a given poule ordered by the points?

# in controller
@teams = @poule.teams.sort_by(&:points).reverse

Now you need to create a points method in Team:

# in team.rb
def points
  matches.inject(0) { |total, match| total + match.points_for_team(self) }
end

inject is just a fancy iterator for keeping track of another variable (such as the sum). IIRC, in edge rails there is a sum method built right into the Array class so you could use that.

Now you need to make the points_for_team method in Match:

# in match.rb
def points_for_team(team)
  if winner_team_id == team.id
    2
  elsif tie?
    1
  else
    0
  end
end

def winner_team_id
  if home_goals > away_goals
    hometeam_id
  elsif away_goals > home_goals
    awayteam_id
  end
end

def tie?
  home_goals == away_goals
end


This entire thing isn't very well optimized. If you want to improve performance I recommend caching the points for each team.

Railscasts - Free Ruby on Rails Screencasts

Re: Sport Competition Design

Thanks... that a very extensive anwser. very helpfull.

I will make it work first, than make it faster smile

Last edited by NeXoPheuS (2006-11-11 07:50:01)