growthtribe_xapi 0.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 (68) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yml +28 -0
  3. data/CHANGELOG.md +2 -0
  4. data/CONTRIBUTING.md +7 -0
  5. data/Gemfile +4 -0
  6. data/Gemfile.lock +78 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +299 -0
  9. data/Rakefile +12 -0
  10. data/bin/rspec +29 -0
  11. data/lib/growthtribe_xapi.rb +2 -0
  12. data/lib/xapi.rb +224 -0
  13. data/lib/xapi/about.rb +15 -0
  14. data/lib/xapi/activity.rb +37 -0
  15. data/lib/xapi/activity_definition.rb +131 -0
  16. data/lib/xapi/agent.rb +44 -0
  17. data/lib/xapi/agent_account.rb +33 -0
  18. data/lib/xapi/attachment.rb +64 -0
  19. data/lib/xapi/context.rb +54 -0
  20. data/lib/xapi/context_activities.rb +102 -0
  21. data/lib/xapi/documents/activity_profile_document.rb +15 -0
  22. data/lib/xapi/documents/agent_profile_document.rb +15 -0
  23. data/lib/xapi/documents/document.rb +20 -0
  24. data/lib/xapi/documents/state_document.rb +15 -0
  25. data/lib/xapi/enum.rb +42 -0
  26. data/lib/xapi/errors.rb +9 -0
  27. data/lib/xapi/group.rb +37 -0
  28. data/lib/xapi/interaction_component.rb +32 -0
  29. data/lib/xapi/interaction_type.rb +58 -0
  30. data/lib/xapi/lrs_response.rb +14 -0
  31. data/lib/xapi/query_result_format.rb +6 -0
  32. data/lib/xapi/remote_lrs.rb +416 -0
  33. data/lib/xapi/result.rb +46 -0
  34. data/lib/xapi/score.rb +39 -0
  35. data/lib/xapi/statement.rb +53 -0
  36. data/lib/xapi/statement_ref.rb +31 -0
  37. data/lib/xapi/statements/statements_base.rb +70 -0
  38. data/lib/xapi/statements_query.rb +42 -0
  39. data/lib/xapi/statements_query_v095.rb +42 -0
  40. data/lib/xapi/statements_result.rb +17 -0
  41. data/lib/xapi/sub_statement.rb +19 -0
  42. data/lib/xapi/tcapi_version.rb +27 -0
  43. data/lib/xapi/team.rb +44 -0
  44. data/lib/xapi/team_analytics_query.rb +36 -0
  45. data/lib/xapi/verb.rb +35 -0
  46. data/lib/xapi/version.rb +4 -0
  47. data/spec/fixtures/about.json +10 -0
  48. data/spec/fixtures/statement.json +33 -0
  49. data/spec/spec_helper.rb +107 -0
  50. data/spec/support/helpers.rb +60 -0
  51. data/spec/xapi/activity_definition_spec.rb +37 -0
  52. data/spec/xapi/activity_spec.rb +23 -0
  53. data/spec/xapi/agent_account_spec.rb +13 -0
  54. data/spec/xapi/agent_spec.rb +24 -0
  55. data/spec/xapi/attachment_spec.rb +26 -0
  56. data/spec/xapi/context_activities_spec.rb +57 -0
  57. data/spec/xapi/context_spec.rb +32 -0
  58. data/spec/xapi/group_spec.rb +15 -0
  59. data/spec/xapi/interaction_component_spec.rb +18 -0
  60. data/spec/xapi/remote_lrs_spec.rb +46 -0
  61. data/spec/xapi/result_spec.rb +24 -0
  62. data/spec/xapi/score_spec.rb +12 -0
  63. data/spec/xapi/statement_ref_spec.rb +19 -0
  64. data/spec/xapi/statement_spec.rb +73 -0
  65. data/spec/xapi/sub_statement_spec.rb +30 -0
  66. data/spec/xapi/verb_spec.rb +17 -0
  67. data/xapi.gemspec +30 -0
  68. metadata +244 -0
data/lib/xapi/agent.rb ADDED
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+ require 'xapi/tcapi_version'
3
+ module Xapi
4
+ # Agent model class
5
+ class Agent
6
+
7
+ attr_accessor :name, :mbox, :mbox_sha1_sum, :open_id, :account, :object_type
8
+
9
+ def initialize(options={}, &block)
10
+ @object_type = 'Agent'
11
+ json = options.fetch(:json, nil)
12
+ if json
13
+ attributes = JSON.parse(json)
14
+ self.name = attributes['name'] if attributes['name']
15
+ self.mbox = attributes['mbox'] if attributes['mbox']
16
+ self.mbox_sha1_sum = attributes['mbox_sha1sum'] if attributes['mbox_sha1sum']
17
+ self.open_id = attributes['openid'] if attributes['openid']
18
+ self.account = AgentAccount.new(json: attributes['account'].to_json) if attributes['account']
19
+ else
20
+ self.name = options.fetch(:name, nil)
21
+ self.mbox = options.fetch(:mbox, nil)
22
+ self.mbox_sha1_sum = options.fetch(:mbox_sha1_sum, nil)
23
+ self.open_id = options.fetch(:open_id, nil)
24
+ self.account = options.fetch(:account, nil)
25
+
26
+ if block_given?
27
+ block[self]
28
+ end
29
+ end
30
+ end
31
+
32
+ def serialize(version)
33
+ node = {}
34
+ node['objectType'] = object_type
35
+ node['name'] = name if name
36
+ node['mbox'] = mbox if mbox
37
+ node['mbox_sha1sum'] = mbox_sha1_sum if mbox_sha1_sum
38
+ node['openid'] = open_id if open_id
39
+ node['account'] = account.serialize(version) if account
40
+ node
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+ require 'json'
3
+ module Xapi
4
+ # Agent Account model class
5
+ class AgentAccount
6
+
7
+ attr_accessor :homePage, :name
8
+
9
+ def initialize(options={}, &block)
10
+ json = options.fetch(:json, nil)
11
+ if json
12
+ attributes = JSON.parse(json)
13
+ self.name = attributes['name'] if attributes['name']
14
+ self.homePage = attributes['homePage'] if attributes['homePage']
15
+ else
16
+ self.homePage = options.fetch(:home_page, nil)
17
+ self.name =options.fetch(:name, nil)
18
+
19
+ if block_given?
20
+ block[self]
21
+ end
22
+ end
23
+ end
24
+
25
+ def serialize(version)
26
+ node = {}
27
+ node['name'] = name if name
28
+ node['homePage'] = homePage if homePage
29
+ node
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+ module Xapi
3
+ # Attachment Class
4
+ class Attachment
5
+
6
+ attr_accessor :display, :description, :content_type, :length, :sha2
7
+ attr_reader :usage_type, :file_url
8
+
9
+ def initialize(options={}, &block)
10
+ json = options.fetch(:json, nil)
11
+ if json
12
+ attributes = JSON.parse(json)
13
+ self.usage_type = attributes['usageType'] if attributes['usageType']
14
+ self.display = attributes['display'] if attributes['display']
15
+ self.description = attributes['description'] if attributes['description']
16
+ self.content_type = attributes['contentType'] if attributes['contentType']
17
+ self.length = attributes['length'] if attributes['length']
18
+ self.sha2 = attributes['sha2'] if attributes['sha2']
19
+ self.file_url = attributes['fileUrl'] if attributes['fileUrl']
20
+ else
21
+ self.usage_type = options.fetch(:usage_type, nil)
22
+ self.display = options.fetch(:display, nil)
23
+ self.description = options.fetch(:description, nil)
24
+ self.content_type = options.fetch(:content_type, nil)
25
+ self.length = options.fetch(:length, nil)
26
+ self.sha2 = options.fetch(:sha2, nil)
27
+ self.file_url = options.fetch(:file_url, nil)
28
+
29
+ if block_given?
30
+ block[self]
31
+ end
32
+ end
33
+ end
34
+
35
+ def usage_type=(value)
36
+ if value.is_a?(String)
37
+ @usage_type = Addressable::URI.parse(value)
38
+ else
39
+ @usage_type = value
40
+ end
41
+ end
42
+
43
+ def file_url=(value)
44
+ if value.is_a?(String)
45
+ @file_url = Addressable::URI.parse(value)
46
+ else
47
+ @file_url = value
48
+ end
49
+ end
50
+
51
+ def serialize(version)
52
+ node = {}
53
+ node['usageType'] = usage_type.to_s if usage_type
54
+ node['display'] = display if display
55
+ node['description'] = description if description
56
+ node['contentType'] = content_type if content_type
57
+ node['length'] = length if length
58
+ node['sha2'] = sha2 if sha2
59
+ node['fileUrl'] = file_url.to_s if file_url
60
+ node
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,54 @@
1
+ # encoding: utf-8
2
+ module Xapi
3
+ # Context Class Description
4
+ class Context
5
+
6
+ attr_accessor :registration, :instructor, :team, :context_activities, :revision
7
+ attr_accessor :platform, :language, :statement, :extensions
8
+
9
+ def initialize(options={}, &block)
10
+ json = options.fetch(:json, nil)
11
+ if json
12
+ attributes = JSON.parse(json)
13
+ self.registration = attributes['registration'] if attributes['registration']
14
+ self.instructor = Xapi::Agent.new(json: attributes['instructor'].to_json) if attributes['instructor']
15
+ self.team = Xapi::Team.new(json: attributes['team'].to_json) if attributes['team']
16
+ self.context_activities = Xapi::ContextActivities.new(json: attributes['contextActivities'].to_json) if attributes['contextActivities']
17
+ self.revision = attributes['revision'] if attributes['revision']
18
+ self.platform = attributes['platform'] if attributes['platform']
19
+ self.language = attributes['language'] if attributes['language']
20
+ self.statement = Xapi::StatementRef.new(json: attributes['statement'].to_json) if attributes['statement']
21
+ self.extensions = attributes['extensions'] if attributes['extensions']
22
+ else
23
+ self.registration = options.fetch(:registration, nil)
24
+ self.instructor = options.fetch(:instructor, nil)
25
+ self.team = options.fetch(:team, nil)
26
+ self.context_activities = options.fetch(:context_activities, nil)
27
+ self.revision = options.fetch(:revision, nil)
28
+ self.platform = options.fetch(:platform, nil)
29
+ self.language = options.fetch(:language, nil)
30
+ self.extensions = options.fetch(:extensions, nil)
31
+
32
+ if block_given?
33
+ block[self]
34
+ end
35
+ end
36
+ end
37
+
38
+ def serialize(version)
39
+ node = {}
40
+ node['registration'] = registration if registration
41
+ node['instructor'] = instructor.serialize(version) if instructor
42
+ node['team'] = team.serialize(version) if team
43
+ node['contextActivities'] = context_activities.serialize(version) if context_activities
44
+ node['revision'] = revision if revision
45
+ node['platform'] = platform if platform
46
+ node['language'] = language if language
47
+ node['statement'] = statement.serialize(version) if statement
48
+ node['extensions'] = extensions if extensions
49
+
50
+ node
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,102 @@
1
+ # encoding: utf-8
2
+ module Xapi
3
+ # ContextActivities Model class
4
+ class ContextActivities
5
+
6
+ attr_accessor :parent, :grouping, :other, :category
7
+
8
+ def initialize(options={}, &block)
9
+ json = options.fetch(:json, nil)
10
+ if json
11
+ attributes = JSON.parse(json)
12
+ if attributes['parent']
13
+ if attributes['parent'].is_a?(Array)
14
+ self.parent = attributes['parent'].map {|element| Activity.new(json: element.to_json)}
15
+ else
16
+ self.parent = [Activity.new(json: attributes['parent'].to_json)]
17
+ end
18
+ end
19
+
20
+ if attributes['grouping']
21
+ if attributes['grouping'].is_a?(Array)
22
+ self.grouping = attributes['grouping'].map {|element| Activity.new(json: element.to_json)}
23
+ else
24
+ self.grouping = [Activity.new(json: attributes['grouping'].to_json)]
25
+ end
26
+ end
27
+
28
+ if attributes['other']
29
+ if attributes['other'].is_a?(Array)
30
+ self.other = attributes['other'].map {|element| Activity.new(json: element.to_json)}
31
+ else
32
+ self.other = [Activity.new(json: attributes['other'].to_json)]
33
+ end
34
+ end
35
+
36
+ if attributes['category']
37
+ if attributes['category'].is_a?(Array)
38
+ self.category = attributes['category'].map {|element| Activity.new(json: element.to_json)}
39
+ else
40
+ self.category = [Activity.new(json: attributes['category'].to_json)]
41
+ end
42
+ end
43
+ else
44
+ self.parent = options.fetch(:parent, nil)
45
+ self.grouping = options.fetch(:grouping, nil)
46
+ self.other = options.fetch(:other, nil)
47
+ self.category = options.fetch(:category, nil)
48
+
49
+ if block_given?
50
+ block[self]
51
+ end
52
+ end
53
+ end
54
+
55
+ def serialize(version)
56
+ node = {}
57
+ if parent && parent.any?
58
+ if version == Xapi::TCAPIVersion::V095 && parent.size > 1
59
+ raise Xapi::Errors::IncompatibleTCAPIVersion, "Version #{version.to_s} doesn't support lists of activities (parent)"
60
+ end
61
+ if version == Xapi::TCAPIVersion::V095
62
+ node['parent'] = parent.first.serialize(version)
63
+ else
64
+ node['parent'] = parent.map {|element| element.serialize(version)}
65
+ end
66
+ end
67
+
68
+ if grouping && grouping.any?
69
+ if version == Xapi::TCAPIVersion::V095 && grouping.size > 1
70
+ raise Xapi::Errors::IncompatibleTCAPIVersion, "Version #{version.to_s} doesn't support lists of activities (grouping)"
71
+ end
72
+ if version == Xapi::TCAPIVersion::V095
73
+ node['grouping'] = grouping.first.serialize(version)
74
+ else
75
+ node['grouping'] = grouping.map {|element| element.serialize(version)}
76
+ end
77
+ end
78
+
79
+ if other && other.any?
80
+ if version == Xapi::TCAPIVersion::V095 && other.size > 1
81
+ raise Xapi::Errors::IncompatibleTCAPIVersion, "Version #{version.to_s} doesn't support lists of activities (other)"
82
+ end
83
+ if version == Xapi::TCAPIVersion::V095
84
+ node['other'] = other.first.serialize(version)
85
+ else
86
+ node['other'] = other.map {|element| element.serialize(version)}
87
+ end
88
+ end
89
+
90
+ if category && category.any?
91
+ if version.ordinal >= Xapi::TCAPIVersion::V100.ordinal
92
+ node['category'] = category.map {|element| element.serialize(version)}
93
+ else
94
+ raise Xapi::Errors::IncompatibleTCAPIVersion, "Version #{version.to_s} doesn't support the category context activity"
95
+ end
96
+ end
97
+
98
+ node
99
+ end
100
+
101
+ end
102
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+ module Xapi
3
+ module Documents
4
+ class ActivityProfileDocument < Document
5
+
6
+ attr_accessor :activity
7
+
8
+ def initialize(&block)
9
+ super(&block)
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+ module Xapi
3
+ module Documents
4
+ class AgentProfileDocument < Document
5
+
6
+ attr_accessor :agent
7
+
8
+ def initialize(&block)
9
+ super(&block)
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+ module Xapi
3
+ module Documents
4
+ class Document
5
+
6
+ attr_accessor :id, :etag, :timestamp, :content_type, :content
7
+
8
+ def initialize(&block)
9
+ if block_given?
10
+ block[self]
11
+ end
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+
18
+ require_relative 'activity_profile_document'
19
+ require_relative 'agent_profile_document'
20
+ require_relative 'state_document'
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+ module Xapi
3
+ module Documents
4
+ class StateDocument < Document
5
+
6
+ attr_accessor :activity, :agent, :registration
7
+
8
+ def initialize(&block)
9
+ super(&block)
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+
data/lib/xapi/enum.rb ADDED
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+ module Xapi
3
+ module Enum
4
+ CONVERT_PROC = Proc.new do
5
+ @values = constants.sort.collect{|c| const_get(c)}.freeze
6
+
7
+ @values.each_with_index do |value, idx|
8
+ the_symbol = constants.find{|c| const_get(c) == value}
9
+ sig = class << value ; self end
10
+ sig.send :define_method, :name, proc{the_symbol}
11
+ sig.send :define_method, :ordinal, proc{idx}
12
+
13
+ if value.is_a? Hash
14
+ value.each do |k, v|
15
+ sig.send :define_method, k, (v.is_a?(Proc) ? v : proc{v})
16
+ end
17
+ end
18
+ value.freeze
19
+ end
20
+
21
+ class << self
22
+ alias :value_of :const_get
23
+ end
24
+
25
+ module_function
26
+ def each
27
+ @values.each { |v| yield v }
28
+ end
29
+ def values
30
+ @values
31
+ end
32
+ extend Enumerable
33
+
34
+ freeze
35
+ end
36
+
37
+ def self.extended extending_obj
38
+ extending_obj.module_eval &CONVERT_PROC
39
+ end
40
+ end
41
+
42
+ end
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+ module Xapi
3
+ module Errors
4
+
5
+ # Raised when an incompatible version is used
6
+ IncompatibleTCAPIVersion = Class.new(StandardError)
7
+
8
+ end
9
+ end
data/lib/xapi/group.rb ADDED
@@ -0,0 +1,37 @@
1
+ # encoding: utf-8
2
+ module Xapi
3
+ # Group model class
4
+ class Group < Agent
5
+
6
+ attr_accessor :members
7
+
8
+ def initialize(options={}, &block)
9
+ super(options, &block)
10
+
11
+ @object_type = 'Group'
12
+ @members = []
13
+ json = options.fetch(:json, nil)
14
+ if json
15
+ attributes = JSON.parse(json)
16
+ attributes['member'].each do |member|
17
+ members << Agent.new(json: member.to_json)
18
+ end
19
+ else
20
+ self.members = options.fetch(:members, nil)
21
+
22
+ if block_given?
23
+ block[self]
24
+ end
25
+ end
26
+ end
27
+
28
+ def serialize(version)
29
+ node = super(version)
30
+ if members.any?
31
+ node['member'] = members.map {|member| member.serialize(version)}
32
+ end
33
+ node
34
+ end
35
+
36
+ end
37
+ end