scorm_engine 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|