sciolyff 0.9.1 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,13 +21,13 @@ module SciolyFF
21
21
  @checkers = {}
22
22
  end
23
23
 
24
- def valid?(rep_or_file)
24
+ def valid?(rep_or_yaml)
25
25
  @logger.flush
26
26
 
27
- if rep_or_file.instance_of? String
28
- valid_file?(rep_or_file, @logger)
27
+ if rep_or_yaml.instance_of? String
28
+ valid_yaml?(rep_or_yaml, @logger)
29
29
  else
30
- valid_rep?(rep_or_file, @logger)
30
+ valid_rep?(rep_or_yaml, @logger)
31
31
  end
32
32
  end
33
33
 
@@ -49,14 +49,14 @@ module SciolyFF
49
49
  result
50
50
  end
51
51
 
52
- def valid_file?(path, logger)
53
- rep = YAML.safe_load(
54
- File.read(path),
52
+ def valid_yaml?(yaml, logger)
53
+ rep = Psych.safe_load(
54
+ yaml,
55
55
  permitted_classes: [Date],
56
56
  symbolize_names: true
57
57
  )
58
58
  rescue StandardError => e
59
- logger.error "could not read file as YAML:\n#{e.message}"
59
+ logger.error "could not read input as YAML:\n#{e.message}"
60
60
  else
61
61
  valid_rep?(rep, logger)
62
62
  end
@@ -80,7 +80,7 @@ module SciolyFF
80
80
  end
81
81
 
82
82
  def check(klass, top_level_rep, rep, logger)
83
- @checkers[klass] ||= klass.new top_level_rep
83
+ @checkers[klass] ||= klass.new top_level_rep, logger
84
84
  checks = klass.instance_methods - Checker.instance_methods
85
85
  checks.map { |im| @checkers[klass].send im, rep, logger }.all?
86
86
  end
@@ -6,6 +6,19 @@ module SciolyFF
6
6
  class Validator::Checker
7
7
  def initialize(rep); end
8
8
 
9
+ # Wraps initialize for child classes
10
+ module SafeInitialize
11
+ def initialize(rep, logger)
12
+ super rep
13
+ rescue StandardError => e
14
+ logger.debug "#{e}\n #{e.backtrace.first}"
15
+ end
16
+ end
17
+
18
+ def self.inherited(subclass)
19
+ subclass.prepend SafeInitialize
20
+ end
21
+
9
22
  # wraps method calls (always using send in Validator) so that exceptions
10
23
  # in the check cause check to pass, as what caused the exception should
11
24
  # cause some other check to fail if the SciolyFF is truly invalid
@@ -32,7 +32,7 @@ module SciolyFF
32
32
  end
33
33
 
34
34
  def placings_for_all_teams?(event, logger)
35
- count = @placings[event[:name]].count
35
+ count = @placings[event[:name]]&.count || 0
36
36
  return true if count == @teams
37
37
 
38
38
  logger.error "'event: #{event[:name]}' has incorrect number of "\
@@ -78,6 +78,13 @@ module SciolyFF
78
78
  "#{placing_log(placing)}"
79
79
  end
80
80
 
81
+ def having_a_tie_makes_sense?(placing, logger)
82
+ return true unless placing.key?(:tie) && placing[:raw]
83
+
84
+ logger.error 'having a tie value does make sense for '\
85
+ "#{placing_log(placing)}"
86
+ end
87
+
81
88
  def possible_participated_disqualified_combination?(placing, logger)
82
89
  return true unless placing[:participated] == false &&
83
90
  placing[:disqualified]
@@ -13,6 +13,7 @@ module SciolyFF
13
13
  }.freeze
14
14
 
15
15
  OPTIONAL = {
16
+ 'tier': Integer,
16
17
  'tiebreaker rank': Integer
17
18
  }.freeze
18
19
  end
@@ -4,6 +4,12 @@ module SciolyFF
4
4
  # Generic tests for (sub-)sections and types. Including classes must have two
5
5
  # hashes REQUIRED and OPTIONAL (see other files in this dir for examples)
6
6
  module Validator::Sections
7
+ def rep_is_hash?(rep, logger)
8
+ return true if rep.instance_of? Hash
9
+
10
+ logger.error "entry in #{section_name} is not a Hash"
11
+ end
12
+
7
13
  def all_required_sections?(rep, logger)
8
14
  missing = self.class::REQUIRED.keys - rep.keys
9
15
  return true if missing.empty?
@@ -22,11 +28,25 @@ module SciolyFF
22
28
  correct_types = self.class::REQUIRED.merge self.class::OPTIONAL
23
29
  rep.all? do |key, value|
24
30
  correct = correct_types[key]
25
- next true if (correct.instance_of?(Array) && correct.include?(value)) ||
26
- (value.instance_of? correct)
31
+ next true if
32
+ (correct.instance_of?(Array) && correct.include?(value)) ||
33
+ (correct.instance_of?(Class) && value.instance_of?(correct)) ||
34
+ correct_date?(correct, value)
27
35
 
28
36
  logger.error "#{key}: #{value} is not #{correct}"
29
37
  end
30
38
  end
39
+
40
+ private
41
+
42
+ def correct_date?(correct, value)
43
+ correct == Date && Date.parse(value)
44
+ rescue StandardError
45
+ false
46
+ end
47
+
48
+ def section_name
49
+ self.class.to_s.split('::').last
50
+ end
31
51
  end
32
52
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |s|
4
+ s.authors = ['Em Zhan']
5
+ s.homepage = 'https://github.com/zqianem/sciolyff'
6
+ s.files = `git ls-files -z`.split("\x0").reject do |f|
7
+ f.start_with? 'examples/', '.'
8
+ end
9
+ s.license = 'MIT'
10
+ s.name = 'sciolyff'
11
+ s.summary = 'A file format for Science Olympiad tournament results.'
12
+ s.version = '0.10.0'
13
+ s.executables << 'sciolyff'
14
+ s.add_runtime_dependency 'erubi', '~> 1.9'
15
+ s.add_runtime_dependency 'optimist', '~> 3.0'
16
+ s.add_runtime_dependency 'psych', '~> 3.1'
17
+ s.required_ruby_version = '>= 2.5'
18
+ end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sciolyff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.10.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-08 00:00:00.000000000 Z
11
+ date: 2020-04-14 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: erubi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.9'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.9'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: optimist
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -25,19 +39,19 @@ dependencies:
25
39
  - !ruby/object:Gem::Version
26
40
  version: '3.0'
27
41
  - !ruby/object:Gem::Dependency
28
- name: rake
42
+ name: psych
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: '12.3'
34
- type: :development
47
+ version: '3.1'
48
+ type: :runtime
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: '12.3'
54
+ version: '3.1'
41
55
  description:
42
56
  email:
43
57
  executables:
@@ -45,6 +59,8 @@ executables:
45
59
  extensions: []
46
60
  extra_rdoc_files: []
47
61
  files:
62
+ - LICENSE
63
+ - README.md
48
64
  - bin/sciolyff
49
65
  - lib/sciolyff.rb
50
66
  - lib/sciolyff/interpreter.rb
@@ -71,6 +87,7 @@ files:
71
87
  - lib/sciolyff/validator/teams.rb
72
88
  - lib/sciolyff/validator/top_level.rb
73
89
  - lib/sciolyff/validator/tournament.rb
90
+ - sciolyff.gemspec
74
91
  homepage: https://github.com/zqianem/sciolyff
75
92
  licenses:
76
93
  - MIT
@@ -83,7 +100,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
83
100
  requirements:
84
101
  - - ">="
85
102
  - !ruby/object:Gem::Version
86
- version: 2.6.0
103
+ version: '2.5'
87
104
  required_rubygems_version: !ruby/object:Gem::Requirement
88
105
  requirements:
89
106
  - - ">="