scorm_engine 0.1.0
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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/Rakefile +13 -0
- data/lib/scorm_engine.rb +13 -0
- data/lib/scorm_engine/api/endpoints.rb +50 -0
- data/lib/scorm_engine/api/endpoints/about.rb +59 -0
- data/lib/scorm_engine/api/endpoints/courses.rb +136 -0
- data/lib/scorm_engine/api/endpoints/courses/configuration.rb +146 -0
- data/lib/scorm_engine/api/endpoints/courses/import.rb +83 -0
- data/lib/scorm_engine/api/endpoints/ping.rb +20 -0
- data/lib/scorm_engine/api/endpoints/registrations.rb +321 -0
- data/lib/scorm_engine/api/endpoints/registrations/configuration.rb +146 -0
- data/lib/scorm_engine/api/endpoints/registrations/launch_history.rb +47 -0
- data/lib/scorm_engine/client.rb +17 -0
- data/lib/scorm_engine/configuration.rb +43 -0
- data/lib/scorm_engine/faraday/connection.rb +35 -0
- data/lib/scorm_engine/faraday/request.rb +54 -0
- data/lib/scorm_engine/models.rb +9 -0
- data/lib/scorm_engine/models/course.rb +66 -0
- data/lib/scorm_engine/models/course_configuration.rb +37 -0
- data/lib/scorm_engine/models/course_import.rb +42 -0
- data/lib/scorm_engine/models/learner.rb +24 -0
- data/lib/scorm_engine/models/registration.rb +82 -0
- data/lib/scorm_engine/models/registration_activity_detail.rb +37 -0
- data/lib/scorm_engine/models/registration_configuration.rb +37 -0
- data/lib/scorm_engine/models/registration_launch_history.rb +92 -0
- data/lib/scorm_engine/models/registration_runtime_interaction.rb +52 -0
- data/lib/scorm_engine/response.rb +26 -0
- data/lib/scorm_engine/utils.rb +13 -0
- data/lib/scorm_engine/version.rb +3 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about/is_successful.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about/knows_the_platform.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about/knows_the_version.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about_user_count/accepts_before_option.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about_user_count/accepts_since_option.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about_user_count/is_successful.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about_user_count/tracks_combined_counts.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about_user_count/tracks_per_tenantcounts.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_delete_course/fails_when_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_delete_course/works.yml +32 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_course_detail/is_successful.yml +41 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_course_detail/results/sucessfully_creates_the_Course_attributes.yml +41 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_course_preview/fails_when_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_course_preview/is_successful.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_course_preview/results/returns_a_URL_string.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/_course_id_option/fetches_a_single_course_but_perhaps_multiple_versions.yml +39 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/_course_id_option/returns_404_when_ID_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/_more_option_pagination_/returns_all_the_courses.yml +89 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/_more_option_pagination_/returns_the_more_key_in_the_raw_response.yml +48 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/_since_option/fails_when_passed_an_invalid_value.yml +37 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/_since_option/works.yml +43 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/is_successful.yml +43 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/results/is_an_enumerator_of_Course_models.yml +43 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/results/sucessfully_creates_the_Course_attributes.yml +43 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration/fails_when_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration/is_successful.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration/results/makes_settings_available_as_key/value_pairs.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration_setting/fails_when_course_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration_setting/fails_when_setting_id_is_invalid.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration_setting/is_successful.yml +65 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration_setting/results/returns_the_value_as_a_string.yml +65 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_post_course_configuration/fails_when_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_post_course_configuration/fails_when_settings_are_invalid.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_post_course_configuration/is_successful.yml +32 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_post_course_configuration/persists_the_settings.yml +131 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_put_course_configuration_setting/fails_when_course_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_put_course_configuration_setting/fails_when_setting_id_is_invalid.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_put_course_configuration_setting/is_successful.yml +65 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_put_course_configuration_setting/results/persists_the_changes.yml +98 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Import/_get_course_import/successful_imports/works.yml +147 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Import/_get_course_import/unsuccessful_imports/fails_to_import_given_an_invalid_url.yml +326 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Import/_post_course_import/successful_imports/works.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Import/_post_course_import/unsuccessful_imports/fails_to_import_a_previously_existing_course.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Ping/_get_ping/is_successful.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Ping/_get_ping/reports_the_api_is_up.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Ping/_get_ping/with_invalid_password/is_unsuccessful.yml +41 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Ping/_get_ping/with_invalid_password/returns_status_403.yml +41 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_delete_registration/is_failure_when_registration_does_not_exist.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_delete_registration/is_successful_when_registration_exists.yml +32 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_exists/is_false_when_registration_does_not_exist.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_exists/is_true_when_registration_exists.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_instances/includes_results_we_expect.yml +39 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_instances/is_successful.yml +39 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_instances/returns_an_array_of_registrations.yml +39 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_launch_link/fails_when_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_launch_link/is_successful.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_launch_link/results/returns_a_URL_string.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_progress/detail/does_not_return_activity_details_by_default.yml +39 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_progress/detail/returns_activity_details_if_requested.yml +41 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_progress/fails_when_registration_does_not_exist.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_progress/returns_a_registration_when_it_exists.yml +39 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/filtering_by_course_id/excludes_results.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/filtering_by_course_id/includes_results.yml +40 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/filtering_by_learner_id/excludes_results.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/filtering_by_learner_id/includes_results.yml +39 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/includes_results_we_expect.yml +40 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/is_successful.yml +40 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/returns_an_array_of_registrations.yml +40 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_post_registration/fails_if_course_id_is_invalid.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_post_registration/fails_if_registration_id_already_exists.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_post_registration/is_successful.yml +61 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration/fails_when_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration/is_successful.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration/results/makes_settings_available_as_key/value_pairs.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration_setting/fails_when_registration_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration_setting/fails_when_setting_id_is_invalid.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration_setting/is_successful.yml +65 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration_setting/results/returns_the_value_as_a_string.yml +65 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_post_registration_configuration/fails_when_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_post_registration_configuration/fails_when_settings_are_invalid.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_post_registration_configuration/is_successful.yml +32 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_post_registration_configuration/persists_the_settings.yml +131 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_put_registration_configuration_setting/fails_when_registration_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_put_registration_configuration_setting/fails_when_setting_id_is_invalid.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_put_registration_configuration_setting/is_successful.yml +65 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_put_registration_configuration_setting/results/persists_the_changes.yml +98 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_LaunchHistory/_get_registration_launch_history/fails_when_registration_does_not_exist.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_LaunchHistory/_get_registration_launch_history/is_successful.yml +54 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_LaunchHistory/_get_registration_launch_history/returns_an_array_of_registration_launch_histories.yml +54 -0
- data/spec/fixtures/zip/Non-working SCORM.zip +0 -0
- data/spec/fixtures/zip/RuntimeBasicCalls_SCORM20043rdEdition.zip +0 -0
- data/spec/scorm_engine/api/endpoints/about_spec.rb +59 -0
- data/spec/scorm_engine/api/endpoints/courses/configuration_spec.rb +143 -0
- data/spec/scorm_engine/api/endpoints/courses/import_spec.rb +92 -0
- data/spec/scorm_engine/api/endpoints/courses_spec.rb +155 -0
- data/spec/scorm_engine/api/endpoints/ping_spec.rb +27 -0
- data/spec/scorm_engine/api/endpoints/registrations/configuration_spec.rb +154 -0
- data/spec/scorm_engine/api/endpoints/registrations/launch_history_spec.rb +46 -0
- data/spec/scorm_engine/api/endpoints/registrations_spec.rb +201 -0
- data/spec/scorm_engine/configuration_spec.rb +29 -0
- data/spec/scorm_engine/models/course_configuration_spec.rb +16 -0
- data/spec/scorm_engine/models/course_import_spec.rb +86 -0
- data/spec/scorm_engine/models/course_spec.rb +92 -0
- data/spec/scorm_engine/models/learner_spec.rb +27 -0
- data/spec/scorm_engine/models/registration_activity_detail_spec.rb +101 -0
- data/spec/scorm_engine/models/registration_launch_history_spec.rb +86 -0
- data/spec/scorm_engine/models/registration_runtime_interaction_spec.rb +91 -0
- data/spec/scorm_engine/models/registration_spec.rb +82 -0
- data/spec/scorm_engine/utils_spec.rb +15 -0
- data/spec/scorm_engine/version_spec.rb +5 -0
- data/spec/scorm_engine_spec.rb +2 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/support/scorm_engine.rb +72 -0
- data/spec/support/scorm_engine_client.rb +6 -0
- data/spec/support/scorm_engine_configuration.rb +7 -0
- data/spec/support/vcr.rb +53 -0
- metadata +329 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
module ScormEngine
|
2
|
+
module Api
|
3
|
+
module Endpoints
|
4
|
+
module Registrations
|
5
|
+
module LaunchHistory
|
6
|
+
#
|
7
|
+
# Get launch history data associated with this registration
|
8
|
+
#
|
9
|
+
# @see http://rustici-docs.s3.amazonaws.com/engine/2017.1.x/api.html#tenant__registrations__registrationId__launchHistory_get
|
10
|
+
#
|
11
|
+
# @param [Hash] options
|
12
|
+
#
|
13
|
+
# @option options [String] :registration_id
|
14
|
+
# ID for the registration.
|
15
|
+
#
|
16
|
+
# @option options [String] :instance ()
|
17
|
+
# The instance of this registration to use. If not provided, the
|
18
|
+
# latest instance will be used.
|
19
|
+
#
|
20
|
+
# @option options [Boolean] :include_history_log (false)
|
21
|
+
# Whether to include the history log in the launch history. The
|
22
|
+
# history log is a blob of XML that shows all of the SCORM-related
|
23
|
+
# calls inside the course. Depending on the course itself, these logs
|
24
|
+
# can get very large if a lot of calls are being made.
|
25
|
+
#
|
26
|
+
# @return [Array<ScormEngine::Models::RegistrationLaunchHistory>]
|
27
|
+
#
|
28
|
+
def get_registration_launch_history(options = {})
|
29
|
+
require_options(options, :registration_id)
|
30
|
+
|
31
|
+
options = options.dup
|
32
|
+
registration_id = options.delete(:registration_id)
|
33
|
+
options[:includeHistoryLog] = !!options.delete(:include_history_log)
|
34
|
+
|
35
|
+
response = get("registrations/#{registration_id}/launchHistory", options)
|
36
|
+
|
37
|
+
result = response.success? && response.body["launchHistory"].map do |history|
|
38
|
+
ScormEngine::Models::RegistrationLaunchHistory.new_from_api(history)
|
39
|
+
end
|
40
|
+
|
41
|
+
Response.new(raw_response: response, result: result)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative "faraday/connection"
|
2
|
+
require_relative "faraday/request"
|
3
|
+
|
4
|
+
module ScormEngine
|
5
|
+
class Client
|
6
|
+
|
7
|
+
include Faraday::Connection
|
8
|
+
include Faraday::Request
|
9
|
+
include Api::Endpoints
|
10
|
+
|
11
|
+
attr_reader :tenant
|
12
|
+
|
13
|
+
def initialize(tenant:)
|
14
|
+
@tenant = tenant
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "logger"
|
2
|
+
|
3
|
+
module ScormEngine
|
4
|
+
def self.configuration
|
5
|
+
@configuration ||= Configuration.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.configure
|
9
|
+
yield(configuration)
|
10
|
+
end
|
11
|
+
|
12
|
+
class Configuration
|
13
|
+
# http://rustici-docs.s3.amazonaws.com/engine/2017.1.x/api.html
|
14
|
+
attr_accessor :host, :path_prefix
|
15
|
+
|
16
|
+
# http://rustici-docs.s3.amazonaws.com/engine/2017.1.x/Architecture-API.html#api-authentication
|
17
|
+
attr_accessor :username, :password
|
18
|
+
|
19
|
+
# defaults to /dev/null
|
20
|
+
# https://github.com/lostisland/faraday/blob/5f1687abbe9eb1c96284b31e303e80f1a22acd09/lib/faraday/response/logger.rb#L7
|
21
|
+
attr_accessor :logger, :log_options
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
reset
|
25
|
+
end
|
26
|
+
|
27
|
+
def reset
|
28
|
+
@host = ENV["SCORM_ENGINE_HOST"]
|
29
|
+
@path_prefix = "/ScormEngineInterface/api/v1/"
|
30
|
+
|
31
|
+
@username = ENV["SCORM_ENGINE_USERNAME"]
|
32
|
+
@password = ENV["SCORM_ENGINE_PASSWORD"]
|
33
|
+
|
34
|
+
@logger = ::Logger.new(ENV.fetch("SCORM_ENGINE_LOGFILE", "/dev/null"))
|
35
|
+
|
36
|
+
@log_options = begin
|
37
|
+
JSON.parse(ENV.fetch("SCORM_ENGINE_LOG_OPTIONS"))
|
38
|
+
rescue KeyError, JSON::ParserError
|
39
|
+
{ headers: false, bodies: false }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "faraday"
|
2
|
+
require "faraday_middleware"
|
3
|
+
|
4
|
+
module ScormEngine
|
5
|
+
module Faraday
|
6
|
+
module Connection
|
7
|
+
private
|
8
|
+
|
9
|
+
def connection
|
10
|
+
@connection ||= ::Faraday.new(url: base_uri.to_s) do |faraday|
|
11
|
+
faraday.headers["Content-Type"] = "application/json"
|
12
|
+
faraday.headers["User-Agent"] = "ScormEngine Ruby Gem #{ScormEngine::VERSION}"
|
13
|
+
|
14
|
+
faraday.basic_auth(ScormEngine.configuration.username, ScormEngine.configuration.password)
|
15
|
+
|
16
|
+
faraday.request :multipart
|
17
|
+
faraday.request :json
|
18
|
+
|
19
|
+
faraday.response :json, content_type: /\bjson$/
|
20
|
+
faraday.response :logger, ScormEngine.configuration.logger, ScormEngine.configuration.log_options
|
21
|
+
|
22
|
+
faraday.adapter ::Faraday.default_adapter
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def base_uri
|
27
|
+
uri = URI("")
|
28
|
+
uri.scheme = "https" # TODO: Make configurable
|
29
|
+
uri.host = ScormEngine.configuration.host
|
30
|
+
uri.path = ScormEngine.configuration.path_prefix
|
31
|
+
uri
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module ScormEngine
|
2
|
+
module Faraday
|
3
|
+
module Request
|
4
|
+
def get(path, options = {})
|
5
|
+
request(:get, path, options)
|
6
|
+
end
|
7
|
+
|
8
|
+
def post(path, options = {}, body = nil)
|
9
|
+
request(:post, path, options, body)
|
10
|
+
end
|
11
|
+
|
12
|
+
def put(path, options = {}, body = nil)
|
13
|
+
request(:put, path, options, body)
|
14
|
+
end
|
15
|
+
|
16
|
+
def delete(path, options = {})
|
17
|
+
request(:delete, path, options)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def request(method, path, options, body = nil)
|
23
|
+
# "more" pagination urls are fully qualified
|
24
|
+
path = "#{tenant}/#{path}" unless path =~ %r{\Ahttps?://}
|
25
|
+
|
26
|
+
options = coerce_options(options)
|
27
|
+
|
28
|
+
connection.send(method) do |request|
|
29
|
+
case method
|
30
|
+
when :get, :delete
|
31
|
+
request.url(path, options)
|
32
|
+
when :post, :put
|
33
|
+
if body.nil?
|
34
|
+
body = options.dup
|
35
|
+
options = {}
|
36
|
+
end
|
37
|
+
request.url(path, options)
|
38
|
+
request.body = body unless body.empty?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def coerce_options(options = {})
|
44
|
+
options.dup.each do |k, v|
|
45
|
+
case k
|
46
|
+
when :before, :since
|
47
|
+
options[k] = v.iso8601 if v.respond_to?(:iso8601)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
options
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require_relative "models/course"
|
2
|
+
require_relative "models/course_configuration"
|
3
|
+
require_relative "models/course_import"
|
4
|
+
require_relative "models/learner"
|
5
|
+
require_relative "models/registration"
|
6
|
+
require_relative "models/registration_activity_detail"
|
7
|
+
require_relative "models/registration_configuration"
|
8
|
+
require_relative "models/registration_launch_history"
|
9
|
+
require_relative "models/registration_runtime_interaction"
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "time"
|
2
|
+
|
3
|
+
module ScormEngine
|
4
|
+
module Models
|
5
|
+
class Course
|
6
|
+
attr_accessor :options
|
7
|
+
private :options
|
8
|
+
|
9
|
+
# TODO: Not sure we want this to be settable. Will depend on how we go
|
10
|
+
# about creating/updating records. For now it makes it easier to create
|
11
|
+
# instances from API options hash.
|
12
|
+
attr_accessor :id, :version, :title, :registration_count, :updated, :description,
|
13
|
+
:scaled_passing_score
|
14
|
+
|
15
|
+
def self.new_from_api(options = {})
|
16
|
+
this = new
|
17
|
+
|
18
|
+
this.options = options.dup
|
19
|
+
this.id = options["id"]
|
20
|
+
this.version = options["version"]
|
21
|
+
this.title = get_title_from_api(options)
|
22
|
+
this.registration_count = options["registrationCount"]
|
23
|
+
this.updated = Time.parse(options["updated"]) if options.key?("updated")
|
24
|
+
this.description = options.fetch("metadata", {})["description"]
|
25
|
+
this.scaled_passing_score = get_scaled_passing_score_from_api(options)
|
26
|
+
|
27
|
+
this
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# Extract and sanitize the title from the API options.
|
32
|
+
#
|
33
|
+
# Special consideration is given to two commonly found, but useless
|
34
|
+
# titles which if found will result in a blank title.
|
35
|
+
#
|
36
|
+
# @param [Hash] options
|
37
|
+
# The API options hash
|
38
|
+
#
|
39
|
+
# @return [String]
|
40
|
+
#
|
41
|
+
def self.get_title_from_api(options = {})
|
42
|
+
title = ScormEngine::Utils.sanitized_text(options["title"])
|
43
|
+
title = "" if ["Title", "Captivate E-Learning Course"].include?(title)
|
44
|
+
title
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Extract and normalize the scaled passing score from the API options.
|
49
|
+
#
|
50
|
+
# @param [Hash] options
|
51
|
+
# The API options hash
|
52
|
+
#
|
53
|
+
# @return [Integer]
|
54
|
+
# An integer between 0 and 100 or nil if undefined.
|
55
|
+
#
|
56
|
+
def self.get_scaled_passing_score_from_api(options = {})
|
57
|
+
first_child = options.fetch("rootActivity", {}).fetch("children", [{}]).first
|
58
|
+
score = first_child.is_a?(Hash) ? first_child["scaledPassingScore"] : nil
|
59
|
+
return if score.nil?
|
60
|
+
score = score.to_f
|
61
|
+
score *= 100 if score <= 1.0
|
62
|
+
score.to_i
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module ScormEngine
|
2
|
+
module Models
|
3
|
+
class CourseConfiguration
|
4
|
+
attr_accessor :options
|
5
|
+
private :options
|
6
|
+
|
7
|
+
# TODO: Not sure we want this to be settable. Will depend on how we go
|
8
|
+
# about creating/updating records. For now it makes it easier to create
|
9
|
+
# instances from API options hash.
|
10
|
+
attr_accessor :settings
|
11
|
+
|
12
|
+
def self.new_from_api(options = {})
|
13
|
+
this = new
|
14
|
+
|
15
|
+
this.options = options.dup
|
16
|
+
this.settings = get_settings_from_api(options)
|
17
|
+
this
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# Extract and normalize the settings from the API options.
|
22
|
+
#
|
23
|
+
# @param [Hash] options
|
24
|
+
# The API options hash
|
25
|
+
#
|
26
|
+
# @return [Hash]
|
27
|
+
# A hash of key/value pairs.
|
28
|
+
#
|
29
|
+
def self.get_settings_from_api(options = {})
|
30
|
+
options["configurationItems"].reduce({}) do |m, o|
|
31
|
+
m[o["id"]] = o["value"]
|
32
|
+
m
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module ScormEngine
|
2
|
+
module Models
|
3
|
+
class CourseImport
|
4
|
+
attr_accessor :options
|
5
|
+
private :options
|
6
|
+
|
7
|
+
# TODO: Not sure we want this to be settable. Will depend on how we go
|
8
|
+
# about creating/updating records. For now it makes it easier to create
|
9
|
+
# instances from API options hash.
|
10
|
+
attr_accessor :id, :status, :parser_warnings, :course
|
11
|
+
|
12
|
+
def self.new_from_api(options = {})
|
13
|
+
this = new
|
14
|
+
this.options = options.dup
|
15
|
+
|
16
|
+
if options.key?("importResult")
|
17
|
+
this.id = options["result"]
|
18
|
+
this.status = options.fetch("importResult", {})["status"]
|
19
|
+
this.parser_warnings = options.fetch("importResult", {})["parserWarnings"]
|
20
|
+
else
|
21
|
+
this.id = options["jobId"]
|
22
|
+
this.status = options["status"]
|
23
|
+
this.course = Course.new_from_api(options["course"]) if options.key?("course") # unavailable in error states
|
24
|
+
end
|
25
|
+
|
26
|
+
this
|
27
|
+
end
|
28
|
+
|
29
|
+
def running?
|
30
|
+
status == "RUNNING"
|
31
|
+
end
|
32
|
+
|
33
|
+
def error?
|
34
|
+
status == "ERROR"
|
35
|
+
end
|
36
|
+
|
37
|
+
def complete?
|
38
|
+
status == "COMPLETE"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ScormEngine
|
2
|
+
module Models
|
3
|
+
class Learner
|
4
|
+
attr_accessor :options
|
5
|
+
private :options
|
6
|
+
|
7
|
+
# TODO: Not sure we want this to be settable. Will depend on how we go
|
8
|
+
# about creating/updating records. For now it makes it easier to create
|
9
|
+
# instances from API options hash.
|
10
|
+
attr_accessor :id, :first_name, :last_name
|
11
|
+
|
12
|
+
def self.new_from_api(options = {})
|
13
|
+
this = new
|
14
|
+
|
15
|
+
this.options = options.dup
|
16
|
+
this.id = options["id"]
|
17
|
+
this.first_name = options["firstName"]
|
18
|
+
this.last_name = options["lastName"]
|
19
|
+
|
20
|
+
this
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
#
|
2
|
+
# TODO: Incorporate all the activity props from:
|
3
|
+
# http://rustici-docs.s3.amazonaws.com/engine/2017.1.x/api.html#tenant__registrations__registrationId__progress_get
|
4
|
+
# http://rustici-docs.s3.amazonaws.com/engine/2017.1.x/api.html#tenant__registrations__registrationId__progress_detail_get
|
5
|
+
#
|
6
|
+
# TODO: Confirmed they are the only values. Integrate them into the model.
|
7
|
+
# registrationCompletion: ["COMPLETED", "INCOMPLETE", "UNKNOWN"]
|
8
|
+
# registrationSuccess: ["Unknown", "Passed", "Failed"]
|
9
|
+
#
|
10
|
+
module ScormEngine
|
11
|
+
module Models
|
12
|
+
class Registration
|
13
|
+
attr_accessor :options
|
14
|
+
private :options
|
15
|
+
|
16
|
+
# TODO: Not sure we want this to be settable. Will depend on how we go
|
17
|
+
# about creating/updating records. For now it makes it easier to create
|
18
|
+
# instances from API options hash.
|
19
|
+
attr_accessor :id, :instance, :updated, :registration_completion, :registration_success,
|
20
|
+
:total_seconds_tracked, :score, :course, :learner, :activity_details,
|
21
|
+
:first_access_date, :last_access_date, :completed_date, :created_date,
|
22
|
+
:registration_completion_amount
|
23
|
+
|
24
|
+
def self.new_from_api(options = {})
|
25
|
+
this = new
|
26
|
+
|
27
|
+
this.options = options.dup
|
28
|
+
this.id = options["id"]
|
29
|
+
this.instance = options["instance"]
|
30
|
+
this.updated = Time.parse(options["updated"]) if options.key?("updated")
|
31
|
+
this.registration_completion = options["registrationCompletion"]
|
32
|
+
this.registration_success = options["registrationSuccess"]
|
33
|
+
this.total_seconds_tracked = options["totalSecondsTracked"]
|
34
|
+
this.first_access_date = Time.parse(options["firstAccessDate"]) if options.key?("firstAccessDate")
|
35
|
+
this.last_access_date = Time.parse(options["lastAccessDate"]) if options.key?("lastAccessDate")
|
36
|
+
this.created_date = Time.parse(options["createdDate"]) if options.key?("createdDate")
|
37
|
+
this.updated = Time.parse(options["updated"]) if options.key?("updated")
|
38
|
+
this.registration_completion_amount = options["registrationCompletionAmount"].to_f # Sometimes it returns "NaN"
|
39
|
+
|
40
|
+
this.score = get_score_from_api(options)
|
41
|
+
this.completed_date = get_completed_at_from_api(options)
|
42
|
+
|
43
|
+
this.activity_details = RegistrationActivityDetail.new_from_api(options["activityDetails"]) if options.key?("activityDetails")
|
44
|
+
this.course = Course.new_from_api(options["course"]) if options.key?("course")
|
45
|
+
this.learner = Learner.new_from_api(options["learner"]) if options.key?("learner")
|
46
|
+
|
47
|
+
this
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# Extract and normalize the scaled passing score from the API options.
|
52
|
+
#
|
53
|
+
# @param [Hash] options
|
54
|
+
# The API options hash
|
55
|
+
#
|
56
|
+
# @return [Float]
|
57
|
+
# A float between 0 and 100 or nil if undefined.
|
58
|
+
#
|
59
|
+
def self.get_score_from_api(options = {})
|
60
|
+
score = options.fetch("score", {})["scaled"]
|
61
|
+
return if score.nil?
|
62
|
+
score.to_f
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
# Extract and normalize the completed date from the API options.
|
67
|
+
#
|
68
|
+
# @param [Hash] options
|
69
|
+
# The API options hash
|
70
|
+
#
|
71
|
+
# @return [Time]
|
72
|
+
# a date/time or nil if undefined.
|
73
|
+
#
|
74
|
+
def self.get_completed_at_from_api(options = {})
|
75
|
+
completed_date = options["completedDate"]
|
76
|
+
completed_date ||= options.fetch("score", {})["completedDate"]
|
77
|
+
return if completed_date.nil?
|
78
|
+
Time.parse(completed_date)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|