pnote_client 1.0.1

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