ims_caliper 0.1.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 (97) hide show
  1. checksums.yaml +15 -0
  2. data/Gemfile +13 -0
  3. data/Gemfile.lock +16 -0
  4. data/README.md +16 -0
  5. data/caliper.gemspec +26 -0
  6. data/config/locales/en.yml +86 -0
  7. data/lib/caliper/client.rb +33 -0
  8. data/lib/caliper/consumer/base.rb +46 -0
  9. data/lib/caliper/consumer/queue.rb +40 -0
  10. data/lib/caliper/consumer/socket.rb +132 -0
  11. data/lib/caliper/defaults.rb +8 -0
  12. data/lib/caliper/entities/annotation/annotation.rb +29 -0
  13. data/lib/caliper/entities/annotation/bookmark_annotation.rb +17 -0
  14. data/lib/caliper/entities/annotation/highlight_annotation.rb +18 -0
  15. data/lib/caliper/entities/annotation/shared_annotation.rb +18 -0
  16. data/lib/caliper/entities/annotation/tag_annotation.rb +17 -0
  17. data/lib/caliper/entities/annotation/text_position_selector.rb +14 -0
  18. data/lib/caliper/entities/digital_resource.rb +52 -0
  19. data/lib/caliper/entities/entity.rb +44 -0
  20. data/lib/caliper/entities/foaf/agent.rb +12 -0
  21. data/lib/caliper/entities/generatable.rb +9 -0
  22. data/lib/caliper/entities/learning_context.rb +21 -0
  23. data/lib/caliper/entities/lis/course_section.rb +18 -0
  24. data/lib/caliper/entities/lis/organization.rb +22 -0
  25. data/lib/caliper/entities/lis/person.rb +12 -0
  26. data/lib/caliper/entities/outcome/result.rb +23 -0
  27. data/lib/caliper/entities/reading/epub_chapter.rb +20 -0
  28. data/lib/caliper/entities/reading/epub_part.rb +20 -0
  29. data/lib/caliper/entities/reading/epub_sub_chapter.rb +20 -0
  30. data/lib/caliper/entities/reading/epub_volume.rb +20 -0
  31. data/lib/caliper/entities/reading/frame.rb +32 -0
  32. data/lib/caliper/entities/schemadotorg/audio_object.rb +15 -0
  33. data/lib/caliper/entities/schemadotorg/creative_work.rb +12 -0
  34. data/lib/caliper/entities/schemadotorg/image_object.rb +15 -0
  35. data/lib/caliper/entities/schemadotorg/media_object.rb +19 -0
  36. data/lib/caliper/entities/schemadotorg/software_application.rb +11 -0
  37. data/lib/caliper/entities/schemadotorg/thing.rb +9 -0
  38. data/lib/caliper/entities/schemadotorg/video_object.rb +15 -0
  39. data/lib/caliper/entities/schemadotorg/web_page.rb +11 -0
  40. data/lib/caliper/entities/session.rb +26 -0
  41. data/lib/caliper/entities/software_application.rb +19 -0
  42. data/lib/caliper/entities/targetable.rb +12 -0
  43. data/lib/caliper/entities/web_page.rb +13 -0
  44. data/lib/caliper/event/.shared.rb.swp +0 -0
  45. data/lib/caliper/event/annotation_event.rb +14 -0
  46. data/lib/caliper/event/event.rb +68 -0
  47. data/lib/caliper/event/media_event.rb +19 -0
  48. data/lib/caliper/event/navigation_event.rb +23 -0
  49. data/lib/caliper/event/outcome_event.rb +20 -0
  50. data/lib/caliper/event/session_event.rb +21 -0
  51. data/lib/caliper/event/view_event.rb +20 -0
  52. data/lib/caliper/options.rb +18 -0
  53. data/lib/caliper/profiles/annotation_profile.rb +61 -0
  54. data/lib/caliper/profiles/profile.rb +46 -0
  55. data/lib/caliper/profiles/reading_profile.rb +36 -0
  56. data/lib/caliper/profiles/session_profile.rb +29 -0
  57. data/lib/caliper/request/event_store_envelope.rb +9 -0
  58. data/lib/caliper/request/event_store_requestor.rb +41 -0
  59. data/lib/caliper/request/http_requestor.rb +42 -0
  60. data/lib/caliper/sensor.rb +37 -0
  61. data/lib/caliper/stats/atomic_wrapper.rb +86 -0
  62. data/lib/caliper/stats/statistic.rb +104 -0
  63. data/lib/caliper/stats/statistics.rb +45 -0
  64. data/lib/caliper/stats/statistics_map.rb +39 -0
  65. data/lib/caliper/validators/error_message.rb +43 -0
  66. data/lib/caliper/validators/event_validator.rb +37 -0
  67. data/lib/caliper/validators/event_validator_context.rb +16 -0
  68. data/lib/caliper/validators/property_type_check.rb +14 -0
  69. data/lib/caliper/validators/session_login_event_validator.rb +103 -0
  70. data/lib/caliper/validators/session_logout_event_validator.rb +102 -0
  71. data/lib/caliper/validators/time_check.rb +30 -0
  72. data/lib/caliper/version.rb +4 -0
  73. data/lib/caliper.rb +17 -0
  74. data/spec/lib/client_spec.rb +35 -0
  75. data/spec/lib/consumer/base_spec.rb +28 -0
  76. data/spec/lib/consumer/queue_spec.rb +16 -0
  77. data/spec/lib/event/annotation_spec.rb +12 -0
  78. data/spec/lib/event/bookmarked_spec.rb +17 -0
  79. data/spec/lib/event/commented_spec.rb +19 -0
  80. data/spec/lib/event/highlighted_spec.rb +18 -0
  81. data/spec/lib/event/navigation_spec.rb +15 -0
  82. data/spec/lib/event/shared_spec.rb +18 -0
  83. data/spec/lib/event/tagged_spec.rb +17 -0
  84. data/spec/lib/event/used_spec.rb +15 -0
  85. data/spec/lib/event/viewed_spec.rb +15 -0
  86. data/spec/spec_helper.rb +26 -0
  87. data/test/caliper/events/session_login_event_test.rb +58 -0
  88. data/test/caliper/events/session_logout_event_test.rb +55 -0
  89. data/test/caliper/events/session_timeout_event_test.rb +55 -0
  90. data/test/caliper/request/http_requestor_test.rb +59 -0
  91. data/test/caliper/test_event.rb +53 -0
  92. data/test/caliper/test_utils.rb +198 -0
  93. data/test/fixtures/caliper_session_login_event.json +71 -0
  94. data/test/fixtures/caliper_session_logout_event.json +52 -0
  95. data/test/fixtures/caliper_session_timeout_event.json +52 -0
  96. data/test/fixtures/event_store_payload.json +85 -0
  97. metadata +165 -0
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZDI0ZGY4YjFhMTE3M2NkYWMxNGNiMDA5OGViMWMzZjcwYzNmZTdkNQ==
5
+ data.tar.gz: !binary |-
6
+ ODk5NGZlMTBiZjdjZTM0N2U0ZjZhMDFhY2VlZWFjYWNhNDNjMjE2MQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MTA3OTY1NjE2ZTMxNTQ1ODFiYzI4MWYzMmQ3ODJiZjM5MGRiN2FkZjRiMTQ3
10
+ OTUzNDJjZjMwMzUyNGRiNDY3MGViN2UwMWM5OGJlMjg0YTNjNmI5NTBlMzAx
11
+ ODg1ODVlZWIyZWY5NjUwNzMwZTJjMGI2YmM5ODA5OGU4OTUxMTI=
12
+ data.tar.gz: !binary |-
13
+ ZjNmNzBjZjg3ZTYwYjQ3YWZhODNiM2RlMWNhOGM0N2Y1ZTY0MzJlMTA4NmUz
14
+ NmFmNWEwNWVmOTAzZTVlZWYwYmIyZDNiNDc2NDlkMDlkNDdhNDc5OGZmYTA0
15
+ ZmQ4YWNlNDVjOGUyNDJkOTNlYzU0NWU1NGZiOThmZTUxZWRkNWM=
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Declare your gem's dependencies in open_data_export.gemspec.
4
+ # Bundler will treat runtime dependencies like base dependencies, and
5
+ # development dependencies will be added by default to the :development group.
6
+
7
+ # the atomic lib
8
+ gem 'atomic', '~> 1.1.99'
9
+
10
+ # translation and localization
11
+ gem 'i18n'
12
+
13
+ gem 'test-unit'
data/Gemfile.lock ADDED
@@ -0,0 +1,16 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ atomic (1.1.99)
5
+ i18n (0.7.0)
6
+ power_assert (0.2.2)
7
+ test-unit (3.0.9)
8
+ power_assert
9
+
10
+ PLATFORMS
11
+ ruby
12
+
13
+ DEPENDENCIES
14
+ atomic (~> 1.1.99)
15
+ i18n
16
+ test-unit
data/README.md ADDED
@@ -0,0 +1,16 @@
1
+ caliper-ruby
2
+ ===================
3
+
4
+ caliper-ruby is a Ruby client for [Caliper](http://www.imsglobal.org) that provides a Ruby implementation of the Caliper Sensor API
5
+
6
+ ## generate the Ruby Gem
7
+
8
+ gem build caliper.gemspec
9
+
10
+ =============
11
+ Use Ruby Style Guide:
12
+
13
+
14
+ https://github.com/styleguide/ruby
15
+
16
+ https://github.com/bbatsov/ruby-style-guide
data/caliper.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ require 'caliper/version'
4
+ Gem::Specification.new do |g|
5
+ g.name = "ims_caliper"
6
+ g.version = Caliper::VERSION
7
+ g.authors = ["Anthus Williams", "Zhen Qian"]
8
+ g.email = ["aj@instructure.com", "zqian@umich.edu"]
9
+ g.homepage = "https://github.com/IMSGlobal/caliper-ruby"
10
+ g.summary = "Caliper Sensor API"
11
+ g.description = "This is the implementation of IMSGlobal Caliper in Ruby"
12
+ g.license = "http://www.imsglobal.org/copyright.html"
13
+
14
+ #g.files = Dir["{app,config,db,lib}/**/*", "Rakefile"]
15
+ g.files = `git ls-files`.split($\)
16
+ g.executables = g.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ g.test_files = g.files.grep(%r{^(test|spec|features)/})
18
+ g.require_path = 'lib'
19
+
20
+ #g.add_dependency "activesupport", '~> 0'
21
+ #g.add_development_dependency "rspec", '~> 0'
22
+ #g.add_development_dependency "simplecov", '~> 0'
23
+ #g.add_development_dependency "simplecov-rcov", '~> 0'
24
+ #g.add_development_dependency "mocha", '~> 0'
25
+ #g.add_development_dependency 'atomic', '~> 1.1.99'
26
+ end
@@ -0,0 +1,86 @@
1
+ en:
2
+ actions:
3
+ annotation:
4
+ attached: "attached"
5
+ bookmarked: "bookmarked"
6
+ classified: "classified"
7
+ commented: "commented"
8
+ described: "described"
9
+ highlighted: "highlighted"
10
+ identified: "identified"
11
+ liked: "liked"
12
+ linked: "linked"
13
+ questioned: "questioned"
14
+ ranked: "ranked"
15
+ recommended: "recommended"
16
+ replied: "replied"
17
+ shared: "shared"
18
+ subscribed: "subscribed"
19
+ tagged: "tagged"
20
+
21
+ assessment:
22
+ paused: "paused"
23
+ restarted: "restarted"
24
+ started: "started"
25
+ submitted: "submitted"
26
+
27
+ item.completed: "completed"
28
+ item.skipped: "skipped"
29
+ item.started: "started"
30
+ item.reviewed: "reviewed"
31
+ item.viewed: "viewed"
32
+
33
+ assignable:
34
+ abandoned: "abandoned"
35
+ activated: "activated"
36
+ completed: "completed"
37
+ deactivated: "deactivated"
38
+ hid: "hid"
39
+ reviewed: "reviewed"
40
+ showed: "showed"
41
+ started: "started"
42
+
43
+ item:
44
+ downloaded: "downloaded"
45
+ uploaded: "uploaded"
46
+
47
+
48
+ media:
49
+ accessibility:
50
+ disabledClosedCaptioning: "disabled closed captioning"
51
+ enabledClosedCaptioning: "enabled closed captioning"
52
+ audio:
53
+ changedVolume: "changed volume"
54
+ muted: "muted"
55
+ unmuted: "unmuted"
56
+ playback:
57
+ changedSpeed: "changed speed"
58
+ ended: "ended"
59
+ forwardedTo: " forwarded to"
60
+ jumpedTo: "jumped to"
61
+ paused: "paused"
62
+ resumed: "resumed"
63
+ rewindedTo: "rewinded to"
64
+ started: "started"
65
+ viewer:
66
+ changedResolution: "changed resolution"
67
+ changedSize: "changed viewer size"
68
+ enteredFullScreen: "entered full screen"
69
+ openedPopout: "opened popout"
70
+ exitedFullScreen: "exited full screen"
71
+ closedPopout: "closed popout"
72
+
73
+ navigation:
74
+ navigatedTo: "navigated to"
75
+
76
+ outcome:
77
+ graded: "graded"
78
+
79
+ reading:
80
+ searched: "searched"
81
+ viewed: "viewed"
82
+
83
+ session:
84
+ loggedIn: "logged in"
85
+ loggedOut: "logged out"
86
+ timedOut: "timed out"
@@ -0,0 +1,33 @@
1
+
2
+ module Caliper
3
+ class Client
4
+ attr_accessor :api_key, :options, :stats
5
+ def initialize(key, opts = {})
6
+ if opts[:consumer]
7
+ opts[:consumer] = Object.const_get(opts[:consumer]) if opts[:consumer].is_a?(String)
8
+ opts[:consumer] = opts[:consumer].new(key, opts) if opts[:consumer].respond_to?(:new)
9
+ raise ArgumentError, "Expecting Caliper::Consumer but got #{opts[:consumer].class.to_s}" unless opts[:consumer].is_a?(Caliper::Consumer::Base)
10
+ end
11
+ @consumer = opts[:consumer] || Caliper::Consumer::Socket.new(key, opts)
12
+ end
13
+
14
+ def measure(event, timestamp=nil)
15
+ raise ArgumentError, "Expecting Caliper::Event but got #{event.class.to_s}" unless event.is_a?(Caliper::Event::Base)
16
+ #todo ensure timestamp is iso8601
17
+ timestamp ||= Time.now
18
+ action = event.action
19
+ # returned json will serialize nil contexts as []
20
+ learning_context = event.learning_context ? event.learning_context : nil
21
+ activity_context = event.activity_context ? event.activity_context : nil
22
+
23
+ @consumer.measure(action, learning_context, activity_context, timestamp)
24
+ end
25
+
26
+ def describe(entity, timestamp=nil)
27
+ raise ArgumentError, "Expecting Caliper::Entity but got #{entity.class.to_s}" unless entity.is_a?(Caliper::Entity::Base)
28
+ #todo ensure timestamp is iso8601
29
+ timestamp ||= Time.now
30
+ @consumer.describe(entity.type, entity.id, entity.properties, Time.now)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,46 @@
1
+ module Caliper
2
+ module Consumer
3
+ class Base
4
+ attr_reader :api_key
5
+
6
+ def initialize(key, opts = {})
7
+ @api_key = key
8
+ @options = validate_options(opts)
9
+ end
10
+
11
+ def describe(type, id, props, timestamp); end
12
+
13
+ def measure(action, learning_context, activity_context, timestamp); end
14
+
15
+ def with_debug?
16
+ @options[:debug] || false
17
+ end
18
+
19
+ def with_ssl?
20
+ @options[:ssl] || false
21
+ end
22
+
23
+ def on_error(error)
24
+ if with_debug?
25
+ #todo: log if debug
26
+ end
27
+
28
+ if @options[:on_error]
29
+ @options[:on_error].call(error)
30
+ end
31
+ end
32
+
33
+ def validate_options(opts)
34
+ hsh = {}
35
+ hsh[:debug] = opts[:debug] ? true : false
36
+ hsh[:ssl] = opts[:ssl] ? true : false
37
+ if opts[:on_error]
38
+ raise ArgumentError, "on_error option should be callable" unless opts[:on_error].is_a?(Proc)
39
+ hsh[:on_error] = opts[:on_error]
40
+ end
41
+ hsh
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,40 @@
1
+ module Caliper
2
+ module Consumer
3
+ class Queue < Base
4
+ attr_reader :max_queue_size, :batch_size
5
+
6
+ def initialize(key, opts = {})
7
+ super
8
+ @queue = []
9
+ end
10
+
11
+ def validate_options(opts)
12
+ hsh = super
13
+ @max_queue_size = hsh[:max_queue_size] = opts[:max_queue_size].to_i
14
+ @batch_size = hsh[:batch_size] = opts[:batch_size].to_i
15
+ hsh
16
+ end
17
+
18
+ def measure(action, learning_context, activity_context, timestamp)
19
+ enqueue OpenStruct.new(api_key: @api_key, action: action, learning_context: learning_context, activity_context: activity_context, timestamp: timestamp, proc_name: "measure")
20
+ end
21
+
22
+ def describe(type, id, properties, timestamp)
23
+ enqueue OpenStruct.new(api_key: @api_key, entity_type: type, entity_id: id, properties: properties, timestamp: timestamp, proc_name: "describe")
24
+ end
25
+
26
+ def enqueue(item)
27
+ if item.proc_name == "measure"
28
+ flush_measure(item)
29
+ elsif item.proc_name == "describe"
30
+ flush_describe(item)
31
+ end
32
+ end
33
+
34
+ def flush_measure(item); end
35
+
36
+ def flush_describe(item); end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,132 @@
1
+ require 'socket'
2
+ require 'openssl'
3
+ require "active_support"
4
+
5
+ module Caliper
6
+ module Consumer
7
+ class Socket < Queue
8
+ attr_reader :socket
9
+
10
+ def initialize(key, opts = {})
11
+ super
12
+ end
13
+
14
+ def validate_options(opts)
15
+ hsh = super(opts)
16
+ hsh[:timeout] = opts[:timeout] || 0.5
17
+ hsh[:host] = opts[:host] || "localhost"
18
+ hsh[:port] = opts[:port] || ( hsh[:ssl] ? 443 : 80 )
19
+ hsh[:max_response_size] = opts[:max_response_size] || 2048
20
+ hsh
21
+ end
22
+
23
+ private
24
+
25
+ def flush_describe(item)
26
+ socket = init_socket
27
+ return unless socket
28
+
29
+ send_request( socket, describe_body( @options[:host], ActiveSupport::JSON.encode(item)) )
30
+ end
31
+
32
+ def flush_measure(item)
33
+ socket = init_socket
34
+ return unless socket
35
+
36
+ send_request( socket, measure_body( @options[:host], ActiveSupport::JSON.encode(item)) )
37
+ end
38
+
39
+ # both describe_body and measure_body hardcode a URL as is the case with caliper-php
40
+ # todo: make this configurable
41
+ def describe_body(host, content)
42
+ <<-STR.gsub(/^ {10}/,'')
43
+ PUT /v1/describe HTTP/1.1/
44
+ Host: #{host}
45
+ Content-Type: application/json
46
+ Accept: application\json
47
+ Content-length: #{content.length}
48
+
49
+ #{content}
50
+ STR
51
+ end
52
+
53
+ def measure_body(host, content)
54
+ <<-STR.gsub(/^ {10}/,'')
55
+ PUT /v1/learningevent HTTP/1.1/
56
+ Host: #{host}
57
+ Content-Type: application/json
58
+ Accept: application\json
59
+ Content-length: #{content.length}
60
+
61
+ #{content}
62
+ STR
63
+ end
64
+
65
+ def init_socket
66
+ # if socket has failed, don't keep trying to connect on future events
67
+ return if @socket_failed
68
+ begin
69
+ s = TCPSocket.new(@options[:host], @options[:port])
70
+ if with_ssl?
71
+ s = OpenSSL::SSL::SSLSocket.new(s)
72
+ s.sync_close
73
+ s.connect
74
+ end
75
+ rescue SocketError => e
76
+ on_error(e)
77
+ @socket_failed = true
78
+ return
79
+ end
80
+ s
81
+ end
82
+
83
+ def send_request(socket, body, with_retries = 1)
84
+ written = 0
85
+ closed = false
86
+ while !closed && bytes_written < body.bytesize
87
+ begin
88
+ bytes_written = socket.write(body[bytes_written..-1])
89
+ if bytes_written.zero?
90
+ closed = true
91
+ else
92
+ written += bytes_written
93
+ end
94
+ rescue SocketError => e
95
+ on_error(e)
96
+ closed = true
97
+ end
98
+ end
99
+
100
+ if closed
101
+ socket.close
102
+ # attempt to retry connection up to with_retries times
103
+ unless with_retries.zero?
104
+ socket = init_socket
105
+ return send_request(socket, body, with_retries - 1) if socket
106
+ end
107
+ return false
108
+ end
109
+
110
+ success = true
111
+
112
+ # if debug is enabled, wait for response
113
+ if with_debug?
114
+ r = parse_response(socket.read(@options[:max_response_size]))
115
+ unless r.status == 200
116
+ #todo build exception and send it to on_error
117
+ success = false
118
+ end
119
+ end
120
+
121
+ return success
122
+ end
123
+
124
+ def parse_response(resp)
125
+ contents = resp.split("\n")
126
+ status = contents.first.split(" ")
127
+ OpenStruct.new(:status => (status.length > 1 ? status[1] : nil), :message => contents.last)
128
+ end
129
+
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,8 @@
1
+ module Caliper
2
+ class Defaults
3
+ HOST = "http://dev-null.comt"
4
+ CONNECTION_TIMEOUT = 10000
5
+ SO_TIMEOUT = 10000
6
+ CONNECTION_REQUEST_TIMEOUT = 10000
7
+ end
8
+ end
@@ -0,0 +1,29 @@
1
+ require_relative '../../entities/entity'
2
+ require_relative '../../entities/schemadotorg/thing'
3
+
4
+ module Caliper
5
+ module Entities
6
+ module Annotation
7
+ module AnnotationType
8
+ ANNOTATION = "http://purl.imsglobal.org/caliper/v1/Annotation"
9
+ BOOKMARK_ANNOTATION = "http://purl.imsglobal.org/caliper/v1/BookmarkAnnotation"
10
+ HIGHLIGHT_ANNOTATION = "http://purl.imsglobal.org/caliper/v1/HighlightAnnotation"
11
+ SHARED_ANNOTATION = "http://purl.imsglobal.org/caliper/v1/SharedAnnotation"
12
+ TAG_ANNOTATION = "http://purl.imsglobal.org/caliper/v1/TagAnnotation"
13
+ end
14
+
15
+ ## implement the interface Thing
16
+ class Annotation < Entity
17
+ include Caliper::Entities::SchemaDotOrg::Thing
18
+ attr_accessor :target,
19
+ :type
20
+
21
+ def initialize
22
+ super
23
+ type = AnnotationType::ANNOTATION
24
+ target = ''
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,17 @@
1
+ require_relative 'annotation'
2
+
3
+ module Caliper
4
+ module Entities
5
+ module Annotation
6
+ class Bookmark < Annotation
7
+ attr_accessor :type,
8
+ :bookmark_notes
9
+
10
+ def initialize(action)
11
+ super
12
+ @type = AnnotationType::BOOKMARK_ANNOTATION
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ require_relative 'annotation'
2
+
3
+ module Caliper
4
+ module Entities
5
+ module Annotation
6
+ class HighlightAnnotation < Annotation
7
+ attr_accessor :type,
8
+ :bookmark_notes
9
+
10
+ def initialize()
11
+ super
12
+ @type = AnnotationType::HIGHLIGHT_ANNOTATION
13
+ @bookmark_notes = ''
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ require_relative 'annotation'
2
+
3
+ module Caliper
4
+ module Entities
5
+ module Annotation
6
+ class SharedAnnotation < Annotation
7
+ attr_accessor :with_agents, # list of Agent object
8
+ :type
9
+
10
+ def initialize()
11
+ super
12
+ @type = AnnotationType::SHARED_ANNOTATION
13
+ @with_agents = ''
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ require_relative 'Annotation'
2
+
3
+ module Caliper
4
+ module Entities
5
+ module Annotation
6
+ class TagAnnotation < Annotation
7
+ attr_accessor :type,
8
+ :tags
9
+
10
+ def initialize()
11
+ super
12
+ @type = AnnotationType::TAG_ANNOTATION
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+
2
+ # An Selector which describes a range of text based on its start and end positions
3
+ # Defined by: http://www.w3.org/ns/oa#d4e667
4
+
5
+ module Caliper
6
+ module Entities
7
+ module Annotation
8
+ class TextPositionSelector
9
+ attr_accessor :start,
10
+ :end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,52 @@
1
+ require "json"
2
+ require_relative 'entity'
3
+
4
+ # Public: Caliper representation of a CreativeWork (https://schema.org/CreativeWork)
5
+ # We add learning specific attributes, including a list of
6
+ # LearningObjective learning objectives and a list of
7
+ # String keywords
8
+ #
9
+ # Examples
10
+ #
11
+
12
+ module Caliper
13
+ module Entities
14
+ module DigitalResourceType
15
+ ASSIGNABLE_DIGITAL_RESOURCE = "http://purl.imsglobal.org/caliper/v1/AssignableDigitalResource"
16
+ EPUB_CHAPTER = "http://www.idpf.org/epub/vocab/structure/#chapter"
17
+ EPUB_PART = "http://www.idpf.org/epub/vocab/structure/#part"
18
+ EPUB_SUB_CHAPTER = "http://www.idpf.org/epub/vocab/structure/#subchapter"
19
+ EPUB_VOLUME = "http://www.idpf.org/epub/vocab/structure/#volume"
20
+ FRAME = "http://purl.imsglobal.org/caliper/v1/Frame"
21
+ MEDIA_LOCATION = "http://purl.imsglobal.org/caliper/v1/MediaLocation"
22
+ MEDIA_OBJECT = "http://purl.imsglobal.org/caliper/v1/MediaObject"
23
+ READING = "http://www.idpf.org/epub/vocab/structure"
24
+ WEB_PAGE = "http://purl.imsglobal.org/caliper/v1/WebPage"
25
+ end
26
+ class DigitalResource < Entity
27
+ attr_accessor :type,
28
+ :object_types, # list of String
29
+ :learning_objectives, # a list of learning objectives
30
+ :keywords,
31
+ :is_part_of,
32
+ :date_published
33
+
34
+ # Public:
35
+ def to_json(*a)
36
+ {
37
+ "type" => @type,
38
+ "objectTypes" => @object_types,
39
+ "learningObjective" => @learning_objectives,
40
+ "keywords" => @keywords,
41
+ "isPartOf" => @is_part_of,
42
+ "datePublished" => @date_published
43
+ }.to_json(*a)
44
+ end
45
+
46
+ def initialize()
47
+ super
48
+ @type = EntityType::DIGITAL_RESOURCE
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,44 @@
1
+ require "json"
2
+
3
+ ##
4
+ ## The base Caliper Entity. Analogous to a schema.org Thing.
5
+ ##
6
+ module Caliper
7
+ module Entities
8
+ module EntityType
9
+ AGENT = "http://purl.imsglobal.org/caliper/v1/Agent"
10
+ ATTEMPT = "http://purl.imsglobal.org/caliper/v1/Attempt"
11
+ DIGITAL_RESOURCE = "http://purl.imsglobal.org/caliper/v1/DigitalResource"
12
+ ENTITY = "http://purl.imsglobal.org/caliper/v1/Entity"
13
+ GENERATED = "http://purl.imsglobal.org/caliper/v1/Generated"
14
+ LEARNING_OBJECTIVE = "http://purl.imsglobal.org/caliper/v1/LearningObjective"
15
+ LIS_PERSON = "http://purl.imsglobal.org/caliper/v1/lis/Person"
16
+ LIS_ORGANIZATION = "http://purl.imsglobal.org/caliper/v1/lis/Organization"
17
+ RESULT = "http://purl.imsglobal.org/caliper/v1/Result"
18
+ SESSION = "http://purl.imsglobal.org/caliper/v1/Session"
19
+ SOFTWARE_APPLICATION = "http://purl.imsglobal.org/caliper/v1/SoftwareApplication"
20
+ TARGET = "http://purl.imsglobal.org/caliper/v1/Target"
21
+ VIEW = "http://purl.imsglobal.org/caliper/v1/View"
22
+ end
23
+
24
+ class Entity
25
+ attr_accessor :id,
26
+ :type,
27
+ :name,
28
+ :description,
29
+ :properties,
30
+ :date_created,
31
+ :date_modified
32
+
33
+ def initialize()
34
+ @id = ""
35
+ @type = EntityType::ENTITY
36
+ @name = ""
37
+ @description = ""
38
+ @properties = ""
39
+ @date_created = Time.now.utc
40
+ @date_modified = Time.now.utc
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,12 @@
1
+ require_relative '../../entities/entity'
2
+ # Public: From http://xmlns.com/foaf/spec/#term_Agent An agent (eg. person,
3
+ # group, software or physical artifact)
4
+ module Caliper
5
+ module Entities
6
+ module FOAF
7
+ module Agent
8
+
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ # The generatable interface marks an object type that is created or generated as a result of an action.
2
+ # The interface allows Caliper to catch errors at compile time for instances of the marked class rather
3
+ # than at runtime if a marker annotation was defined instead.
4
+ module Caliper
5
+ module Entities
6
+ module Generatable
7
+ end
8
+ end
9
+ end