sciolyff 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'sciolyff/validator/checker'
4
4
  require 'sciolyff/validator/sections'
5
+ require 'sciolyff/validator/canonical'
5
6
 
6
7
  module SciolyFF
7
8
  # Checks for one team in the Teams section of a SciolyFF file
@@ -25,6 +26,7 @@ module SciolyFF
25
26
 
26
27
  def initialize(rep)
27
28
  initialize_teams_info(rep[:Teams])
29
+ @subdivisions = rep[:Subdivisions]&.map { |s| s[:name] } || []
28
30
  @placings = rep[:Placings].group_by { |p| p[:team] }
29
31
  @exempt = rep[:Tournament][:'exempt placings'] || 0
30
32
  end
@@ -45,6 +47,14 @@ module SciolyFF
45
47
  'as another team from the same school'
46
48
  end
47
49
 
50
+ def suffix_needed?(team, logger)
51
+ rep = [team[:school], team[:city], team[:state]]
52
+ return true unless team[:suffix] && @schools[rep].count == 1
53
+
54
+ logger.warn "team number #{team[:number]} may have unnecessary "\
55
+ "suffix: #{team[:suffix]}"
56
+ end
57
+
48
58
  def unambiguous_cities_per_school?(team, logger)
49
59
  return true unless @schools.keys.find do |other|
50
60
  team[:city].nil? && !other[1].nil? &&
@@ -64,18 +74,35 @@ module SciolyFF
64
74
  "exempt placings (#{count} insteand of #{@exempt})"
65
75
  end
66
76
 
77
+ def matching_subdivision?(team, logger)
78
+ sub = team[:subdivision]
79
+ return true if sub.nil? || @subdivisions.include?(sub)
80
+
81
+ logger.error "'subdivision: #{sub}' does not match any name in "\
82
+ 'section Subdivisions'
83
+ end
84
+
67
85
  def in_a_subdivision_if_possible?(team, logger)
68
- return true unless @subdivisions && !team[:subdivision]
86
+ return true unless !@subdivisions.empty? && !team[:subdivision]
69
87
 
70
88
  logger.warn "missing subdivision for 'team: #{team[:number]}'"
71
89
  end
72
90
 
91
+ include Validator::Canonical
92
+
93
+ def in_canonical_list?(team, logger)
94
+ rep = [team[:school], team[:city], team[:state]]
95
+ return true if canonical?(rep, 'schools.csv', logger)
96
+
97
+ location = rep[1..-1].compact.join ', '
98
+ logger.warn "non-canonical school: #{team[:school]} in #{location}"
99
+ end
100
+
73
101
  private
74
102
 
75
103
  def initialize_teams_info(teams)
76
104
  @numbers = teams.map { |t| t[:number] }
77
105
  @schools = teams.group_by { |t| [t[:school], t[:city], t[:state]] }
78
- @subdivisions = teams.find { |t| t[:subdivision] }
79
106
  end
80
107
  end
81
108
  end
@@ -16,6 +16,7 @@ module SciolyFF
16
16
  }.freeze
17
17
 
18
18
  OPTIONAL = {
19
+ Subdivisions: Array,
19
20
  Penalties: Array
20
21
  }.freeze
21
22
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'sciolyff/validator/checker'
4
4
  require 'sciolyff/validator/sections'
5
+ require 'sciolyff/validator/range'
5
6
 
6
7
  module SciolyFF
7
8
  # Checks for Tournament section of a SciolyFF file
@@ -19,6 +20,10 @@ module SciolyFF
19
20
  OPTIONAL = {
20
21
  name: String,
21
22
  state: String,
23
+ medals: Integer,
24
+ trophies: Integer,
25
+ bids: Integer,
26
+ 'bids per school': Integer,
22
27
  'short name': String,
23
28
  'worst placings dropped': Integer,
24
29
  'exempt placings': Integer,
@@ -29,6 +34,9 @@ module SciolyFF
29
34
 
30
35
  def initialize(rep)
31
36
  @maximum_place = rep[:Teams].count { |t| !t[:exhibition] }
37
+ @schools_count = rep[:Teams].uniq do |t|
38
+ [t[:school], t[:city], t[:state]]
39
+ end.count
32
40
  end
33
41
 
34
42
  def name_for_not_states_or_nationals?(tournament, logger)
@@ -46,6 +54,34 @@ module SciolyFF
46
54
  "('level: #{tournament[:level]}' is not Nationals)"
47
55
  end
48
56
 
57
+ def bids_for_regionals_or_states?(tournament, logger)
58
+ level = tournament[:level]
59
+
60
+ if %w[Regionals States].include?(level)
61
+ return true if tournament.key? :bids
62
+
63
+ logger.error "field 'bids:' required for level: #{level}"
64
+ else
65
+ return true unless tournament.key? :bids
66
+
67
+ logger.error "bids: does not make sense for level: #{level}"
68
+ end
69
+ end
70
+
71
+ def bids_per_school_positive?(tournament, logger)
72
+ bids = tournament[:'bids per school']
73
+ return true if bids.nil? || tournament[:'bids per school'].positive?
74
+
75
+ logger.error "'bids per school: #{bids}' is not positive"
76
+ end
77
+
78
+ def bids_per_school_relevant?(tournament, logger)
79
+ return true unless tournament[:'bids per school'] &&
80
+ !tournament.key?(:bids)
81
+
82
+ logger.error "field 'bids per school:' not relevant without field 'bids:'"
83
+ end
84
+
49
85
  def short_name_is_relevant?(tournament, logger)
50
86
  return true unless tournament[:'short name'] && !tournament[:name]
51
87
 
@@ -61,12 +97,23 @@ module SciolyFF
61
97
  "is longer than normal 'name: #{tournament[:name]}'"
62
98
  end
63
99
 
100
+ include Validator::Range
101
+
64
102
  def maximum_place_within_range?(tournament, logger)
65
- return true if tournament[:'maximum place'].nil? ||
66
- tournament[:'maximum place'].between?(1, @maximum_place)
103
+ within_range?(tournament, :'maximum place', logger, 1, @maximum_place)
104
+ end
105
+
106
+ def medals_within_range?(tournament, logger)
107
+ max = [@maximum_place, tournament[:'maximum place']].compact.min
108
+ within_range?(tournament, :medals, logger, 1, max)
109
+ end
110
+
111
+ def trophies_within_range?(tournament, logger)
112
+ within_range?(tournament, :trophies, logger, 1, @maximum_place)
113
+ end
67
114
 
68
- logger.error "custom 'maximum place: #{tournament[:'maximum place']}' "\
69
- "is not within range [1, #{@maximum_place}]"
115
+ def bids_within_range?(tournament, logger)
116
+ within_range?(tournament, :bids, logger, 1, @schools_count)
70
117
  end
71
118
  end
72
119
  end
data/sciolyff.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
9
9
  s.license = 'MIT'
10
10
  s.name = 'sciolyff'
11
11
  s.summary = 'A file format for Science Olympiad tournament results.'
12
- s.version = '0.10.0'
12
+ s.version = '0.11.0'
13
13
  s.executables << 'sciolyff'
14
14
  s.add_runtime_dependency 'erubi', '~> 1.9'
15
15
  s.add_runtime_dependency 'optimist', '~> 3.0'
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.10.0
4
+ version: 0.11.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: 2020-04-14 00:00:00.000000000 Z
11
+ date: 2020-05-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: erubi
@@ -64,9 +64,12 @@ files:
64
64
  - bin/sciolyff
65
65
  - lib/sciolyff.rb
66
66
  - lib/sciolyff/interpreter.rb
67
+ - lib/sciolyff/interpreter/bids.rb
67
68
  - lib/sciolyff/interpreter/event.rb
68
69
  - lib/sciolyff/interpreter/html.rb
69
70
  - lib/sciolyff/interpreter/html/helpers.rb
71
+ - lib/sciolyff/interpreter/html/main.css
72
+ - lib/sciolyff/interpreter/html/main.js
70
73
  - lib/sciolyff/interpreter/html/template.html.erb
71
74
  - lib/sciolyff/interpreter/model.rb
72
75
  - lib/sciolyff/interpreter/penalty.rb
@@ -77,13 +80,16 @@ files:
77
80
  - lib/sciolyff/interpreter/tiebreaks.rb
78
81
  - lib/sciolyff/interpreter/tournament.rb
79
82
  - lib/sciolyff/validator.rb
83
+ - lib/sciolyff/validator/canonical.rb
80
84
  - lib/sciolyff/validator/checker.rb
81
85
  - lib/sciolyff/validator/events.rb
82
86
  - lib/sciolyff/validator/logger.rb
83
87
  - lib/sciolyff/validator/penalties.rb
84
88
  - lib/sciolyff/validator/placings.rb
89
+ - lib/sciolyff/validator/range.rb
85
90
  - lib/sciolyff/validator/raws.rb
86
91
  - lib/sciolyff/validator/sections.rb
92
+ - lib/sciolyff/validator/subdivisions.rb
87
93
  - lib/sciolyff/validator/teams.rb
88
94
  - lib/sciolyff/validator/top_level.rb
89
95
  - lib/sciolyff/validator/tournament.rb