academic_benchmarks 0.0.8 → 1.0.1

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.
Files changed (27) hide show
  1. checksums.yaml +5 -5
  2. data/lib/academic_benchmarks/api/auth.rb +7 -5
  3. data/lib/academic_benchmarks/api/constants.rb +2 -20
  4. data/lib/academic_benchmarks/api/handle.rb +2 -22
  5. data/lib/academic_benchmarks/api/standards.rb +130 -85
  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 +36 -10
  9. data/lib/academic_benchmarks/standards/disciplines.rb +21 -0
  10. data/lib/academic_benchmarks/standards/document.rb +15 -7
  11. data/lib/academic_benchmarks/standards/education_levels.rb +21 -0
  12. data/lib/academic_benchmarks/standards/grade.rb +5 -6
  13. data/lib/academic_benchmarks/standards/number.rb +23 -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 +38 -71
  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 +4 -5
  21. data/lib/academic_benchmarks/standards/utilizations.rb +19 -0
  22. metadata +52 -20
  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
- require_relative '../lib/inst_vars_to_hash'
2
- require_relative '../lib/remove_obsolete_children'
1
+ require 'academic_benchmarks/lib/inst_vars_to_hash'
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
@@ -1,19 +1,18 @@
1
- require_relative '../lib/inst_vars_to_hash'
1
+ require 'academic_benchmarks/lib/inst_vars_to_hash'
2
2
 
3
3
  module AcademicBenchmarks
4
4
  module Standards
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,23 @@
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 :enhanced, :raw
9
+
10
+ def self.from_hash(hash)
11
+ self.new(
12
+ enhanced: hash["enhanced"],
13
+ raw: hash["raw"]
14
+ )
15
+ end
16
+
17
+ def initialize(enhanced:, raw:)
18
+ @enhanced = enhanced
19
+ @raw = raw
20
+ end
21
+ end
22
+ end
23
+ 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_relative '../lib/inst_vars_to_hash'
2
- require_relative '../lib/remove_obsolete_children'
1
+ require 'academic_benchmarks/lib/attr_to_vals'
2
+ require 'academic_benchmarks/lib/inst_vars_to_hash'
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