sciolyff 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64f19b6f05fc3a19ae643aa8c783561f094ddd93959021b77eda3ad437ec9f6d
4
- data.tar.gz: e0359c5b02d570f75d068ae5d4b0dd2965d0bece8acfa7451b6cc29acfe19cb7
3
+ metadata.gz: 32773284dba3d9f67b630bd64bc1e42c60ca301a49da032c51a055101a8a96c5
4
+ data.tar.gz: dee4202db369a0d6968ffdd32b98be3a6e42edb49558a8a05855a1ea77c3d653
5
5
  SHA512:
6
- metadata.gz: dfacd78064019cebf1be0d4cf7351965eb6dd134d2457a1f00d8ed26babb535c94d292d90b9cb6f21f04350faa8b9d96745bdb61d05b8c00806e8a4fbde57df6
7
- data.tar.gz: 51e0a6fd2deaa74b1f0692e7a39a4d2712bef21f3a4f92b322d205219ac58d2dd0102ba438c2a6b085850d2d23885ee1d95386f67c81c5c66d355b4c7bef2db0
6
+ metadata.gz: acab98c9051a82ed655f14551e185f4e69cc3f22c08af64ab2361d00759216b812a96f0eb247aa5add92ad3367d705c339dfbb2be67e44b6d4df588901611d69
7
+ data.tar.gz: ddcb26d4a7ab3a9f668ab1a95923183697857bb44e64942a63314b3336d57fd01c6275a2081e765ae0de66953527a15d5b6bc1637d62db5bfa06898da2a835eb
data/bin/sciolyff CHANGED
@@ -6,7 +6,7 @@ require 'yaml'
6
6
  require 'sciolyff'
7
7
 
8
8
  opts = Optimist.options do
9
- version 'sciolyff 0.6.0'
9
+ version 'sciolyff 0.7.0'
10
10
  banner <<~STRING
11
11
  Checks if a given file is in the Scioly File Format
12
12
 
@@ -46,6 +46,12 @@ module SciolyFF
46
46
  end
47
47
 
48
48
  def points
49
+ return 0 unless considered_for_team_points?
50
+
51
+ isolated_points
52
+ end
53
+
54
+ def isolated_points
49
55
  return @cache[:points] if @cache[:points]
50
56
 
51
57
  n = event.competing_teams.count
@@ -60,6 +66,11 @@ module SciolyFF
60
66
  end
61
67
 
62
68
  def considered_for_team_points?
69
+ initially_considered_for_team_points? &&
70
+ !team.worst_placings_to_be_dropped.include?(self)
71
+ end
72
+
73
+ def initially_considered_for_team_points?
63
74
  !(event.trial? || event.trialed? || exempt?)
64
75
  end
65
76
 
@@ -61,21 +61,21 @@ module SciolyFF
61
61
  def points
62
62
  return @cache[:points] if @cache[:points]
63
63
 
64
- counted_placings = placings.select(&:considered_for_team_points?)
64
+ @cache[:points] = placings.sum(&:points) + penalties.sum(&:points)
65
+ end
65
66
 
66
- if @tournament.worst_placings_dropped?
67
- counted_placings
68
- .sort!(&:points)
69
- .reverse!
70
- .drop!(@tournament.worst_placings_dropped)
71
- end
67
+ def worst_placings_to_be_dropped
68
+ return [] if @tournament.worst_placings_dropped.zero?
72
69
 
73
- @cache[:points] =
74
- counted_placings.sum(&:points) + penalties.sum(&:points)
70
+ placings
71
+ .select(&:initially_considered_for_team_points?)
72
+ .sort(&:points)
73
+ .reverse
74
+ .take(@tournament.worst_placings_dropped)
75
75
  end
76
76
 
77
77
  def trial_event_points
78
- placings.select { |p| p.event.trial? }.sum(&:points)
78
+ placings.select { |p| p.event.trial? }.sum(&:isolated_points)
79
79
  end
80
80
 
81
81
  def medal_counts
@@ -53,13 +53,19 @@ module SciolyFF
53
53
  end
54
54
 
55
55
  def worst_placings_dropped?
56
- @rep[:'worst placings dropped'].instance_of? Integer
56
+ @rep.key? :'worst placings dropped'
57
57
  end
58
58
 
59
59
  def worst_placings_dropped
60
- return 0 unless @rep[:'worst placings dropped']
60
+ worst_placings_dropped? ? @rep[:'worst placings dropped'] : 0
61
+ end
62
+
63
+ def exempt_placings?
64
+ @rep.key? :'exempt placings'
65
+ end
61
66
 
62
- @rep[:'worst placings dropped']
67
+ def exempt_placings
68
+ exempt_placings? ? @rep[:'exempt placings'] : 0
63
69
  end
64
70
 
65
71
  def max_points_per_event(trial: false)
@@ -69,6 +69,23 @@ module SciolyFF
69
69
  end
70
70
  end
71
71
 
72
+ def test_each_team_has_correct_number_of_exempt_placings
73
+ skip unless SciolyFF.rep.instance_of? Hash
74
+ skip unless SciolyFF.rep[:Tournament].instance_of? Hash
75
+
76
+ exempt_placings = SciolyFF.rep[:Tournament][:'exempt placings']
77
+ exempt_placings = 0 if exempt_placings.nil?
78
+ skip unless exempt_placings.instance_of? Integer
79
+
80
+ @placings.select { |p| p.instance_of?(Hash) && p[:'exempt'] }
81
+ .group_by { |p| p[:team] }
82
+ .each do |team_number, placings|
83
+ assert placings.count == exempt_placings,
84
+ "Team number #{team_number} has the incorrect number of exempt "\
85
+ "placings (#{placings.count} instead of #{exempt_placings})"
86
+ end
87
+ end
88
+
72
89
  def test_each_placing_has_valid_tie
73
90
  @placings.select { |p| p.instance_of? Hash }.each do |placing|
74
91
  next unless placing.key? :tie
@@ -23,7 +23,7 @@ module SciolyFF
23
23
 
24
24
  def test_does_not_have_extra_info
25
25
  info = Set.new %i[name location level division state year date]
26
- info << :'short name'
26
+ info << :'short name' << :'worst placings dropped' << :'exempt placings'
27
27
  assert Set.new(@tournament.keys).subset? info
28
28
  end
29
29
 
@@ -74,5 +74,15 @@ module SciolyFF
74
74
  skip unless @tournament.key? :date
75
75
  assert_instance_of Date, @tournament[:date]
76
76
  end
77
+
78
+ def test_has_valid_worst_placings_dropped
79
+ skip unless @tournament.key? :'worst placings dropped'
80
+ assert_instance_of Integer, @tournament[:'worst placings dropped']
81
+ end
82
+
83
+ def test_has_valid_exempt_placings
84
+ skip unless @tournament.key? :'exempt placings'
85
+ assert_instance_of Integer, @tournament[:'exempt placings']
86
+ end
77
87
  end
78
88
  end
data/lib/sciolyff.rb CHANGED
@@ -47,166 +47,4 @@ module SciolyFF
47
47
  Doesn't give line numbers from original file? Yeah.
48
48
 
49
49
  STRING
50
-
51
- # Deprecated: Please use `SciolyFF::Interpreter` instead
52
- #
53
- # Wrapper class around a SciolyFF Ruby object representation with utility
54
- # methods to help in displaying results
55
- class Helper
56
- attr_reader :rep, :tournament, :events_by_name, :teams_by_number
57
- attr_reader :placings_by_event, :placings_by_team, :penalties_by_team
58
-
59
- def initialize(rep)
60
- warn 'Class `SciolyFF::Helper` is deprecated. '\
61
- 'Please use `SciolyFF::Interpreter` instead.'
62
-
63
- @rep = rep
64
- @exhibition_teams_count = rep[:Teams].count { |t| t[:exhibition] }
65
- @exempt_placings_count = rep[:Placings].count { |p| p[:exempt] }
66
- @team_points_cache = {}
67
-
68
- @tournament = rep[:Tournament]
69
- @events_by_name = index_array(rep[:Events], [:name])
70
- @teams_by_number = index_array(rep[:Teams], [:number])
71
- @placings_by_event = index_array(rep[:Placings], %i[event team])
72
- @placings_by_team = index_array(rep[:Placings], %i[team event])
73
- return unless rep[:Penalties]
74
-
75
- @penalties_by_team = index_array(rep[:Penalties], [:team])
76
- end
77
-
78
- def nonexhibition_teams
79
- @teams_by_number.reject { |_, t| t[:exhibition] }
80
- end
81
-
82
- def event_points(team_number, event_name)
83
- placing = @placings_by_event[event_name][team_number]
84
- number_of_teams = number_of_competing_teams(event_name)
85
-
86
- if placing[:disqualified] then number_of_teams + 2
87
- elsif placing[:participated] == false then number_of_teams + 1
88
- elsif placing[:unknown] then number_of_teams - 1
89
- elsif placing[:place].nil? then number_of_teams
90
- else calculate_event_points(placing)
91
- end
92
- end
93
-
94
- def team_points(team_number)
95
- return @team_points_cache[team_number] if @team_points_cache[team_number]
96
-
97
- @team_points_cache[team_number] = calculate_team_points(team_number)
98
- end
99
-
100
- def team_points_from_penalties(team_number)
101
- if @penalties_by_team.nil? || @penalties_by_team[team_number].nil? then 0
102
- else @penalties_by_team[team_number][:points]
103
- end
104
- end
105
-
106
- def sort_teams_by_rank
107
- @teams_by_number
108
- .values
109
- .sort do |a, b|
110
- next 1 if a[:exhibition] && !b[:exhibition]
111
- next -1 if !a[:exhibition] && b[:exhibition]
112
-
113
- cmp = team_points(a[:number]) - team_points(b[:number])
114
- cmp.zero? ? break_tie(a[:number], b[:number]) : cmp
115
- end
116
- end
117
-
118
- def medal_counts(team_number)
119
- (1..(nonexhibition_teams.count + 2)).map do |m|
120
- @events_by_name
121
- .values
122
- .reject { |e| e[:trial] || e[:trialed] }
123
- .count { |e| event_points(team_number, e[:name]) == m }
124
- end
125
- end
126
-
127
- private
128
-
129
- def index_array(arr, index_keys)
130
- return arr.first if index_keys.empty?
131
-
132
- indexed_hash = arr.group_by { |x| x[index_keys.first] }
133
-
134
- indexed_hash.transform_values do |a|
135
- index_array(a, index_keys.drop(1))
136
- end
137
- end
138
-
139
- def number_of_competing_teams(event_name)
140
- return @teams_by_number.count if @events_by_name[event_name][:trial]
141
-
142
- nonexhibition_teams.count
143
- end
144
-
145
- def calculate_event_points(placing)
146
- return placing[:place] if simple_placing?(placing)
147
-
148
- # Points is place minus number of exhibition and exempt teams with a
149
- # better place
150
- placing[:place] -
151
- @placings_by_event[placing[:event]]
152
- .values
153
- .select { |p| p[:place] && exhibition_or_exempt_placing?(p) }
154
- .count { |p| p[:place] < placing[:place] }
155
- end
156
-
157
- def calculate_team_points(team_number)
158
- @placings_by_team[team_number]
159
- .values
160
- .reject { |p| @events_by_name[p[:event]][:trial] }
161
- .reject { |p| @events_by_name[p[:event]][:trialed] }
162
- .reject { |p| p[:exempt] }
163
- .sum { |p| event_points(team_number, p[:event]) } \
164
- + team_points_from_penalties(team_number)
165
- end
166
-
167
- def simple_placing?(placing)
168
- @events_by_name[placing[:event]][:trial] ||
169
- (@exhibition_teams_count.zero? && @exempt_placings_count.zero?)
170
- end
171
-
172
- def exhibition_or_exempt_placing?(placing)
173
- @teams_by_number[placing[:team]][:exhibition] || placing[:exempt]
174
- end
175
-
176
- def break_tie(team_number_a, team_number_b)
177
- medal_counts(team_number_a)
178
- .zip(medal_counts(team_number_b))
179
- .map { |count| count.last - count.first }
180
- .find(proc { break_second_tie(team_number_a, team_number_b) },
181
- &:nonzero?)
182
- end
183
-
184
- def break_second_tie(team_number_a, team_number_b)
185
- cmp = points_from_trial(team_number_a) - points_from_trial(team_number_b)
186
- cmp.zero? ? break_third_tie(team_number_a, team_number_b) : cmp
187
- end
188
-
189
- def break_third_tie(team_number_a, team_number_b)
190
- medal_counts_from_trial(team_number_a)
191
- .zip(medal_counts_from_trial(team_number_b))
192
- .map { |count| count.last - count.first }
193
- .find(proc { team_number_a <=> team_number_b }, &:nonzero?)
194
- end
195
-
196
- def points_from_trial(team_number)
197
- @placings_by_team[team_number]
198
- .values
199
- .select { |p| @events_by_name[p[:event]][:trial] }
200
- .sum { |p| event_points(team_number, p[:event]) }
201
- end
202
-
203
- def medal_counts_from_trial(team_number)
204
- (1..(@teams_by_number.count + 2)).map do |m|
205
- @events_by_name
206
- .values
207
- .select { |e| e[:trial] }
208
- .count { |e| event_points(team_number, e[:name]) == m }
209
- end
210
- end
211
- end
212
50
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sciolyff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Em Zhan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-26 00:00:00.000000000 Z
11
+ date: 2019-10-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest