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.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +98 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/config.json +26 -0
- data/exe/pnote_to_json +64 -0
- data/lib/pnote_client/converters/hml_to_pnote_converter.rb +195 -0
- data/lib/pnote_client/converters/pnote_to_json_converter.rb +96 -0
- data/lib/pnote_client/display/console_display.rb +37 -0
- data/lib/pnote_client/documents/hml/binary_item.rb +20 -0
- data/lib/pnote_client/documents/hml/char.rb +27 -0
- data/lib/pnote_client/documents/hml/equation.rb +33 -0
- data/lib/pnote_client/documents/hml/image.rb +28 -0
- data/lib/pnote_client/documents/hml/paragraph.rb +84 -0
- data/lib/pnote_client/documents/hml/paragraph_reader.rb +29 -0
- data/lib/pnote_client/documents/hml/rectangle.rb +39 -0
- data/lib/pnote_client/documents/hml/style.rb +21 -0
- data/lib/pnote_client/documents/hml/table.rb +55 -0
- data/lib/pnote_client/documents/hml/table_cell.rb +49 -0
- data/lib/pnote_client/documents/hml/table_row.rb +34 -0
- data/lib/pnote_client/documents/hml.rb +60 -0
- data/lib/pnote_client/documents/pnote/chapter.rb +27 -0
- data/lib/pnote_client/documents/pnote/concept.rb +26 -0
- data/lib/pnote_client/documents/pnote/exercise.rb +10 -0
- data/lib/pnote_client/documents/pnote/image.rb +16 -0
- data/lib/pnote_client/documents/pnote/practice.rb +25 -0
- data/lib/pnote_client/documents/pnote/problem.rb +50 -0
- data/lib/pnote_client/documents/pnote/sub_chapter.rb +32 -0
- data/lib/pnote_client/documents/pnote/teacher_comment.rb +22 -0
- data/lib/pnote_client/documents/pnote.rb +20 -0
- data/lib/pnote_client/utils/string_util.rb +10 -0
- data/lib/pnote_client/version.rb +3 -0
- data/lib/pnote_client.rb +4 -0
- data/pnote_client.gemspec +35 -0
- 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
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
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
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
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
|