pnote_client 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +98 -0
  8. data/Rakefile +6 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +8 -0
  11. data/config.json +26 -0
  12. data/exe/pnote_to_json +64 -0
  13. data/lib/pnote_client/converters/hml_to_pnote_converter.rb +195 -0
  14. data/lib/pnote_client/converters/pnote_to_json_converter.rb +96 -0
  15. data/lib/pnote_client/display/console_display.rb +37 -0
  16. data/lib/pnote_client/documents/hml/binary_item.rb +20 -0
  17. data/lib/pnote_client/documents/hml/char.rb +27 -0
  18. data/lib/pnote_client/documents/hml/equation.rb +33 -0
  19. data/lib/pnote_client/documents/hml/image.rb +28 -0
  20. data/lib/pnote_client/documents/hml/paragraph.rb +84 -0
  21. data/lib/pnote_client/documents/hml/paragraph_reader.rb +29 -0
  22. data/lib/pnote_client/documents/hml/rectangle.rb +39 -0
  23. data/lib/pnote_client/documents/hml/style.rb +21 -0
  24. data/lib/pnote_client/documents/hml/table.rb +55 -0
  25. data/lib/pnote_client/documents/hml/table_cell.rb +49 -0
  26. data/lib/pnote_client/documents/hml/table_row.rb +34 -0
  27. data/lib/pnote_client/documents/hml.rb +60 -0
  28. data/lib/pnote_client/documents/pnote/chapter.rb +27 -0
  29. data/lib/pnote_client/documents/pnote/concept.rb +26 -0
  30. data/lib/pnote_client/documents/pnote/exercise.rb +10 -0
  31. data/lib/pnote_client/documents/pnote/image.rb +16 -0
  32. data/lib/pnote_client/documents/pnote/practice.rb +25 -0
  33. data/lib/pnote_client/documents/pnote/problem.rb +50 -0
  34. data/lib/pnote_client/documents/pnote/sub_chapter.rb +32 -0
  35. data/lib/pnote_client/documents/pnote/teacher_comment.rb +22 -0
  36. data/lib/pnote_client/documents/pnote.rb +20 -0
  37. data/lib/pnote_client/utils/string_util.rb +10 -0
  38. data/lib/pnote_client/version.rb +3 -0
  39. data/lib/pnote_client.rb +4 -0
  40. data/pnote_client.gemspec +35 -0
  41. metadata +155 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: aefca9ca088bc2820cb547cc1440e8f16171f330
4
+ data.tar.gz: 7f906da6182fc767d86f66f609f2125154f1e873
5
+ SHA512:
6
+ metadata.gz: 5206517055ab81f50e9dd8fd55c0b3b2a0ec884d92ba7503bdf5213a4ea6b038b9b85a7111bc7741c64c06463006efa2990666dd9e899e3e7776ce97533ddd25
7
+ data.tar.gz: 44fcad012662f3149139acc9134ddb415fa1f981921e6f4501e2394f08913495c44ceaaa1b96885e5d7a188274b1abbe4d19be588bdb2da5c90bf9b406a1b05f
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ examples/
11
+ .DS_Store
12
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.2.3
5
+ before_install: gem install bundler -v 1.12.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in pnote_client.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 bluesh55
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # PnoteClient
2
+
3
+ 아래아 한글으로 작성된 프라이빗 노트의 노트 파일(이하 pnote 파일)을 json포맷으로 변환하여 저장합니다.
4
+
5
+ ## Installation
6
+
7
+ Bundler를 사용할 경우 Gemfile에 다음 줄을 추가합니다.
8
+
9
+ ```ruby
10
+ gem 'pnote_client', git: 'git@github.com:PrivateCoach/pnote_client.git'
11
+ ```
12
+
13
+ 그리고 다음 명령을 실행합니다.
14
+
15
+ $ bundle
16
+
17
+ 혹은 다음 명령으로 직접 젬을 설치할 수 있습니다.
18
+
19
+ ```bash
20
+ git clone git@github.com:PrivateCoach/pnote_client.git
21
+ cd ./pnote_client
22
+ gem build pnote_client.gemspec
23
+ gem install pnote_client-[version].gem
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ ### Pnote to JSON
29
+
30
+ hml로 저장된 pnote 파일을 json 파일로 저장시키는 기능입니다.
31
+
32
+ ```bash
33
+ $ pnote_to_json -f [input file(.hml)] -o [output file]
34
+ ```
35
+
36
+ 예를 들어 다음과 같이 사용할 수 있습니다.
37
+
38
+ ```bash
39
+ $ pnote_to_json -f ./subject_1.hml -o ./subject_1.json
40
+ ```
41
+
42
+ 이 기능은 아래아 한글의 `스타일`을 사용하여 문단을 구분하기 때문에
43
+ 입력으로 주어진 pnote에서 사용된 스타일 정보가 필요합니다.
44
+ 기본으로 사용하는 스타일 정보는 다음과 같습니다.
45
+
46
+
47
+ 1. 단원
48
+ 2. 개념군
49
+ 3. 개념
50
+ 4. 개념 본문
51
+ 5. 예제 문제
52
+ 6. 예제(그림, 표, 박스, 글)
53
+ 7. 예제 정답
54
+ 8. 예제 정답 해설
55
+ 9. 문제
56
+ 10. 문제(그림, 표, 박스, 글)
57
+ 11. 문제 정답
58
+ 12. 문제 정답 해설
59
+ 13. 각주(선생님한테 과외받기)
60
+ 14. 보기
61
+ 15. 꿀팁
62
+
63
+ 설정 파일을 통해 스타일 정보를 수정할 수 있습니다.
64
+ 설정 파일은 json 포맷으로 작성되고, `-c` 옵션을 통해 지정할 수 있습니다.
65
+ 예를 들면 다음과 같습니다.
66
+
67
+ ```bash
68
+ $ pnote_to_json -f [input] -o [output] -c ./config.json
69
+ ```
70
+
71
+ `config.json` 파일의 예시는 다음과 같습니다. 키 값은 그대로 두고 스타일 문자열 부분만 변경하면 됩니다.
72
+
73
+ ```json
74
+ {
75
+ "hml_pnote_styles": {
76
+ "chapter": "단원",
77
+ "sub_chapter_title": "개념군",
78
+ "concept_title": "개념",
79
+ "concept_content": "개념 본문",
80
+ "exercise_question": "예제 문제",
81
+ "exercise_continuous_question": "예제(그림, 표, 박스, 글)",
82
+ "exercise_answer": "예제 정답",
83
+ "exercise_explaination": "예제 정답 해설",
84
+ "practice_question": "문제",
85
+ "practice_continuous_question": "문제(그림, 표, 박스, 글)",
86
+ "practice_answer": "문제 정답",
87
+ "practice_explaination": "문제 정답 해설",
88
+ "practice_teacher_comment": "각주(선생님한테 과외받기)",
89
+ "choice": "보기",
90
+ "tip_content": "꿀팁"
91
+ }
92
+ }
93
+ ```
94
+
95
+ ## License
96
+
97
+ [MIT License](http://opensource.org/licenses/MIT)
98
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "pnote_client"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/config.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "hml_pnote_styles": {
3
+ "chapter": "단원",
4
+ "sub_chapter_title": "개념군",
5
+ "concept_title": "개념",
6
+ "concept_content": "개념 본문",
7
+ "exercise_question": "예제 문제",
8
+ "exercise_continuous_question": "예제(그림, 표, 박스, 글)",
9
+ "exercise_answer": "예제 정답",
10
+ "exercise_explaination": "예제 정답 해설",
11
+ "practice_question": "문제",
12
+ "practice_continuous_question": "문제(그림, 표, 박스, 글)",
13
+ "practice_answer": "문제 정답",
14
+ "practice_explaination": "문제 정답 해설",
15
+ "practice_teacher_comment": [
16
+ "각주(선생님한테 과외받기)",
17
+ "코멘트1",
18
+ "코멘트2",
19
+ "코멘트3",
20
+ "코멘트4",
21
+ "코멘트5"
22
+ ],
23
+ "choice": "보기",
24
+ "tip_content": "꿀팁"
25
+ }
26
+ }
data/exe/pnote_to_json ADDED
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+ ## Private Note 파일(.hml)을 JSON 구조로 변환하여 Export 해줍니다.
3
+
4
+ require 'json'
5
+ require 'optparse'
6
+ require 'pnote_client/converters/hml_to_pnote_converter'
7
+ require 'pnote_client/converters/pnote_to_json_converter'
8
+ require 'pnote_client/documents/hml'
9
+ require 'pnote_client/display/console_display'
10
+
11
+ def read_file(filepath)
12
+ f = File.open(filepath, 'r')
13
+ content = f.read
14
+ f.close
15
+ return content
16
+ end
17
+
18
+ def write_file(content, filepath)
19
+ f = File.open(filepath, 'w')
20
+ f.write(content)
21
+ f.close
22
+ end
23
+
24
+ options = {
25
+ include_image_data: false
26
+ }
27
+
28
+ optparser = OptionParser.new do |opt|
29
+ opt.banner = 'Usage: pnote_to_json [options]'
30
+
31
+ opt.on('-f', '--file [FILEPATH]', String, 'Input file path(.hml)') do |filepath|
32
+ options[:input_filepath] = filepath
33
+ end
34
+
35
+ opt.on('-o', '--output [FILEPATH]', String, 'Output file path') do |filepath|
36
+ options[:output_filepath] = filepath
37
+ end
38
+
39
+ opt.on('--[no-]image', 'Include image raw data (Default: false)') do |flag|
40
+ options[:include_image_data] = flag
41
+ end
42
+
43
+ opt.on('-c', '--config [FILEPATH]', String, 'File path of configuration file(`config.json`). Default is `../config.json`') do |filepath|
44
+ options[:config_filepath]
45
+ end
46
+ end
47
+ optparser.parse!
48
+
49
+ if options[:input_filepath].nil? || options[:output_filepath].nil?
50
+ abort(optparser.help)
51
+ end
52
+
53
+ display = PnoteClient::ConsoleDisplay.new
54
+ default_config_file_path = File.join(File.dirname(__FILE__), '..', 'config.json')
55
+ config_content = read_file(options[:config_filepath] || default_config_file_path)
56
+ config = JSON.parse(config_content, symbolize_names: true)
57
+ type_style_mapper = config[:hml_pnote_styles]
58
+
59
+ hml_document = PnoteClient::Documents::Hml.parse_from_file(options[:input_filepath])
60
+ hml_to_pnote_converter = PnoteClient::Converters::HmlToPnoteConverter.new(hml_document, type_style_mapper)
61
+ hml_to_pnote_converter.delegate = display
62
+ pnote_document = hml_to_pnote_converter.convert
63
+ json = PnoteClient::Converters::PnoteToJsonConverter.new(pnote_document, include_image_data: options[:include_image_data]).convert
64
+ write_file(json, options[:output_filepath])
@@ -0,0 +1,195 @@
1
+ require 'pnote_client/documents/pnote'
2
+ require 'pnote_client/documents/pnote/chapter'
3
+ require 'pnote_client/documents/pnote/sub_chapter'
4
+ require 'pnote_client/documents/pnote/concept'
5
+ require 'pnote_client/documents/pnote/exercise'
6
+ require 'pnote_client/documents/pnote/practice'
7
+ require 'pnote_client/documents/pnote/image'
8
+ require 'pnote_client/documents/pnote/teacher_comment'
9
+ require 'pnote_client/documents/hml/paragraph_reader'
10
+
11
+ module PnoteClient
12
+ module Converters
13
+ class HmlToPnoteConverter
14
+
15
+ attr_accessor :delegate
16
+
17
+ def initialize(hml_document, type_style_mapper = {})
18
+ @hml_document = hml_document
19
+ @type_style_mapper = type_style_mapper
20
+
21
+ @current_chapter = nil
22
+ @current_sub_chapter = nil
23
+ @current_concept = nil
24
+ @current_exercise = nil
25
+ @current_practice = nil
26
+ @practice_continuous = false
27
+ @current_problem = nil
28
+ @current_teacher_comment = nil
29
+ @delegate = nil
30
+ end
31
+
32
+ def convert
33
+ pnote_document = Documents::Pnote.new
34
+
35
+ paragraph_length = @hml_document.paragraphs.length
36
+ paragraph_reader = Documents::Hml::ParagraphReader.new(@hml_document.paragraphs)
37
+ paragraph_reader.next_paragraph do |paragraph, prev_paragraph, is_continuous, index|
38
+ case paragraph_type(paragraph)
39
+ when :chapter # 구분점
40
+ new_chapter = Documents::Pnote::Chapter.new
41
+ new_chapter.set_title(paragraph.content)
42
+ add_new_chapter_to_pnote(pnote_document, new_chapter)
43
+ when :sub_chapter_title # 구분점
44
+ new_sub_chapter = Documents::Pnote::SubChapter.new
45
+ new_sub_chapter.set_title(paragraph.content)
46
+ add_new_sub_chapter_to_chapter(@current_chapter, new_sub_chapter) if @current_chapter
47
+ when :concept_title # 구분점
48
+ new_concept = Documents::Pnote::Concept.new
49
+ new_concept.set_title(paragraph.content)
50
+ add_new_concept_to_sub_chapter(@current_sub_chapter, new_concept) if @current_sub_chapter
51
+ when :concept_content
52
+ @current_concept.add_content(paragraph.content) if @current_concept
53
+ when :exercise_question # 구분점
54
+ if is_continuous
55
+ @current_exercise.add_question_line(paragraph.content) if @current_exercise
56
+ else
57
+ new_exercise = Documents::Pnote::Exercise.new
58
+ new_exercise.question = paragraph.content
59
+ add_new_exercise_to_sub_chapter(@current_sub_chapter, new_exercise) if @current_sub_chapter
60
+ end
61
+ when :exercise_continuous_question
62
+ @current_exercise.add_question_line(paragraph.content) if @current_exercise
63
+ when :exercise_answer
64
+ @current_exercise.add_answer_line(paragraph.content) if @current_exercise
65
+ when :exercise_explaination
66
+ @current_exercise.add_explaination_line(paragraph.content) if @current_exercise
67
+ when :practice_question # 구분점
68
+ if @practice_continuous
69
+ @current_practice.add_question_line(paragraph.content) if @current_practice
70
+ else
71
+ new_practice = Documents::Pnote::Practice.new
72
+ new_practice.question = paragraph.content
73
+
74
+ if @current_sub_chapter
75
+ # 실전문제를 소단원에 추가
76
+ add_new_practice_to_sub_chapter(@current_sub_chapter, new_practice) if @current_sub_chapter
77
+ elsif @current_chapter
78
+ # 소단원이 없다면 실전문제를 단원에 추가(심화문제)
79
+ add_new_practice_to_chapter(@current_chapter, new_practice) if @current_chapter
80
+ end
81
+ end
82
+
83
+ # 답변(미주)
84
+ endnote_paragraph_reader = Documents::Hml::ParagraphReader.new(paragraph.endnote_paragraphs)
85
+ endnote_paragraph_reader.next_paragraph do |endnote_paragraph, prev_endnote_paragraph, is_continuous|
86
+ case paragraph_type(endnote_paragraph)
87
+ when :practice_answer
88
+ @current_practice.add_answer_line(endnote_paragraph.content) if @current_practice
89
+ when :practice_explaination
90
+ @current_practice.add_explaination_line(endnote_paragraph.content) if @current_practice
91
+ when :tip_content
92
+ @current_practice.add_tip_line(endnote_paragraph.content) if @current_practice
93
+ end
94
+ end
95
+
96
+ # 과외노트(각주)
97
+ footnote_paragraph_reader = Documents::Hml::ParagraphReader.new(paragraph.footnote_paragraphs)
98
+ footnote_paragraph_reader.next_paragraph do |footnote_paragraph, prev_footnote_paragraph, is_continuous, index|
99
+ case paragraph_type(footnote_paragraph)
100
+ when :practice_teacher_comment
101
+ if is_continuous
102
+ @current_teacher_comment.add_content_line(footnote_paragraph.content) if @current_teacher_comment
103
+ else
104
+ new_teacher_comment = Documents::Pnote::TeacherComment.new(index)
105
+ new_teacher_comment.content = footnote_paragraph.content
106
+ add_new_teacher_comment_to_practice(@current_practice, new_teacher_comment) if @current_practice
107
+ end
108
+ end
109
+ end
110
+
111
+ @practice_continuous = paragraph.footnote_paragraphs.size == 0 # 각주가 없다면 다음 paragraph도 같은 문제로 인식
112
+ when :practice_continuous_question
113
+ @current_practice.add_question_line(paragraph.content) if @current_practice
114
+ when :choice
115
+ @current_problem.add_choice_line(paragraph.content) if @current_problem
116
+ end
117
+
118
+ @delegate.paragraph_converted(count: paragraph_length, current: index) if @delegate
119
+ end
120
+
121
+
122
+ binary_count = @hml_document.bin_items.length
123
+ @hml_document.bin_items.each_with_index do |bin_item, index|
124
+ pnote_document.add_image(Documents::Pnote::Image.new(bin_item.id, bin_item.format, bin_item.size, bin_item.raw_data))
125
+
126
+ @delegate.binary_converted(count: binary_count, current: index) if @delegate
127
+ end
128
+
129
+ return pnote_document
130
+ end
131
+
132
+ private
133
+
134
+ def add_new_chapter_to_pnote(pnote_document, new_chapter)
135
+ pnote_document.add_chapter(new_chapter)
136
+ @current_chapter = new_chapter
137
+ @current_sub_chapter = nil
138
+ @current_concept = nil
139
+ @current_exercise = nil
140
+ @current_practice = nil
141
+ @current_problem = nil
142
+ @current_teacher_comment = nil
143
+ end
144
+
145
+ def add_new_sub_chapter_to_chapter(chapter, new_sub_chapter)
146
+ chapter.add_sub_chapter(new_sub_chapter)
147
+ @current_sub_chapter = new_sub_chapter
148
+ @current_concept = nil
149
+ @current_exercise = nil
150
+ @current_practice = nil
151
+ @current_problem = nil
152
+ @current_teacher_comment = nil
153
+ end
154
+
155
+ def add_new_concept_to_sub_chapter(sub_chapter, new_concept)
156
+ sub_chapter.add_concept(new_concept)
157
+ @current_concept = new_concept
158
+ end
159
+
160
+ def add_new_exercise_to_sub_chapter(sub_chapter, new_exercise)
161
+ sub_chapter.add_exercise(new_exercise)
162
+ @current_exercise = new_exercise
163
+ @current_problem = new_exercise
164
+ end
165
+
166
+ def add_new_practice_to_sub_chapter(sub_chapter, new_practice)
167
+ sub_chapter.add_practice(new_practice)
168
+ @current_practice = new_practice
169
+ @current_problem = new_practice
170
+ end
171
+
172
+ def add_new_practice_to_chapter(chapter, new_practice)
173
+ chapter.add_practice(new_practice)
174
+ @current_practice = new_practice
175
+ @current_problem = new_practice
176
+ end
177
+
178
+ def add_new_teacher_comment_to_practice(practice, new_teacher_comment)
179
+ practice.add_teacher_comment(new_teacher_comment)
180
+ @current_teacher_comment = new_teacher_comment
181
+ end
182
+
183
+ def paragraph_type(paragraph)
184
+ pg_style = find_style(paragraph.style_id)
185
+ result = @type_style_mapper.find {|k, v| v == pg_style.name || (v.is_a?(Array) && v.include?(pg_style.name))}
186
+ return nil if result.nil?
187
+ return result[0]
188
+ end
189
+
190
+ def find_style(style_id)
191
+ return @hml_document.styles.find {|style| style.id == style_id}
192
+ end
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,96 @@
1
+ require 'json'
2
+
3
+ module PnoteClient
4
+ module Converters
5
+ class PnoteToJsonConverter
6
+
7
+ def initialize(pnote_document, include_image_data: false)
8
+ @pnote_document = pnote_document
9
+ @include_image_data = include_image_data
10
+ end
11
+
12
+ def convert
13
+ result = {
14
+ chapters: [],
15
+ images: [],
16
+ created_at: Time.now.strftime("%Y-%m-%d %H:%M")
17
+ }
18
+
19
+ @pnote_document.images.each do |image|
20
+ result[:images] << {
21
+ id: image.id,
22
+ format: image.format,
23
+ size: image.size,
24
+ raw_data: @include_image_data ? image.raw_data : nil
25
+ }
26
+ end
27
+
28
+ @pnote_document.chapters.each do |chapter|
29
+ chapter_hash = {
30
+ title: chapter.title,
31
+ sub_chapters: [],
32
+ practices: []
33
+ }
34
+ result[:chapters] << chapter_hash
35
+
36
+ # 단원의 소단원 목록
37
+ chapter.sub_chapters.each do |sub_chapter|
38
+ sub_chapter_hash = {
39
+ title: sub_chapter.title,
40
+ concepts: [],
41
+ exercises: [],
42
+ practices: []
43
+ }
44
+ chapter_hash[:sub_chapters] << sub_chapter_hash
45
+
46
+ sub_chapter.concepts.each do |concept|
47
+ concept_hash = {
48
+ title: concept.title,
49
+ content: concept.content
50
+ }
51
+
52
+ sub_chapter_hash[:concepts] << concept_hash
53
+ end
54
+
55
+ sub_chapter.exercises.each do |exercise|
56
+ exercise_hash = {
57
+ question: exercise.question,
58
+ answer: exercise.answer,
59
+ explaination: exercise.explaination,
60
+ choices: exercise.choices
61
+ }
62
+ sub_chapter_hash[:exercises] << exercise_hash
63
+ end
64
+
65
+ sub_chapter.practices.each do |practice|
66
+ practice_hash = {
67
+ question: practice.question,
68
+ answer: practice.answer,
69
+ explaination: practice.explaination,
70
+ teacher_comments: practice.teacher_comments.sort_by {|tc| tc.index }.map(&:content),
71
+ choices: practice.choices,
72
+ tip: practice.tip
73
+ }
74
+ sub_chapter_hash[:practices] << practice_hash
75
+ end
76
+ end
77
+
78
+ # 단원의 실전 문제
79
+ chapter.practices.each do |practice|
80
+ practice_hash = {
81
+ question: practice.question,
82
+ answer: practice.answer,
83
+ explaination: practice.explaination,
84
+ teacher_comments: practice.teacher_comments.sort_by {|tc| tc.index }.map(&:content),
85
+ choices: practice.choices,
86
+ tip: practice.tip
87
+ }
88
+ chapter_hash[:practices] << practice_hash
89
+ end
90
+ end
91
+
92
+ return result.to_json
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,37 @@
1
+ module PnoteClient
2
+ class ConsoleDisplay
3
+ # implement HmlToPnoteConverter Delegate
4
+ # implement PnoteClient Delegate
5
+
6
+ def initialize
7
+ end
8
+
9
+ def paragraph_converted(count:, current:)
10
+ print_progress(count, current, "Converting paragraphs")
11
+
12
+ # Print newline when task is done
13
+ if count == (current + 1)
14
+ printf("\n")
15
+ end
16
+ end
17
+
18
+ def binary_converted(count:, current:)
19
+ print_progress(count, current, "Converting binaries")
20
+
21
+ # Print newline when task is done
22
+ if count == (current + 1)
23
+ printf("\n")
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def print_progress(count, current, title)
30
+ printf("\r[#{title}] #{current + 1}/#{count} [%-20s]", "=" * (percentage(count, current + 1) / 5) + ">")
31
+ end
32
+
33
+ def percentage(count, current)
34
+ return ((100.0 / count) * current)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,20 @@
1
+ module PnoteClient
2
+ module Documents
3
+ class Hml
4
+ class BinaryItem
5
+ attr_reader :id, :raw_data, :format, :size
6
+
7
+ def initialize(bin_item_tag, doc)
8
+ bin_data_id = bin_item_tag['BinData']
9
+ bin_item = doc.at_xpath("//BINITEM[@BinData=#{bin_data_id}]")
10
+ bin_data = doc.at_xpath("//BINDATA[@Id=#{bin_data_id}]")
11
+
12
+ @id = bin_data_id
13
+ @raw_data = bin_data.content
14
+ @format = bin_item['Format']
15
+ @size = bin_data['Size'].to_i
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+ module PnoteClient
2
+ module Documents
3
+ class Hml
4
+ class Char
5
+ # Textable Element
6
+
7
+ def self.from_tag(char_tag)
8
+ return self.new(char_tag.content)
9
+ end
10
+
11
+ attr_reader :text
12
+
13
+ def initialize(text)
14
+ @text = text
15
+ end
16
+
17
+ def content
18
+ return @text
19
+ end
20
+
21
+ def textable?
22
+ return true
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end