moodle2cc 0.2.5 → 0.2.6

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 (89) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog +7 -0
  3. data/lib/moodle2cc.rb +3 -0
  4. data/lib/moodle2cc/canvas_cc/calculated_question_writer.rb +11 -0
  5. data/lib/moodle2cc/canvas_cc/matching_question_writer.rb +6 -4
  6. data/lib/moodle2cc/canvas_cc/models/assessment.rb +1 -1
  7. data/lib/moodle2cc/canvas_cc/models/calculated_question.rb +13 -1
  8. data/lib/moodle2cc/canvas_cc/models/course.rb +2 -2
  9. data/lib/moodle2cc/canvas_cc/models/multiple_dropdowns_question.rb +7 -0
  10. data/lib/moodle2cc/canvas_cc/models/page.rb +7 -1
  11. data/lib/moodle2cc/canvas_cc/models/question.rb +1 -0
  12. data/lib/moodle2cc/canvas_cc/multiple_answers_question_writer.rb +7 -6
  13. data/lib/moodle2cc/canvas_cc/multiple_dropdowns_question_writer.rb +30 -0
  14. data/lib/moodle2cc/canvas_cc/question_writer.rb +2 -1
  15. data/lib/moodle2cc/moodle2/extractor.rb +7 -0
  16. data/lib/moodle2cc/moodle2/models.rb +1 -1
  17. data/lib/moodle2cc/moodle2/models/course.rb +3 -2
  18. data/lib/moodle2cc/moodle2/models/label.rb +5 -5
  19. data/lib/moodle2cc/moodle2/models/questionnaire.rb +1 -1
  20. data/lib/moodle2cc/moodle2/models/quizzes.rb +1 -0
  21. data/lib/moodle2cc/moodle2/models/quizzes/calculated_question.rb +2 -1
  22. data/lib/moodle2cc/moodle2/models/quizzes/multichoice_question.rb +6 -0
  23. data/lib/moodle2cc/moodle2/models/quizzes/question.rb +1 -1
  24. data/lib/moodle2cc/moodle2/models/wiki.rb +10 -0
  25. data/lib/moodle2cc/moodle2/parsers.rb +1 -0
  26. data/lib/moodle2cc/moodle2/parsers/course_parser.rb +5 -5
  27. data/lib/moodle2cc/moodle2/parsers/parser_helper.rb +7 -2
  28. data/lib/moodle2cc/moodle2/parsers/question_parsers/calculated_parser.rb +11 -1
  29. data/lib/moodle2cc/moodle2/parsers/question_parsers/match_parser.rb +2 -1
  30. data/lib/moodle2cc/moodle2/parsers/question_parsers/multichoice_parser.rb +2 -0
  31. data/lib/moodle2cc/moodle2/parsers/questionnaire_parser.rb +5 -0
  32. data/lib/moodle2cc/moodle2/parsers/quiz_parser.rb +5 -0
  33. data/lib/moodle2cc/moodle2/parsers/section_parser.rb +5 -1
  34. data/lib/moodle2cc/moodle2/parsers/wiki_parser.rb +47 -0
  35. data/lib/moodle2cc/moodle2converter/assessment_converter.rb +6 -4
  36. data/lib/moodle2cc/moodle2converter/assignment_converter.rb +1 -1
  37. data/lib/moodle2cc/moodle2converter/book_converter.rb +4 -4
  38. data/lib/moodle2cc/moodle2converter/converter_helper.rb +14 -0
  39. data/lib/moodle2cc/moodle2converter/discussion_converter.rb +1 -1
  40. data/lib/moodle2cc/moodle2converter/feedback_converter.rb +3 -3
  41. data/lib/moodle2cc/moodle2converter/html_converter.rb +16 -1
  42. data/lib/moodle2cc/moodle2converter/label_converter.rb +2 -2
  43. data/lib/moodle2cc/moodle2converter/migrator.rb +70 -2
  44. data/lib/moodle2cc/moodle2converter/question_bank_converter.rb +1 -1
  45. data/lib/moodle2cc/moodle2converter/question_converters.rb +1 -0
  46. data/lib/moodle2cc/moodle2converter/question_converters/calculated_converter.rb +1 -0
  47. data/lib/moodle2cc/moodle2converter/question_converters/matching_converter.rb +3 -0
  48. data/lib/moodle2cc/moodle2converter/question_converters/multichoice_converter.rb +15 -0
  49. data/lib/moodle2cc/moodle2converter/question_converters/multiple_blanks_converter.rb +1 -1
  50. data/lib/moodle2cc/moodle2converter/question_converters/question_converter.rb +3 -5
  51. data/lib/moodle2cc/moodle2converter/questionnaire_converter.rb +44 -8
  52. data/lib/moodle2cc/moodle2converter/section_converter.rb +3 -3
  53. data/lib/moodle2cc/moodle2converter/wiki_converter.rb +37 -0
  54. data/lib/moodle2cc/version.rb +1 -1
  55. data/spec/moodle2cc/canvas_cc/calculated_question_writer_spec.rb +7 -0
  56. data/spec/moodle2cc/canvas_cc/matching_question_writer_spec.rb +2 -2
  57. data/spec/moodle2cc/canvas_cc/models/assessment_spec.rb +1 -1
  58. data/spec/moodle2cc/canvas_cc/models/calculated_question_spec.rb +25 -0
  59. data/spec/moodle2cc/canvas_cc/models/page_spec.rb +6 -0
  60. data/spec/moodle2cc/canvas_cc/multiple_answers_question_writer_spec.rb +4 -1
  61. data/spec/moodle2cc/canvas_cc/multiple_blanks_question_writer_spec.rb +1 -1
  62. data/spec/moodle2cc/canvas_cc/multiple_dropdowns_question_writer_spec.rb +46 -0
  63. data/spec/moodle2cc/moodle2/extractor_spec.rb +8 -0
  64. data/spec/moodle2cc/moodle2/models/label_spec.rb +4 -4
  65. data/spec/moodle2cc/moodle2/parsers/parser_helper_spec.rb +10 -0
  66. data/spec/moodle2cc/moodle2/parsers/question_parsers/calculated_parser_spec.rb +17 -0
  67. data/spec/moodle2cc/moodle2/parsers/questionnaire_parser_spec.rb +4 -0
  68. data/spec/moodle2cc/moodle2/parsers/quiz_parser_spec.rb +1 -1
  69. data/spec/moodle2cc/moodle2/parsers/wiki_parser_spec.rb +23 -0
  70. data/spec/moodle2cc/moodle2converter/assessment_converter_spec.rb +12 -7
  71. data/spec/moodle2cc/moodle2converter/converter_helper_spec.rb +5 -0
  72. data/spec/moodle2cc/moodle2converter/html_converter_spec.rb +7 -2
  73. data/spec/moodle2cc/moodle2converter/label_converter_spec.rb +17 -0
  74. data/spec/moodle2cc/moodle2converter/migrator_spec.rb +83 -2
  75. data/spec/moodle2cc/moodle2converter/question_converters/calculated_converter_spec.rb +2 -0
  76. data/spec/moodle2cc/moodle2converter/question_converters/matching_converter_spec.rb +2 -3
  77. data/spec/moodle2cc/moodle2converter/question_converters/multichoice_converter_spec.rb +26 -0
  78. data/spec/moodle2cc/moodle2converter/question_converters/question_converter_spec.rb +0 -3
  79. data/spec/moodle2cc/moodle2converter/wiki_converter_spec.rb +36 -0
  80. data/test/fixtures/moodle2/backup/activities/quiz_5/quiz.xml +1 -1
  81. data/test/fixtures/moodle2/backup/activities/wiki_58541/calendar.xml +3 -0
  82. data/test/fixtures/moodle2/backup/activities/wiki_58541/completion.xml +3 -0
  83. data/test/fixtures/moodle2/backup/activities/wiki_58541/grades.xml +7 -0
  84. data/test/fixtures/moodle2/backup/activities/wiki_58541/inforef.xml +47 -0
  85. data/test/fixtures/moodle2/backup/activities/wiki_58541/module.xml +28 -0
  86. data/test/fixtures/moodle2/backup/activities/wiki_58541/roles.xml +7 -0
  87. data/test/fixtures/moodle2/backup/activities/wiki_58541/wiki.xml +70 -0
  88. data/test/fixtures/moodle2/backup/moodle_backup.xml +7 -0
  89. metadata +33 -2
@@ -22,10 +22,20 @@ module Moodle2CC::Moodle2
22
22
  end
23
23
 
24
24
  q_node.search('dataset_definitions/dataset_definition').each do |ds_node|
25
+ var_name = parse_text(ds_node, 'name')
25
26
  question.dataset_definitions << {
26
- :name => parse_text(ds_node, 'name'),
27
+ :name => var_name,
27
28
  :options => parse_text(ds_node, 'options')
28
29
  }
30
+ ds_node.search('dataset_items/dataset_item').each do |ds_item_node|
31
+ ident = parse_text(ds_item_node, 'number')
32
+ var_set = question.var_sets.detect{|vs| vs[:ident] == ident}
33
+ unless var_set
34
+ var_set = {:ident => ident, :vars => {}}
35
+ question.var_sets << var_set
36
+ end
37
+ var_set[:vars][var_name] = parse_text(ds_item_node, 'value')
38
+ end
29
39
  end
30
40
 
31
41
  q_node.search('calculated_records/calculated_record').each do |cr_node|
@@ -2,9 +2,10 @@ module Moodle2CC::Moodle2
2
2
  class Parsers::QuestionParsers::MatchParser < Parsers::QuestionParsers::QuestionParser
3
3
  include Parsers::ParserHelper
4
4
  register_parser_type('match')
5
+ register_parser_type('ddmatch')
5
6
 
6
7
  def parse_question(node)
7
- question = super
8
+ question = super(node, 'match')
8
9
 
9
10
  q_node = node.at_xpath("plugin_qtype_#{question.qtype}_question")
10
11
 
@@ -9,6 +9,8 @@ module Moodle2CC::Moodle2
9
9
  answer_parser = Parsers::AnswerParser.new
10
10
  question.answers += node.search('answers/answer').map { |n| answer_parser.parse(n) }
11
11
 
12
+ question.single = parse_boolean(node, 'plugin_qtype_multichoice_question/multichoice/single')
13
+
12
14
  question
13
15
  end
14
16
 
@@ -39,6 +39,11 @@ module Moodle2CC::Moodle2::Parsers
39
39
  question.type_id = parse_text(node, 'type_id')
40
40
  question.position = parse_text(node, 'position')
41
41
  question.content = parse_text(node, 'content')
42
+
43
+ question.length = parse_text(node, 'length') # used for rating scale
44
+ question.precise = parse_text(node, 'precise') # used for rating scale type
45
+
46
+ question.deleted = parse_boolean(node, 'deleted')
42
47
  node.search('quest_choices/quest_choice').each do |choice_node|
43
48
  question.choices << {
44
49
  :id => choice_node.attributes['id'].value,
@@ -69,6 +69,11 @@ module Moodle2CC::Moodle2::Parsers
69
69
  }
70
70
  end
71
71
 
72
+ question_order = parse_text(xml, '/activity/quiz/questions').to_s.split(',')
73
+ unless question_order.empty?
74
+ quiz.question_instances.sort_by!{|qi| question_order.index(qi[:question])}
75
+ end
76
+
72
77
  xml.search('/activity/quiz/feedbacks/feedback').each do |node|
73
78
  quiz.feedbacks << {
74
79
  :text => parse_text(node, 'feedbacktext'),
@@ -25,7 +25,11 @@ module Moodle2CC::Moodle2::Parsers
25
25
  section.summary = parse_text(section_xml, '/section/summary')
26
26
  section.summary_format = parse_text(section_xml, 'section/summaryformat')
27
27
  section.sequence = parse_text(section_xml, 'section/sequence')
28
- section.sequence = section.sequence.split(',') if section.sequence
28
+ if section.sequence
29
+ section.sequence = section.sequence.split(',')
30
+ else
31
+ section.sequence = []
32
+ end
29
33
  section.visible = parse_text(section_xml, 'section/visible') == '1' ? true : false
30
34
  section.available_from = parse_text(section_xml, 'section/availablefrom')
31
35
  section.available_until = parse_text(section_xml, 'section/availableuntil')
@@ -0,0 +1,47 @@
1
+ module Moodle2CC::Moodle2::Parsers
2
+ class WikiParser
3
+ include ParserHelper
4
+
5
+ WIKI_XML = 'wiki.xml'
6
+ WIKI_MODULE_NAME = 'wiki'
7
+
8
+ def initialize(backup_dir)
9
+ @backup_dir = backup_dir
10
+ end
11
+
12
+ def parse
13
+ activity_dirs = activity_directories(@backup_dir, WIKI_MODULE_NAME)
14
+ activity_dirs.map { |dir| parse_wiki(dir) }
15
+ end
16
+
17
+ private
18
+
19
+ def parse_wiki(dir)
20
+ wiki = Moodle2CC::Moodle2::Models::Wiki.new
21
+ activity_dir = File.join(@backup_dir, dir)
22
+ File.open(File.join(activity_dir, WIKI_XML)) do |f|
23
+ wiki_xml = Nokogiri::XML(f)
24
+ wiki.id = wiki_xml.at_xpath('/activity/wiki/@id').value
25
+ wiki.module_id = wiki_xml.at_xpath('/activity/@moduleid').value
26
+ wiki.name = parse_text(wiki_xml, '/activity/wiki/name')
27
+ wiki.intro = parse_text(wiki_xml, '/activity/wiki/intro')
28
+ wiki.intro_format = parse_text(wiki_xml, '/activity/wiki/introformat')
29
+
30
+ wiki.first_page_title = parse_text(wiki_xml, '/activity/wiki/firstpagetitle')
31
+
32
+ wiki_xml.search('/activity/wiki/subwikis/subwiki/pages/page').each do |node|
33
+ wiki.pages << {
34
+ :id => node.attributes['id'].value,
35
+ :title => parse_text(node, 'title'),
36
+ :content => parse_text(node, 'cachedcontent')
37
+ }
38
+ end
39
+ end
40
+ parse_module(activity_dir, wiki)
41
+
42
+ wiki
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -11,7 +11,7 @@ module Moodle2CC::Moodle2Converter
11
11
  def convert_quiz(moodle_quiz)
12
12
  canvas_assessment = Moodle2CC::CanvasCC::Models::Assessment.new
13
13
  canvas_assessment.identifier = generate_unique_identifier_for(moodle_quiz.id, ASSESSMENT_SUFFIX)
14
- canvas_assessment.title = moodle_quiz.name
14
+ canvas_assessment.title = truncate_text(moodle_quiz.name)
15
15
  canvas_assessment.description = moodle_quiz.intro
16
16
  canvas_assessment.workflow_state = workflow_state(moodle_quiz.visible)
17
17
 
@@ -25,7 +25,9 @@ module Moodle2CC::Moodle2Converter
25
25
  canvas_assessment.access_code = moodle_quiz.password
26
26
  canvas_assessment.ip_filter = moodle_quiz.subnet
27
27
  canvas_assessment.shuffle_answers = moodle_quiz.shuffle_answers
28
- canvas_assessment.time_limit = Integer(moodle_quiz.time_limit) if moodle_quiz.time_limit
28
+ if moodle_quiz.time_limit && moodle_quiz.time_limit.to_i > 0
29
+ canvas_assessment.time_limit = (moodle_quiz.time_limit.to_f / 60).ceil
30
+ end
29
31
  canvas_assessment.quiz_type = 'practice_quiz'
30
32
 
31
33
  canvas_assessment.question_references = moodle_quiz.question_instances
@@ -36,7 +38,7 @@ module Moodle2CC::Moodle2Converter
36
38
  def convert_choice(moodle_choice)
37
39
  canvas_assessment = Moodle2CC::CanvasCC::Models::Assessment.new
38
40
  canvas_assessment.identifier = generate_unique_identifier_for(moodle_choice.id, CHOICE_ASSESSMENT_SUFFIX)
39
- canvas_assessment.title = moodle_choice.name
41
+ canvas_assessment.title = truncate_text(moodle_choice.name)
40
42
  canvas_assessment.description = ''
41
43
  canvas_assessment.workflow_state = workflow_state(moodle_choice.visible)
42
44
 
@@ -49,7 +51,7 @@ module Moodle2CC::Moodle2Converter
49
51
 
50
52
  question = Moodle2CC::CanvasCC::Models::Question.create('multiple_choice_question')
51
53
  question.identifier = generate_unique_identifier_for(moodle_choice.id, '_choice_question')
52
- question.title = moodle_choice.name
54
+ question.title = truncate_text(moodle_choice.name)
53
55
  question.material = moodle_choice.intro
54
56
  question.answers = []
55
57
  moodle_choice.options.each_with_index do |option, num|
@@ -5,7 +5,7 @@ module Moodle2CC::Moodle2Converter
5
5
  def convert(moodle_assignment)
6
6
  canvas_assignment = Moodle2CC::CanvasCC::Models::Assignment.new
7
7
  canvas_assignment.identifier = generate_unique_identifier_for(moodle_assignment.id, ASSIGNMENT_SUFFIX)
8
- canvas_assignment.title = moodle_assignment.name
8
+ canvas_assignment.title = truncate_text(moodle_assignment.name)
9
9
  canvas_assignment.body = moodle_assignment.intro
10
10
  canvas_assignment.due_at = Time.at(Integer(moodle_assignment.due_date)) if moodle_assignment.due_date
11
11
  canvas_assignment.lock_at = Time.at(Integer(moodle_assignment.cut_off_date)) if moodle_assignment.cut_off_date
@@ -24,7 +24,7 @@ module Moodle2CC
24
24
  page.identifier = generate_unique_identifier_for_book_intro(moodle_book)
25
25
  page.body = moodle_book.intro
26
26
  if pages.any?{|p| page.title == p.title}
27
- page.title = "#{page.title} (Introduction)"
27
+ page.title = "#{truncate_text(page.title, MAX_TITLE_LENGTH - 20)} (Introduction)"
28
28
  end
29
29
  page.workflow_state = workflow_state(moodle_book.visible)
30
30
  pages.unshift(page)
@@ -46,7 +46,7 @@ module Moodle2CC
46
46
  def create_title(moodle_book)
47
47
  module_item = create_module_item_with_defaults()
48
48
  module_item.content_type = Moodle2CC::CanvasCC::Models::ModuleItem::CONTENT_TYPE_CONTEXT_MODULE_SUB_HEADER
49
- module_item.title = moodle_book.name
49
+ module_item.title = truncate_text(moodle_book.name)
50
50
  module_item.indent = "0"
51
51
  module_item.identifier = generate_unique_identifier()
52
52
  module_item.workflow_state = workflow_state(moodle_book.visible)
@@ -67,7 +67,7 @@ module Moodle2CC
67
67
 
68
68
  def create_chapter(moodle_chapter)
69
69
  module_item = create_module_item_with_defaults()
70
- module_item.title = moodle_chapter.title
70
+ module_item.title = truncate_text(moodle_chapter.title)
71
71
  module_item.indent = moodle_chapter.subchapter ? "2" : "1"
72
72
  module_item.identifier = generate_unique_identifier()
73
73
  module_item.identifierref = generate_unique_identifier_for_activity(moodle_chapter)
@@ -88,7 +88,7 @@ module Moodle2CC
88
88
  page = CanvasCC::Models::Page.new
89
89
  page.type = CanvasCC::Models::Resource::WEB_CONTENT_TYPE
90
90
  page.href = generate_unique_resource_path(CanvasCC::Models::Page::BOOK_PATH, title)
91
- page.title = title
91
+ page.title = truncate_text(title)
92
92
  page.workflow_state = CanvasCC::Models::WorkflowState::ACTIVE
93
93
  page.editing_roles = CanvasCC::Models::Page::EDITING_ROLE_TEACHER
94
94
  page
@@ -20,6 +20,7 @@ module Moodle2CC
20
20
 
21
21
  ACTIVITY_LOOKUP = {
22
22
  Moodle2::Models::Page => {suffix: PAGE_SUFFIX, content_type: CanvasCC::Models::ModuleItem::CONTENT_TYPE_WIKI_PAGE},
23
+ Moodle2::Models::Wiki => {suffix: PAGE_SUFFIX, content_type: CanvasCC::Models::ModuleItem::CONTENT_TYPE_WIKI_PAGE},
23
24
  Moodle2::Models::Assignment => {suffix: ASSIGNMENT_SUFFIX, content_type: CanvasCC::Models::ModuleItem::CONTENT_TYPE_ASSIGNMENT},
24
25
  Moodle2::Models::Folder => {suffix: FOLDER_SUFFIX, content_type: CanvasCC::Models::ModuleItem::CONTENT_TYPE_WIKI_PAGE},
25
26
  Moodle2::Models::Forum => {suffix: DISCUSSION_SUFFIX, content_type: CanvasCC::Models::ModuleItem::CONTENT_TYPE_DISCUSSION_TOPIC},
@@ -35,6 +36,8 @@ module Moodle2CC
35
36
  Moodle2::Models::Resource => {suffix: nil, content_type: CanvasCC::Models::ModuleItem::CONTENT_TYPE_ATTACHMENT}
36
37
  }
37
38
 
39
+ MAX_TITLE_LENGTH = 250
40
+
38
41
  def generate_unique_resource_path(base_path, readable_name, file_extension = 'html')
39
42
  file_name_suffix = readable_name ? Moodle2CC::CanvasCC::Models::Page.convert_name_to_url(readable_name) : ''
40
43
  ext = file_extension ? ".#{file_extension}" : ''
@@ -69,6 +72,17 @@ module Moodle2CC
69
72
  moodle_visibility ? CanvasCC::Models::WorkflowState::ACTIVE : CanvasCC::Models::WorkflowState::UNPUBLISHED
70
73
  end
71
74
 
75
+ def truncate_text(text, max_length = nil, ellipsis = '...')
76
+ max_length ||= MAX_TITLE_LENGTH
77
+ return text if !text || text.length <= max_length
78
+
79
+ actual_length = max_length - ellipsis.length
80
+
81
+ # First truncate the text down to the bytes max, then lop off any invalid
82
+ # unicode characters at the end.
83
+ truncated = text[0,actual_length][/.{0,#{actual_length}}/mu]
84
+ truncated + ellipsis
85
+ end
72
86
 
73
87
  end
74
88
  end
@@ -6,7 +6,7 @@ module Moodle2CC::Moodle2Converter
6
6
  def convert(forum)
7
7
  discussion = Moodle2CC::CanvasCC::Models::Discussion.new
8
8
  discussion.identifier = generate_unique_identifier_for(forum.id, DISCUSSION_SUFFIX)
9
- discussion.title = forum.name
9
+ discussion.title = truncate_text(forum.name)
10
10
  discussion.text = forum.intro
11
11
  discussion.discussion_type = 'threaded'
12
12
  discussion.workflow_state = workflow_state(forum.visible)
@@ -5,7 +5,7 @@ module Moodle2CC::Moodle2Converter
5
5
  def convert_feedback(moodle_feedback)
6
6
  canvas_assessment = Moodle2CC::CanvasCC::Models::Assessment.new
7
7
  canvas_assessment.identifier = generate_unique_identifier_for(moodle_feedback.id, FEEDBACK_ASSESSMENT_SUFFIX)
8
- canvas_assessment.title = moodle_feedback.name
8
+ canvas_assessment.title = truncate_text(moodle_feedback.name)
9
9
  canvas_assessment.description = moodle_feedback.intro
10
10
  canvas_assessment.workflow_state = workflow_state(moodle_feedback.visible)
11
11
 
@@ -40,10 +40,10 @@ module Moodle2CC::Moodle2Converter
40
40
  canvas_question = Moodle2CC::CanvasCC::Models::Question.create(canvas_type)
41
41
  canvas_question.identifier = generate_unique_identifier_for(moodle_question.id, "_feedback_question")
42
42
  if moodle_question.type == 'label'
43
- canvas_question.title = moodle_question.name
43
+ canvas_question.title = truncate_text(moodle_question.name)
44
44
  canvas_question.material = moodle_question.presentation
45
45
  else
46
- canvas_question.title = moodle_question.label
46
+ canvas_question.title = truncate_text(moodle_question.label)
47
47
  canvas_question.material = moodle_question.name
48
48
  end
49
49
 
@@ -17,7 +17,9 @@ module Moodle2CC::Moodle2Converter
17
17
  end
18
18
 
19
19
  def convert(content)
20
- update_links(content.gsub('id="main"', ''))
20
+ content = update_links(content.gsub('id="main"', ''))
21
+ content = convert_equations(content)
22
+ content
21
23
  end
22
24
 
23
25
  private
@@ -92,5 +94,18 @@ module Moodle2CC::Moodle2Converter
92
94
  end
93
95
  end
94
96
 
97
+ def convert_equations(content)
98
+ # turn moodle equations ( e.g. $$3 * x$$ ) into canvas equations
99
+ content.gsub(/\$\$([^\$]*)\$\$/) do |match|
100
+ latex = $1.to_s.gsub("\"", "\\\"")
101
+ if latex.length > 0
102
+ url = "/equation_images/#{CGI.escape(CGI.escape(latex).gsub("+", "%20"))}"
103
+
104
+ "<img class=\"equation_image\" title=\"#{latex}\" alt=\"#{latex}\" src=\"#{url}\">"
105
+ else
106
+ ""
107
+ end
108
+ end
109
+ end
95
110
  end
96
111
  end
@@ -7,7 +7,7 @@ module Moodle2CC
7
7
  module_item = CanvasCC::Models::ModuleItem.new
8
8
  module_item.identifier = generate_unique_identifier
9
9
  module_item.workflow_state = workflow_state(moodle_label.visible)
10
- module_item.title = moodle_label.converted_title
10
+ module_item.title = truncate_text(moodle_label.converted_title)
11
11
  module_item.indent = '0'
12
12
 
13
13
  if moodle_label.convert_to_page?
@@ -25,7 +25,7 @@ module Moodle2CC
25
25
  if moodle_label.convert_to_page?
26
26
  canvas_page = CanvasCC::Models::Page.new
27
27
  canvas_page.identifier = generate_unique_identifier_for_activity(moodle_label)
28
- canvas_page.title = moodle_label.converted_title
28
+ canvas_page.title = truncate_text(moodle_label.converted_title)
29
29
  canvas_page.workflow_state = workflow_state(moodle_label.visible)
30
30
  canvas_page.editing_roles = CanvasCC::Models::Page::EDITING_ROLE_TEACHER
31
31
  canvas_page.body = moodle_label.intro
@@ -1,6 +1,8 @@
1
1
  module Moodle2CC::Moodle2Converter
2
2
  class Migrator
3
3
 
4
+ include ConverterHelper
5
+
4
6
  def initialize(source_file, output_dir)
5
7
  @extractor = Moodle2CC::Moodle2::Extractor.new(source_file)
6
8
  @output_dir = output_dir
@@ -11,6 +13,7 @@ module Moodle2CC::Moodle2Converter
11
13
  cc_course = convert_course(moodle_course)
12
14
  cc_course.files += convert_files(moodle_course.files)
13
15
  cc_course.pages += convert_pages(moodle_course.pages)
16
+ cc_course.pages += convert_wikis(moodle_course.wikis)
14
17
  cc_course.discussions += convert_discussions(moodle_course.forums)
15
18
  cc_course.assignments += convert_assignments(moodle_course.assignments)
16
19
 
@@ -19,7 +22,6 @@ module Moodle2CC::Moodle2Converter
19
22
  cc_course.assessments += convert_assessments(moodle_course.quizzes, moodle_course.choices,
20
23
  moodle_course.feedbacks, moodle_course.questionnaires)
21
24
  cc_course.question_banks += convert_question_banks(moodle_course.question_categories)
22
- cc_course.resolve_question_references
23
25
 
24
26
  cc_course.pages += convert_sections_to_pages(moodle_course.sections)
25
27
  cc_course.pages += convert_folders(moodle_course)
@@ -29,8 +31,10 @@ module Moodle2CC::Moodle2Converter
29
31
 
30
32
  cc_course.canvas_modules += convert_sections(moodle_course.sections)
31
33
 
34
+ resolve_duplicate_page_titles!(cc_course)
32
35
  convert_html!(cc_course, moodle_course)
33
36
 
37
+ cc_course.resolve_question_references!
34
38
  @path = Moodle2CC::CanvasCC::CartridgeCreator.new(cc_course).create(@output_dir)
35
39
  end
36
40
  @path
@@ -61,6 +65,11 @@ module Moodle2CC::Moodle2Converter
61
65
  pages.map { |page| page_converter.convert(page) }
62
66
  end
63
67
 
68
+ def convert_wikis(wikis)
69
+ wiki_converter = Moodle2CC::Moodle2Converter::WikiConverter.new
70
+ wikis.map { |wiki| wiki_converter.convert(wiki) }.flatten
71
+ end
72
+
64
73
  def convert_discussions(discussions)
65
74
  discussion_converter = Moodle2CC::Moodle2Converter::DiscussionConverter.new
66
75
  discussions.map { |discussion| discussion_converter.convert(discussion) }
@@ -118,8 +127,67 @@ module Moodle2CC::Moodle2Converter
118
127
  cc_course.pages.each {|page| page.body = html_converter.convert(page.body)}
119
128
  cc_course.discussions.each {|discussion| discussion.text = html_converter.convert(discussion.text)}
120
129
  cc_course.assignments.each {|assignment| assignment.body = html_converter.convert(assignment.body)}
121
- cc_course.assessments.each {|assessment| assessment.description = html_converter.convert(assessment.description)}
130
+
131
+ cc_course.assessments.each do |assessment|
132
+ assessment.description = html_converter.convert(assessment.description)
133
+
134
+ next unless assessment.items
135
+ assessment.items.each do |item|
136
+ if item.is_a?(Moodle2CC::CanvasCC::Models::QuestionGroup)
137
+ item.questions.each do |question|
138
+ convert_question_html!(question, html_converter)
139
+ end
140
+ elsif item.is_a?(Moodle2CC::CanvasCC::Models::Question)
141
+ convert_question_html!(item, html_converter)
142
+ end
143
+ end
144
+ end
145
+
146
+ cc_course.question_banks.each do |question_bank|
147
+ question_bank.questions.each do |question|
148
+ convert_question_html!(question, html_converter)
149
+ end
150
+ end
151
+ end
152
+
153
+ def convert_question_html!(question, html_converter)
154
+ question.material = html_converter.convert(question.material)
155
+ question.general_feedback = html_converter.convert(question.general_feedback) if question.general_feedback
156
+
157
+ question.answers.each do |answer|
158
+ answer.answer_text = html_converter.convert(answer.answer_text)
159
+ answer.feedback = html_converter.convert(answer.feedback) if answer.feedback
160
+ end
161
+
162
+ question.post_process! if question.is_a?(Moodle2CC::CanvasCC::Models::CalculatedQuestion)
122
163
  end
123
164
 
165
+ def resolve_duplicate_page_titles!(cc_course)
166
+ page_titles = cc_course.pages.map(&:title)
167
+ duplicate_page_map = cc_course.pages.group_by(&:title).select{|k, v| v.count > 1}
168
+ duplicate_page_map.each do |title, dup_pages|
169
+ dup_pages.sort_by!{|page| find_module_index_for_page(cc_course, page)}
170
+
171
+ dup_pages.each_with_index do |page, index|
172
+ next if index == 0
173
+ num = index + 1
174
+ while (title = "#{page.title}-#{num}") && page_titles.include?(title)
175
+ num += 1
176
+ end
177
+ page.title = title
178
+ end
179
+ end
180
+ end
181
+
182
+ def find_module_index_for_page(cc_course, canvas_page)
183
+ cc_course.canvas_modules.each_with_index do |canvas_module, module_index|
184
+ canvas_module.module_items.each_with_index do |module_item, item_index|
185
+ if module_item.identifierref.to_s == canvas_page.identifier.to_s
186
+ return [module_index, item_index]
187
+ end
188
+ end
189
+ end
190
+ [Float::INFINITY]
191
+ end
124
192
  end
125
193
  end