From 9d226fcd27b6c2470edf718ad36a262348891470 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Tue, 22 Apr 2014 15:50:21 -0400 Subject: re-factor for tournament_stage's and separate scheduling modules --- app/controllers/matches_controller.rb | 6 --- app/controllers/tournaments_controller.rb | 9 ++-- app/models/tournament.rb | 31 ++---------- app/models/tournament_stage.rb | 26 ++++++++++ app/views/matches/index.html.erb | 80 ++----------------------------- config/routes.rb | 10 ++++ lib/scheduling/elimination.rb | 55 +++++++++++++++++++++ lib/scheduling/elimination.svg.erb | 72 ++++++++++++++++++++++++++++ 8 files changed, 176 insertions(+), 113 deletions(-) create mode 100644 lib/scheduling/elimination.rb create mode 100644 lib/scheduling/elimination.svg.erb diff --git a/app/controllers/matches_controller.rb b/app/controllers/matches_controller.rb index d7a8b99..e95f24a 100644 --- a/app/controllers/matches_controller.rb +++ b/app/controllers/matches_controller.rb @@ -8,12 +8,6 @@ class MatchesController < ApplicationController # GET /tournaments/1/matches # GET /tournaments/1/matches.json def index - @matches = @tournament.matches - # depth of SVG tree - @depth = Math.log2(@matches.count).floor+1; - # height of SVG - @height = 200 * 2**Math.log2(@matches.count).floor + 100; - @h_sector = 2**(@depth-1)+1 end # For compatability with the router assumptions made by ApplicationController#check_permission diff --git a/app/controllers/tournaments_controller.rb b/app/controllers/tournaments_controller.rb index b6f911f..4b0e1af 100644 --- a/app/controllers/tournaments_controller.rb +++ b/app/controllers/tournaments_controller.rb @@ -96,10 +96,13 @@ class TournamentsController < ApplicationController when "start" check_permission(:edit, @tournament) @tournament.status = 1 - @tournament.save + ok = + @tournament.save && + @tournament.tournament_stages.create(scheduling: "elimination") && + @tournament.tournament_stages.first.create_matches respond_to do |format| - if @tournament.setup - format.html { redirect_to @tournament, notice: 'You have joined this tournament.' } + if ok + format.html { redirect_to @tournament, notice: 'You have started this tournament.' } format.json { head :no_content } else format.html { redirect_to @tournament, notice: "You don't have permission to start this tournament." } diff --git a/app/models/tournament.rb b/app/models/tournament.rb index 822e641..e21ccb1 100644 --- a/app/models/tournament.rb +++ b/app/models/tournament.rb @@ -1,15 +1,15 @@ class Tournament < ActiveRecord::Base belongs_to :game - has_many :matches + has_many :tournament_stages has_many :settings_raw, class_name: "TournamentSetting" has_and_belongs_to_many :players, class_name: "User", association_foreign_key: "player_id", join_table: "players_tournaments" has_and_belongs_to_many :hosts, class_name: "User", association_foreign_key: "host_id", join_table: "hosts_tournaments" - def matches_ordered + def stages_ordered h = {} i = 1 - matches.order(:id).each do |m| - h[i] = m + self.tournament_stages.order(:id).each do |s| + h[i] = s i += 1 end return h @@ -86,27 +86,4 @@ class Tournament < ActiveRecord::Base players.delete(user) end end - - def setup - num_teams = (self.players.count/self.min_players_per_team).floor - num_matches = num_teams - 1 - for i in 1..num_matches - self.matches.create(name: "Match #{i}", status: 0, submitted_peer_evaluations: 0) - end - match_num = num_matches-1 - team_num = 0 - #for each grouping of min_players_per_team - players.each_slice(min_players_per_team) do |players| - - #if the match is full, move to the next match, otherwise move to the next team - if (team_num == min_teams_per_match) - match_num -= 1 - team_num = 0 - else - team_num += 1 - end - #create a new team in the current match - self.matches[match_num].teams.push(Team.create(users: players)) - end - end end diff --git a/app/models/tournament_stage.rb b/app/models/tournament_stage.rb index 205c8cc..a24d7b9 100644 --- a/app/models/tournament_stage.rb +++ b/app/models/tournament_stage.rb @@ -1,3 +1,29 @@ class TournamentStage < ActiveRecord::Base belongs_to :tournament + has_many :matches + + def matches_ordered + h = {} + i = 1 + self.matches.order(:id).each do |m| + h[i] = m + i += 1 + end + return h + end + + def create_matches + set_scheduling + @scheduling.create_matches + end + + def to_svg + set_scheduling + return @scheduling.graph(self) + end + + private + def set_scheduling + @scheduling ||= "Scheduling::#{self.scheduling}".constantize.new(self) + end end diff --git a/app/views/matches/index.html.erb b/app/views/matches/index.html.erb index 03427d8..cebabb3 100644 --- a/app/views/matches/index.html.erb +++ b/app/views/matches/index.html.erb @@ -32,80 +32,6 @@
-
- - <% lastrx = 0 - lastry = 0 - lastrh = 0 - lastrw = 0 %> - - - - - - - - - <% (1..@matches.count).each do |i| %> - - - <% when 0 %> - <% if @matches[i-1].teams.count < @tournament.min_teams_per_match %> - stroke="red" - fill-opacity="0.6" - <% else %> - stroke="green" - <% end %> - <% when 1 %> - stroke="orange" - <% when 2 %> - stroke="yellow" - <% when 3 %> - stroke="grey" - <% end %> - /> - " /> - - <% if @matches[i-1].teams.first %> - Team <%= @matches[i-1].teams.first.id %> - <% end %> - - VS - - " /> - - <% if @matches[i-1].teams[1] %> - Team <%= @matches[i-1].teams[1].id %> - <% end %> - - <% if i > 1 %> - - <% end %> - <% if Math.log2(i+1) == Math.log2(i+1).ceil %> - <% lastrx = rx - lastry = ry - lastrh = rh - lastrw = rw %> - <% end %> - - - <% end %> - -
+<% @tournament.stages_ordered.each do |stage| %> +
<%= stage.to_svg %>
+<% end %> diff --git a/config/routes.rb b/config/routes.rb index 8ec4432..f94bd2f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -25,7 +25,17 @@ Leaguer::Application.routes.draw do root to: 'static#homepage' get '/testsvg', to: 'static#test' +end +Leaguer::Application.routes.named_routes.module.module_eval do + def match_path(match, options={}) + tournament_match_path(match.tournament_stage.tournament, match, options) + end + def match_url(match, options={}) + tournament_match_url(match.tournament_stage.tournament, match, options) + end +end +if false # The priority is based upon order of creation: first created -> highest priority. # See how all your routes lay out with "rake routes". diff --git a/lib/scheduling/elimination.rb b/lib/scheduling/elimination.rb new file mode 100644 index 0000000..519d08a --- /dev/null +++ b/lib/scheduling/elimination.rb @@ -0,0 +1,55 @@ +module Scheduling + class Elimination + + def initialize(tournament_stage) + @tournament_stage = tournament_stage + end + + def tournament_stage + @tournament_stage + end + def tournament + self.tournament_stage.tournament + end + + def create_matches + num_teams = (self.tournament.players.count/self.tournament.min_players_per_team).floor + num_matches = num_teams - 1 + for i in 1..num_matches + self.tournament_stage.matches.create(status: 0, submitted_peer_evaluations: 0) + end + match_num = num_matches-1 + team_num = 0 + # for each grouping of min_players_per_team + self.tournament.players.each_slice(min_players_per_team) do |team_members| + # if the match is full, move to the next match, otherwise move to the next team + if (team_num == min_teams_per_match) + match_num -= 1 + team_num = 0 + else + team_num += 1 + end + # create a new team in the current match + self.tournament_stage.matches[match_num].teams.push(Team.create(users: team_members)) + end + end + + def match_finished(match) + matches = match.tournament_stage.matches_ordered + cur_match_num = matches.invert[match] + unless cur_match_num == 1 + match.winner.matches.push(matches[cur_match_num/2]) + end + end + + def graph + require 'erb' + erb_filename = File.join(File.dirname(__FILE__), 'elimination.svg.erb') + + erb = ERB.new(File.read(erb_filename)) + erb.filename = erb_filename + return erb.result + end + + end +end diff --git a/lib/scheduling/elimination.svg.erb b/lib/scheduling/elimination.svg.erb new file mode 100644 index 0000000..91b8f6a --- /dev/null +++ b/lib/scheduling/elimination.svg.erb @@ -0,0 +1,72 @@ +<% + +matches = @tournament_stage.matches_ordered +# depth of SVG tree +depth = Math.log2(matches.count).floor+1; +# height of SVG +height = 200 * 2**Math.log2(matches.count).floor + 100; +lastrx = 0 +lastry = 0 +lastrh = 0 +lastrw = 0 + +%> + <% %> + + + + + + + <% (1..matches.count).each do |i| %> + + + <% when 0 %> + <% if matches[i-1].teams.count < @tournament_stage.tournament.min_teams_per_match %> + stroke="red" + fill-opacity="0.6" + <% else %> + stroke="green" + <% end %> + <% when 1 %> + stroke="orange" + <% when 2 %> + stroke="yellow" + <% when 3 %> + stroke="grey" + <% end %> /> + " /> + + <% if matches[i-1].teams.first %> + Team <%= matches[i-1].teams.first.id %> + <% end %> + + VS + " /> + + <% if matches[i-1].teams[1] %> + Team <%= matches[i-1].teams[1].id %> + <% end %> + + <% if i > 1 %> + + <% end %> + <% if Math.log2(i+1) == Math.log2(i+1).ceil %> + <% lastrx = rx + lastry = ry + lastrh = rh + lastrw = rw %> + <% end %> + + <% end %> + -- cgit v1.2.3-2-g168b