academic_benchmarks 0.0.10 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (27) hide show
  1. checksums.yaml +5 -5
  2. data/lib/academic_benchmarks/api/auth.rb +6 -4
  3. data/lib/academic_benchmarks/api/constants.rb +2 -20
  4. data/lib/academic_benchmarks/api/handle.rb +0 -20
  5. data/lib/academic_benchmarks/api/standards.rb +127 -83
  6. data/lib/academic_benchmarks/lib/attr_to_vals.rb +7 -0
  7. data/lib/academic_benchmarks/lib/inst_vars_to_hash.rb +2 -0
  8. data/lib/academic_benchmarks/standards/authority.rb +35 -9
  9. data/lib/academic_benchmarks/standards/disciplines.rb +21 -0
  10. data/lib/academic_benchmarks/standards/document.rb +14 -6
  11. data/lib/academic_benchmarks/standards/education_levels.rb +21 -0
  12. data/lib/academic_benchmarks/standards/grade.rb +4 -5
  13. data/lib/academic_benchmarks/standards/number.rb +21 -0
  14. data/lib/academic_benchmarks/standards/publication.rb +59 -0
  15. data/lib/academic_benchmarks/standards/section.rb +23 -0
  16. data/lib/academic_benchmarks/standards/standard.rb +37 -70
  17. data/lib/academic_benchmarks/standards/standards_forest.rb +4 -38
  18. data/lib/academic_benchmarks/standards/standards_tree.rb +2 -63
  19. data/lib/academic_benchmarks/standards/statement.rb +21 -0
  20. data/lib/academic_benchmarks/standards/subject.rb +3 -4
  21. data/lib/academic_benchmarks/standards/utilizations.rb +19 -0
  22. metadata +37 -18
  23. data/lib/academic_benchmarks/lib/remove_obsolete_children.rb +0 -10
  24. data/lib/academic_benchmarks/standards/course.rb +0 -22
  25. data/lib/academic_benchmarks/standards/has_relations.rb +0 -21
  26. data/lib/academic_benchmarks/standards/parent.rb +0 -41
  27. data/lib/academic_benchmarks/standards/subject_doc.rb +0 -22
@@ -0,0 +1,21 @@
1
+ require 'academic_benchmarks/lib/attr_to_vals'
2
+ require 'academic_benchmarks/lib/inst_vars_to_hash'
3
+
4
+ module AcademicBenchmarks
5
+ module Standards
6
+ class Disciplines
7
+ include AttrToVals
8
+ include InstVarsToHash
9
+
10
+ attr_accessor :subjects
11
+
12
+ def self.from_hash(hash)
13
+ self.new(subjects: hash["subjects"])
14
+ end
15
+
16
+ def initialize(subjects:)
17
+ @subjects = attr_to_vals(Subject, subjects)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,23 +1,31 @@
1
1
  require 'academic_benchmarks/lib/inst_vars_to_hash'
2
- require 'academic_benchmarks/lib/remove_obsolete_children'
3
2
 
4
3
  module AcademicBenchmarks
5
4
  module Standards
6
5
  class Document
7
6
  include InstVarsToHash
8
- include RemoveObsoleteChildren
9
7
 
10
- attr_accessor :title, :guid, :children
8
+ attr_accessor :guid, :descr, :publication, :adopt_year, :children
9
+ alias_method :description, :descr
11
10
 
12
11
  def self.from_hash(hash)
13
- self.new(title: hash["title"], guid: hash["guid"])
12
+ self.new(guid: hash["guid"], descr: hash["descr"], publication: hash["publication"], adopt_year: hash["adopt_year"])
14
13
  end
15
14
 
16
- def initialize(title:, guid:, children: [])
17
- @title = title
15
+ def initialize(guid:, descr:, publication:, adopt_year:, children: [])
18
16
  @guid = guid
17
+ @descr = descr
18
+ @publication = attr_to_val_or_nil(Publication, publication)
19
+ @adopt_year = adopt_year
19
20
  @children = children
20
21
  end
22
+
23
+ private
24
+
25
+ def attr_to_val_or_nil(klass, hash)
26
+ return nil if hash.nil?
27
+ klass.from_hash(hash)
28
+ end
21
29
  end
22
30
  end
23
31
  end
@@ -0,0 +1,21 @@
1
+ require 'academic_benchmarks/lib/attr_to_vals'
2
+ require 'academic_benchmarks/lib/inst_vars_to_hash'
3
+
4
+ module AcademicBenchmarks
5
+ module Standards
6
+ class EducationLevels
7
+ include AttrToVals
8
+ include InstVarsToHash
9
+
10
+ attr_accessor :grades
11
+
12
+ def self.from_hash(hash)
13
+ self.new(grades: hash["grades"])
14
+ end
15
+
16
+ def initialize(grades:)
17
+ @grades = attr_to_vals(Grade, grades)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -5,15 +5,14 @@ module AcademicBenchmarks
5
5
  class Grade
6
6
  include InstVarsToHash
7
7
 
8
- attr_accessor :high, :low
8
+ attr_accessor :code
9
9
 
10
10
  def self.from_hash(hash)
11
- self.new(high: hash["high"], low: hash["low"])
11
+ self.new(code: hash["code"])
12
12
  end
13
13
 
14
- def initialize(high:, low:)
15
- @high = high
16
- @low = low
14
+ def initialize(code:)
15
+ @code = code
17
16
  end
18
17
  end
19
18
  end
@@ -0,0 +1,21 @@
1
+ require 'academic_benchmarks/lib/inst_vars_to_hash'
2
+
3
+ module AcademicBenchmarks
4
+ module Standards
5
+ class Number
6
+ include InstVarsToHash
7
+
8
+ attr_accessor :prefix_enhanced
9
+
10
+ def self.from_hash(hash)
11
+ self.new(
12
+ prefix_enhanced: hash["prefix_enhanced"]
13
+ )
14
+ end
15
+
16
+ def initialize(prefix_enhanced:)
17
+ @prefix_enhanced = prefix_enhanced
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,59 @@
1
+ require 'academic_benchmarks/lib/attr_to_vals'
2
+ require 'academic_benchmarks/lib/inst_vars_to_hash'
3
+
4
+ module AcademicBenchmarks
5
+ module Standards
6
+ class Publication
7
+ include AttrToVals
8
+ include InstVarsToHash
9
+
10
+ attr_accessor :acronym, :descr, :guid, :authorities, :children
11
+
12
+ alias_method :code, :acronym
13
+ alias_method :description, :descr
14
+
15
+ def self.from_hash(hash)
16
+ self.new(
17
+ acronym: hash["acronym"],
18
+ descr: hash["descr"],
19
+ guid: hash["guid"],
20
+ authorities: hash["authorities"]
21
+ )
22
+ end
23
+
24
+ def initialize(acronym:, descr:, guid:, authorities:, children: [])
25
+ @acronym = acronym
26
+ @descr = descr
27
+ @guid = guid
28
+ @authorities = attr_to_vals(Authority, authorities)
29
+ @children = children
30
+ end
31
+
32
+ # Children are standards, so rebranch them so we have
33
+ # the following structure:
34
+ #
35
+ # Publication -> Document -> Section -> Standard
36
+ def rebranch_children
37
+ @seen = Set.new()
38
+ @guid_to_obj = {}
39
+ new_children = []
40
+ @children.each do |child|
41
+ doc = reparent(child.document, new_children)
42
+ sec = reparent(child.section, doc.children)
43
+ sec.children.push(child)
44
+ end
45
+ @children.replace(new_children)
46
+ remove_instance_variable('@seen')
47
+ remove_instance_variable('@guid_to_obj')
48
+ end
49
+
50
+ private
51
+
52
+ def reparent(object, children)
53
+ cached_object = (@guid_to_obj[object.guid] ||= object)
54
+ children.push(cached_object) if @seen.add? cached_object.guid
55
+ cached_object
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,23 @@
1
+ require 'academic_benchmarks/lib/inst_vars_to_hash'
2
+
3
+ module AcademicBenchmarks
4
+ module Standards
5
+ class Section
6
+ include InstVarsToHash
7
+
8
+ attr_accessor :guid, :descr, :children
9
+
10
+ alias_method :description, :descr
11
+
12
+ def self.from_hash(hash)
13
+ self.new(descr: hash["descr"], guid: hash["guid"])
14
+ end
15
+
16
+ def initialize(guid:, descr:, children: [])
17
+ @guid = guid
18
+ @descr = descr
19
+ @children = children
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,80 +1,51 @@
1
+ require 'academic_benchmarks/lib/attr_to_vals'
1
2
  require 'academic_benchmarks/lib/inst_vars_to_hash'
2
- require 'academic_benchmarks/lib/remove_obsolete_children'
3
3
 
4
4
  module AcademicBenchmarks
5
5
  module Standards
6
6
  class Standard
7
+ include AttrToVals
7
8
  include InstVarsToHash
8
- include RemoveObsoleteChildren
9
9
 
10
- attr_reader :status, :deepest, :children
11
- attr_writer :grade
12
- attr_accessor :guid, :description, :number, :stem, :label, :level,
13
- :version, :seq, :adopt_year, :authority, :course,
14
- :document, :has_relations, :subject, :subject_doc,
10
+ attr_reader :status, :children
11
+ attr_writer :education_levels
12
+ attr_accessor :guid,
13
+ :statement,
14
+ :number, :stem, :label, :level,
15
+ :seq,
16
+ :section,
17
+ :document, :disciplines,
18
+ :utilizations,
15
19
  :parent, :parent_guid
16
20
 
17
- alias_method :descr, :description
18
-
21
+ # Before standards are rebranched in Authority#rebranch_children
22
+ # or Document#rebranch_children, they have the following structure.
23
+ #
24
+ # Standard
25
+ # |-> Document
26
+ # | |-> Publication
27
+ # | |-> Authority
28
+ # |-> Section
29
+ #
19
30
  def initialize(data)
20
- data = data["data"] if data["data"]
21
- @guid = data["guid"]
22
- @grade = attr_to_val_or_nil(Grade, data, "grade")
23
- @label = data["label"]
24
- @level = data["level"]
25
- @course = attr_to_val_or_nil(Course, data, "course")
26
- @number = data["number"]
27
- @status = data["status"]
28
- @parent = nil
29
- @subject = attr_to_val_or_nil(Subject, data, "subject")
30
- @deepest = data["deepest"]
31
- @version = data["version"]
31
+ attributes = data["attributes"]
32
+ @guid = attributes["guid"]
33
+ @education_levels = attr_to_val_or_nil(EducationLevels, attributes, "education_levels")
34
+ @label = attributes["label"]
35
+ @level = attributes["level"]
36
+ @section = attr_to_val_or_nil(Section, attributes, "section")
37
+ @number = attr_to_val_or_nil(Number, attributes, "number")
38
+ @status = attributes["status"]
39
+ @disciplines = attr_to_val_or_nil(Disciplines, attributes, "disciplines")
32
40
  @children = []
33
- @document = attr_to_val_or_nil(Document, data, "document")
34
- @authority = attr_to_val_or_nil(Authority, data, "authority")
35
- @adopt_year = data["adopt_year"]
36
- @description = data["descr"]
37
- @subject_doc = attr_to_val_or_nil(SubjectDoc, data, "subject_doc")
38
- @has_relations = attr_to_val_or_nil(HasRelations, data, "has_relations")
39
-
40
- # Parent guid extraction can be a little more complicated
41
- if data["parent"] && data["parent"].is_a?(String)
42
- @parent_guid = data["parent"]
43
- elsif data["parent"] && data["parent"].is_a?(Hash)
44
- @parent_guid = data["parent"]["guid"]
45
- end
41
+ @document = attr_to_val_or_nil(Document, attributes, "document")
42
+ @statement = attr_to_val_or_nil(Statement, attributes, "statement")
43
+ @utilizations = attr_to_vals(Utilizations, attributes["utilizations"])
44
+ @parent_guid = data.dig("relationships", "parent", "data", "id")
46
45
  end
47
46
 
48
47
  alias_method :from_hash, :initialize
49
48
 
50
- def active?
51
- status == "Active"
52
- end
53
-
54
- def obsolete?
55
- status == "Obsolete"
56
- end
57
-
58
- def deepest?
59
- deepest == 'Y'
60
- end
61
-
62
- def status=(status)
63
- unless %w[Active Obsolete].include?(status)
64
- raise ArgumentError.new(
65
- "Standard status must be either 'Active' or 'Obsolete'"
66
- )
67
- end
68
- @status = status
69
- end
70
-
71
- def deepest=(deepest)
72
- unless %w[Y N].include?(deepest)
73
- raise ArgumentError.new("Standard deepest must be either 'Y' or 'N'")
74
- end
75
- @deepest = deepest
76
- end
77
-
78
49
  def add_child(child)
79
50
  raise StandardError.new("Tried to add self as a child") if self == child
80
51
 
@@ -94,17 +65,13 @@ module AcademicBenchmarks
94
65
  @children.count > 0
95
66
  end
96
67
 
97
- def leaf?
98
- !has_children?
99
- end
100
-
101
- def grade
102
- return @grade if @grade
68
+ def education_levels
69
+ return @education_levels if @education_levels
103
70
 
104
- # check to see if one of our parents has a grade. Use that if so
71
+ # check to see if one of our parents has education levels. Use that if so
105
72
  p = parent
106
73
  while p
107
- return p.grade if p.grade
74
+ return p.education_levels if p.education_levels
108
75
  p = p.parent
109
76
  end
110
77
  nil
@@ -1,36 +1,17 @@
1
1
  module AcademicBenchmarks
2
2
  module Standards
3
3
  class StandardsForest
4
- attr_reader :trees, :data_hash, :orphans
5
-
6
- # The guid to standard hash can optionally be saved to permit speedily
7
- # adding standards to the tree (since the tree is unordered,
8
- # this would otherwise be an expensive operation).
9
- #
10
- # The initial data hash can also be optionally saved to
11
- # permit testing and internal consistency checks
12
-
13
- def initialize(
14
- data_hash,
15
- save_guid_to_standard_hash: true,
16
- save_initial_data_hash: false,
17
- include_obsoletes: true
18
- )
19
- @data_hash = data_hash.dup.freeze if save_initial_data_hash
4
+ attr_reader :trees, :orphans
5
+
6
+ def initialize(data_hash)
20
7
  @guid_to_standard = {} # a hash of guids to standards
21
8
  @trees = []
22
9
  @orphans = []
23
10
  process_items(data_hash)
24
11
 
25
- @trees.delete_if(&:obsolete?) unless include_obsoletes
26
-
27
12
  # upgrade the hash data to a StandardsTree object
28
13
  @trees.map! do |item|
29
- StandardsTree.new(
30
- item,
31
- build_item_hash: save_guid_to_standard_hash,
32
- include_obsoletes: include_obsoletes
33
- )
14
+ StandardsTree.new(item)
34
15
  end
35
16
 
36
17
  # We will still have the guid-to-standards saved at the Tree level,
@@ -47,21 +28,6 @@ module AcademicBenchmarks
47
28
  StandardsTree.new(root).tap{ |st| st.add_orphans(@orphans) }
48
29
  end
49
30
 
50
- def add_standard(standard)
51
- if standard.is_a?(Standard)
52
- raise StandardError.new(
53
- "adding standards is not currently implemented"
54
- )
55
- elsif standard.is_a?(Hash)
56
- add_standard(Standard.new(standard))
57
- else
58
- raise ArgumentError.new(
59
- "standard must be an 'AcademicBenchmarks::Standards::Standard' " \
60
- "or a 'Hash' but was a #{standard.class}"
61
- )
62
- end
63
- end
64
-
65
31
  def single_tree?
66
32
  @trees.count == 1
67
33
  end
@@ -6,40 +6,10 @@ module AcademicBenchmarks
6
6
  attr_reader :root, :orphans
7
7
  delegate :children, :to_s, :to_h, :to_json, to: :root
8
8
 
9
- # The item hash can optionally be built to permit the speedy
10
- # addition of standards to the tree. since the tree is unordered,
11
- # adding to it can be expensive without this
12
-
13
- def initialize(root, build_item_hash: true, include_obsoletes: true)
9
+ def initialize(root)
14
10
  @orphans = []
15
11
  @root = root
16
- prune_obsolete_branches unless include_obsoletes
17
-
18
- if build_item_hash
19
- @item_hash = {}
20
- go_ahead_and_build_item_hash
21
- end
22
- end
23
-
24
- def add_standard(standard)
25
- if standard.is_a?(Standard)
26
- parent = @item_hash ? @item_hash[standard.parent_guid] : find_parent(standard)
27
- unless parent
28
- raise StandardError.new(
29
- "Parent of standard not found in tree. Parent guid is " \
30
- "'#{standard.parent_guid}' and child guid is '#{standard.guid}'"
31
- )
32
- end
33
- parent.add_child(standard)
34
- standard.parent = parent
35
- elsif standard.is_a?(Hash)
36
- add_standard(Standard.new(standard))
37
- else
38
- raise ArgumentError.new(
39
- "standard must be an 'AcademicBenchmarks::Standards::Standard' " \
40
- "or a 'Hash' but was a #{standard.class}"
41
- )
42
- end
12
+ root.rebranch_children if root.is_a?(Authority) || root.is_a?(Publication)
43
13
  end
44
14
 
45
15
  def add_orphan(orphan)
@@ -53,37 +23,6 @@ module AcademicBenchmarks
53
23
  def has_orphans?
54
24
  @orphans.present?
55
25
  end
56
-
57
- private
58
-
59
- def go_ahead_and_build_item_hash
60
- @item_hash[@root.guid] = @root
61
- add_children_to_item_hash(@root)
62
- end
63
-
64
- def add_children_to_item_hash(parent)
65
- parent.children.each do |child|
66
- @item_hash[child.guid] = child
67
- add_children_to_item_hash(child) if child.has_children?
68
- end
69
- end
70
-
71
- def find_parent(standard)
72
- return @root if @root.guid == standard.parent_guid
73
- check_children_for_parent(standard.parent_guid, @root)
74
- end
75
-
76
- # does a depth-first search
77
- def check_children_for_parent(parent_guid, standard)
78
- standard.children.each do |child|
79
- return child if child.guid == parent_guid
80
- check_children_for_parent(parent_guid, child) if child.has_children?
81
- end
82
- end
83
-
84
- def prune_obsolete_branches
85
- root.remove_obsolete_children
86
- end
87
26
  end
88
27
  end
89
28
  end