summaryrefslogtreecommitdiff
path: root/app/models/match.rb
blob: ed21f78fa3f02a9e00b77e4bf3220e923c35d70d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
class Match < ActiveRecord::Base
	belongs_to :tournament_stage
	has_many :statistics
	has_and_belongs_to_many :teams

	belongs_to :winner, class_name: "Team"

	# status:integer
	before_save { self.status ||= 0 }

	# tournament_stage:references
	validates_presence_of :tournament_stage

	# winner:references
	# not validated

	##
	# Returns whether or not all the statistics have been collected
	# such that the match may be considered finished.
	def finished?
		ok = true
		self.tournament_stage.scoring.stats_needed(self).each do |stat|
			self.users.each do |user|
				ok &= self.statistics.where(user: user, name: stat).first
			end
		end
		ok
	end

	##
	# Returns all players involved in this match (from all teams).
	def users
		ret = []
		self.teams.each{|t| ret.concat(t.users)}
		return ret
	end

	##
	# Given a sampling class (a class that implements the interface
	# described in `/lib/sampling/README.md`), this returns which
	# statistics (in an Array of Strings) an instance of the class
	# should collect.
	def stats_from(sampling_class)
		figure_sampling_methods.map{|stat,klass| (sampling_class==klass) ? stat : nil}.select{|s| not s.nil?}
	end

	##
	# Delagates PUT/PATCH HTTP params to the appropriate sampling
	# methods.
	def handle_sampling(user, params)
		method_classes.each do |klass|
			klass.new(self).handle_user_interaction(user, params)
		end
	end

	##
	# Delagates out rendering forms to the appropriate sampling
	# methods.
	def render_sampling(user)
		require 'set'
		html = ''

		method_classes.each do |klass|
			html += '<div>'
			html += klass.new(self).render_user_interaction(user)
			html += '</div>'
		end

		return html.html_safe
	end

	##
	# Calls `Sampling#start` on every sampling method that this match
	# uses.
	def start_sampling
		method_classes.each do |klass|
			klass.new(self).start
		end
	end

	private
	def figure_sampling_methods
		if @sampling_methods.nil?
			data = {}
			needed = self.tournament_stage.scoring.stats_needed(self)
			methods_names = self.tournament_stage.tournament.sampling_methods
			methods_names.each do |method_name|
				method_class = "Sampling::#{method_name.camelcase}".constantize
				needed.each do |stat|
					data[stat] ||= {}
					data[stat][method_class] = method_class.can_get?(stat)
				end
			end

			needed.each do |stat|
				max_val = nil
				max_pri = 0
				data[stat].each do |method,priority|
					if priority > max_pri
						max_val = method
						max_pri = priority
					end
				end
				data[stat] = max_val
			end
			@sampling_methods = data
		end
		return @sampling_methods
	end

	def method_classes
		if @method_classes.nil?
			data = Set.new
			figure_sampling_methods.each do |stat,method|
				data.add(method)
			end
			@method_classes = data
		end
		return @method_classes
	end

end