curriculum-generator 1.0.5 → 1.0.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.
- checksums.yaml +4 -4
- data/lib/curriculum-generator.rb +3 -3
- data/lib/curriculum-generator/data_loader/yaml_data_loader.rb +27 -21
- data/lib/curriculum-generator/generator/cv_item_with_comment.rb +29 -25
- data/lib/curriculum-generator/generator/cv_list_double_item.rb +28 -24
- data/lib/curriculum-generator/generator/cv_list_item.rb +21 -17
- data/lib/curriculum-generator/generator/list.rb +23 -19
- data/lib/curriculum-generator/generator/macro_substitution.rb +11 -7
- data/lib/curriculum-generator/generator/specific/education.rb +68 -64
- data/lib/curriculum-generator/generator/specific/self_assessment.rb +60 -56
- data/lib/curriculum-generator/generator/specific/work_experience.rb +58 -54
- data/lib/curriculum-generator/util/latex_to_pdf.rb +57 -53
- data/lib/curriculum-generator/util/logging.rb +26 -22
- data/lib/curriculum-generator/util/shell_command.rb +41 -37
- data/lib/curriculum-generator/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4ca48dcc11780c66bb696b872897abb8b9b94c84
|
4
|
+
data.tar.gz: 69d410306cf74b85962261c54f5a2da1d4926baf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 380be4c4ed32c3502b01de9dba5ca46326b904f79865b4b9b11ad09a8b616b5d027c6e666f44e4d665ce17dc273fb9a93b7bfce8b110b18ee9fe61697e79aa6c
|
7
|
+
data.tar.gz: 1c192889f053696e106d8c5b7a60b18f9c07d01eba34a247a83021df75a6dc4812d51483ffa368264094626b8ab87cbc0db0e6d67c30f93d0c6a6880b9bf9fb4
|
data/lib/curriculum-generator.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
#
|
1
|
+
# Require the core dependencies.
|
2
2
|
require "tmpdir"
|
3
3
|
require "pathname"
|
4
4
|
|
5
|
-
#
|
5
|
+
# Require all of the external dependencies.
|
6
6
|
require "hash_deep_merge"
|
7
7
|
require "monadic"
|
8
8
|
require "awesome_print"
|
@@ -10,7 +10,7 @@ require "colorize"
|
|
10
10
|
require "highline/import"
|
11
11
|
require "erubis"
|
12
12
|
|
13
|
-
#
|
13
|
+
# Require the project stuff.
|
14
14
|
require "curriculum-generator/version"
|
15
15
|
require "curriculum-generator/util"
|
16
16
|
require "curriculum-generator/compiler"
|
@@ -1,31 +1,37 @@
|
|
1
|
-
require
|
1
|
+
require "yaml"
|
2
2
|
|
3
3
|
|
4
|
-
|
4
|
+
module CurriculumGenerator
|
5
|
+
module DataLoader
|
6
|
+
class YamlDataLoader
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
# Load the localized data from the directory `data_dir_pth`, following the convention that the localized data for
|
9
|
+
# a language are in a subdirectory of `data_dir_pth` named with the same name of the language.
|
10
|
+
# The target language name (which is also the subdirectory name) is `trgt_lang`, which fallbacks to the `master_lang`
|
11
|
+
def load_data(data_dir_pth, trgt_lang, master_lang)
|
12
|
+
CurriculumGenerator::Util::Logging.log(:loading_curriculum_data, trgt_lang: trgt_lang, master_lang: master_lang)
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
+
trgt_lang_data_dir_pth = data_dir_pth.join(trgt_lang.to_s)
|
15
|
+
master_lang_data_dir_pth = data_dir_pth.join(master_lang.to_s)
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
+
master_data = load_recursive_from_pth(trgt_lang_data_dir_pth)
|
18
|
+
trgt_data = load_recursive_from_pth(master_lang_data_dir_pth)
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
+
trgt_data.deep_merge(master_data)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Load all of the YAML file starting from the given `base_dir_pth` and merges all of the data into an `Hash` and
|
24
|
+
# returns it
|
25
|
+
def load_recursive_from_pth(base_dir_pth)
|
26
|
+
data = {}
|
27
|
+
|
28
|
+
Dir.glob(base_dir_pth.join('**').join('*.yml')) do |yml_file_pth|
|
29
|
+
File.open(yml_file_pth, 'r') { |yml_file| data.merge!(YAML::load(yml_file)) }
|
30
|
+
end
|
31
|
+
|
32
|
+
data
|
33
|
+
end
|
20
34
|
|
21
|
-
# Load all of the YAML file starting from the given `base_dir_pth` and merges all of the data into an `Hash` and
|
22
|
-
# returns it
|
23
|
-
def load_recursive_from_pth(base_dir_pth)
|
24
|
-
data = {}
|
25
|
-
Dir.glob(base_dir_pth.join('**').join('*.yml')) do |yml_file_pth|
|
26
|
-
File.open(yml_file_pth, 'r') { |yml_file| data.merge!(YAML::load(yml_file)) }
|
27
35
|
end
|
28
|
-
data # return
|
29
36
|
end
|
30
|
-
|
31
37
|
end
|
@@ -1,32 +1,36 @@
|
|
1
|
-
|
1
|
+
module CurriculumGenerator
|
2
|
+
module Generator
|
3
|
+
class CvItemWithComment < BasicGenerator
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
5
|
+
def initialize(param, data, lang)
|
6
|
+
super(param, data, lang)
|
7
|
+
end
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
9
|
+
def generate
|
10
|
+
value = get_value(param)
|
11
|
+
value = Array[value] unless value.is_a?(Array)
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
13
|
+
inst = self
|
14
|
+
value.collect do |elem|
|
15
|
+
result = Either.chain do
|
16
|
+
bind -> { elem.is_a?(Hash) }
|
17
|
+
bind -> {
|
18
|
+
elem.has_key?('title') &&
|
19
|
+
elem.has_key?('content') &&
|
20
|
+
elem.has_key?('comment')
|
21
|
+
}
|
22
|
+
bind -> {
|
23
|
+
inst.get_cv_item_with_comment(elem['title'], elem['content'], elem['comment'])
|
24
|
+
}
|
25
|
+
end
|
26
|
+
result.success? ? result.fetch : ''
|
27
|
+
end.join("\n")
|
23
28
|
end
|
24
|
-
result.success? ? result.fetch : ''
|
25
|
-
end.join("\n")
|
26
|
-
end
|
27
29
|
|
28
|
-
|
29
|
-
|
30
|
-
|
30
|
+
def get_cv_item_with_comment(title, content, comment)
|
31
|
+
"\\cvitemwithcomment{#{title}}{#{content}}{#{comment}}"
|
32
|
+
end
|
31
33
|
|
34
|
+
end
|
35
|
+
end
|
32
36
|
end
|
@@ -1,31 +1,35 @@
|
|
1
|
-
|
1
|
+
module CurriculumGenerator
|
2
|
+
module Generator
|
3
|
+
class CvListDoubleItem < BasicGenerator
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
5
|
+
def initialize(param, data, lang)
|
6
|
+
super(param, data, lang)
|
7
|
+
end
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
9
|
+
def generate
|
10
|
+
value = get_value(param)
|
11
|
+
unless value.is_a?(Array)
|
12
|
+
value = Array[value]
|
13
|
+
end
|
14
|
+
value.collect do |elem|
|
15
|
+
instance = self
|
16
|
+
result = Either.chain do
|
17
|
+
bind -> { elem.is_a?(Hash) }
|
18
|
+
bind -> { elem.has_key?('item_0') && elem.has_key?('item_1') }
|
19
|
+
bind -> {
|
20
|
+
instance.get_cv_list_double_item(elem['item_0'], elem['item_1'])
|
21
|
+
}
|
22
|
+
end
|
23
|
+
result.success? ? result.fetch : ''
|
24
|
+
end.join("\n")
|
20
25
|
end
|
21
|
-
result.success? ? result.fetch : ''
|
22
|
-
end.join("\n")
|
23
|
-
end
|
24
26
|
|
25
|
-
|
27
|
+
protected
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
|
29
|
+
def get_cv_list_double_item(item_0, item_1)
|
30
|
+
"\\cvlistdoubleitem{#{item_0}}{#{item_1}}"
|
31
|
+
end
|
30
32
|
|
33
|
+
end
|
34
|
+
end
|
31
35
|
end
|
@@ -1,23 +1,27 @@
|
|
1
|
-
class CurriculumGenerator
|
1
|
+
class CurriculumGenerator
|
2
|
+
module Generator
|
3
|
+
class CvListItem < BasicGenerator
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
5
|
+
def initialize(param, data, lang)
|
6
|
+
super(param, data, lang)
|
7
|
+
end
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
def generate
|
10
|
+
value = get_value(param)
|
11
|
+
unless value.is_a?(Array)
|
12
|
+
value = Array[value]
|
13
|
+
end
|
14
|
+
value.collect do |content|
|
15
|
+
get_cv_list_item(content)
|
16
|
+
end.join("\n")
|
17
|
+
end
|
16
18
|
|
17
|
-
|
19
|
+
protected
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
def get_cv_list_item(content)
|
22
|
+
"\\cvlistitem{#{content}}"
|
23
|
+
end
|
22
24
|
|
25
|
+
end
|
26
|
+
end
|
23
27
|
end
|
@@ -1,25 +1,29 @@
|
|
1
|
-
|
1
|
+
module CurriculumGenerator
|
2
|
+
module Generator
|
3
|
+
class List < BasicGenerator
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
5
|
+
def initialize(param, data, lang)
|
6
|
+
super(param, data, lang)
|
7
|
+
end
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
9
|
+
def generate
|
10
|
+
value = get_value(param)
|
11
|
+
unless value.is_a?(Array)
|
12
|
+
value = Array[value]
|
13
|
+
end
|
14
|
+
'\begin{itemize}' +
|
15
|
+
value.collect do |item|
|
16
|
+
get_list(item)
|
17
|
+
end.join('') +
|
18
|
+
'\end{itemize}'
|
19
|
+
end
|
18
20
|
|
19
|
-
|
21
|
+
protected
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
|
23
|
+
def get_list(item)
|
24
|
+
"\\item #{item}"
|
25
|
+
end
|
24
26
|
|
27
|
+
end
|
28
|
+
end
|
25
29
|
end
|
@@ -1,11 +1,15 @@
|
|
1
|
-
|
1
|
+
module CurriculumGenerator
|
2
|
+
module Generator
|
3
|
+
class MacroSubstitution < BasicGenerator
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
5
|
+
def initialize(param, data, lang)
|
6
|
+
super(param, data, lang)
|
7
|
+
end
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
9
|
+
def generate
|
10
|
+
get_value(param)
|
11
|
+
end
|
10
12
|
|
13
|
+
end
|
14
|
+
end
|
11
15
|
end
|
@@ -1,95 +1,99 @@
|
|
1
|
-
|
1
|
+
module CurriculumGenerator
|
2
|
+
module Generator
|
3
|
+
class Education < BasicGenerator
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
5
|
+
def initialize(param, data, lang)
|
6
|
+
super(param, data, lang)
|
7
|
+
end
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
def generate
|
10
|
+
value = get_value(param)
|
11
|
+
value.collect do |elem|
|
12
|
+
get_education(elem)
|
13
|
+
end.join('')
|
14
|
+
end
|
13
15
|
|
14
|
-
|
16
|
+
protected
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
+
def get_education(context)
|
19
|
+
context.merge!({'titles' => get_value('titles')})
|
18
20
|
|
19
|
-
|
21
|
+
input = <<-CODE
|
20
22
|
|
21
|
-
|
23
|
+
\\cventry
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
<% if @date.nil? %>
|
26
|
+
{}
|
27
|
+
<% elsif @date.is_a?(Hash) && @date.has_key?('from') && @date.has_key?('to') %>
|
28
|
+
{<%= @date['from'] %>\\\\<%= @date['to'] %>}
|
29
|
+
<% else %>
|
30
|
+
{<%= @date %>}
|
31
|
+
<% end %>
|
30
32
|
|
31
|
-
|
33
|
+
{<%= @title.nil? ? '' : @title %>}
|
32
34
|
|
33
|
-
|
35
|
+
{}{}{}
|
34
36
|
|
35
|
-
|
37
|
+
{\\begin{itemize}
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
39
|
+
<% if @qualification %>
|
40
|
+
\\item \\textit{<%= @titles['S_4']['qualification'] %>}: <%= @qualification %>
|
41
|
+
<% end %>
|
40
42
|
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
<% if @organisation %>
|
44
|
+
\\item \\textit{<%= @titles['S_4']['organisation'] %>}: <%= @organisation %>
|
45
|
+
<% end %>
|
46
|
+
|
47
|
+
<% if @level %>
|
48
|
+
\\item \\textit{<%= @titles['S_4']['level'] %>}: <%= @level %>
|
49
|
+
<% end %>
|
44
50
|
|
45
|
-
|
46
|
-
|
47
|
-
|
51
|
+
<% if @lessons %>
|
52
|
+
\\item \\textit{<%= @titles['S_4']['lessons'] %>}: <%= @lessons %>
|
53
|
+
<% end %>
|
48
54
|
|
49
|
-
|
50
|
-
|
51
|
-
|
55
|
+
<% if @validity %>
|
56
|
+
\\item \\textit{<%= @titles['S_4']['validity'] %>}: <%= @validity %>
|
57
|
+
<% end %>
|
52
58
|
|
53
|
-
|
54
|
-
|
55
|
-
|
59
|
+
<% if @location %>
|
60
|
+
\\item \\textit{<%= @titles['S_4']['location'] %>}: <%= @location %>
|
61
|
+
<% end %>
|
56
62
|
|
57
|
-
|
58
|
-
|
59
|
-
|
63
|
+
<% if @teacher %>
|
64
|
+
\\item \\textit{<%= @titles['S_4']['teacher'] %>}: <%= @teacher %>
|
65
|
+
<% end %>
|
60
66
|
|
61
|
-
|
62
|
-
\\item \\textit{<%= @titles['S_4']['teacher'] %>}: <%= @teacher %>
|
63
|
-
<% end %>
|
67
|
+
<% if @skills_covered %>
|
64
68
|
|
65
|
-
|
69
|
+
<% unless @skills_covered.is_a?(Array) %>
|
70
|
+
<% @skills_covered = Array[@skills_covered] %>
|
71
|
+
<% end %>
|
66
72
|
|
67
|
-
|
68
|
-
<% @skills_covered = Array[@skills_covered] %>
|
69
|
-
<% end %>
|
73
|
+
<% @skills_covered.compact! %>
|
70
74
|
|
71
|
-
|
75
|
+
<% if @skills_covered.length > 0 %>
|
72
76
|
|
73
|
-
|
77
|
+
\\item \\textit{<%= @titles['S_4']['skills_covered'] %>}:
|
78
|
+
\\begin{itemize}
|
74
79
|
|
75
|
-
|
76
|
-
|
80
|
+
<% @skills_covered.each do |skill_covered| %>
|
81
|
+
\\item <%= skill_covered %>
|
82
|
+
<% end %>
|
77
83
|
|
78
|
-
|
79
|
-
\\item <%= skill_covered %>
|
80
|
-
<% end %>
|
84
|
+
\\end{itemize}
|
81
85
|
|
82
|
-
|
86
|
+
<% end %>
|
83
87
|
|
84
|
-
|
88
|
+
<% end %>
|
85
89
|
|
86
|
-
|
90
|
+
\\end{itemize}}
|
87
91
|
|
88
|
-
|
92
|
+
CODE
|
89
93
|
|
90
|
-
|
94
|
+
evaluate(input, context).gsub(/^\s+/,'').gsub(/\n/,'') + "\n\n"
|
95
|
+
end
|
91
96
|
|
92
|
-
|
97
|
+
end
|
93
98
|
end
|
94
|
-
|
95
99
|
end
|
@@ -1,61 +1,65 @@
|
|
1
|
-
|
1
|
+
module CurriculumGenerator
|
2
|
+
module Generator
|
3
|
+
class SelfAssessment < BasicGenerator
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
5
|
+
def initialize(param, data, lang)
|
6
|
+
super(param, data, lang)
|
7
|
+
end
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
9
|
+
def generate
|
10
|
+
get_self_assessment(get_value(param))
|
11
|
+
end
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
\\multicolumn{1}{c|}{<%= ' ' %>} &
|
25
|
-
\\multicolumn{4}{|c|}{\\textbf{<%= @titles['S_5']['understanding'] %>}} &
|
26
|
-
\\multicolumn{4}{|c|}{\\textbf{<%= @titles['S_5']['speaking'] %>}} &
|
27
|
-
\\multicolumn{2}{|c|}{\\textbf{<%= @titles['S_5']['writing'] %>}} \\\\
|
28
|
-
|
29
|
-
\\multicolumn{1}{c|}{<%= ' ' %>} &
|
30
|
-
\\multicolumn{2}{|c|}{<%= @titles['S_5']['listening'] %>} &
|
31
|
-
\\multicolumn{2}{|c|}{<%= @titles['S_5']['reading'] %>} &
|
32
|
-
\\multicolumn{2}{|c|}{<%= @titles['S_5']['spoken_interaction'] %>} &
|
33
|
-
\\multicolumn{2}{|c|}{<%= @titles['S_5']['spoken_production'] %>} &
|
34
|
-
\\multicolumn{2}{|c|}{<%= @titles['S_5']['written_production'] %>} \\\\
|
35
|
-
\\hline
|
36
|
-
|
37
|
-
<% @languages.each do |language| %>
|
38
|
-
\\hline
|
39
|
-
\\textbf{<%= language['name'] %>} &
|
40
|
-
<%= language['listening']['level'] %> &
|
41
|
-
<%= language['listening']['description'] %> &
|
42
|
-
<%= language['reading']['level'] %> &
|
43
|
-
<%= language['reading']['description'] %> &
|
44
|
-
<%= language['spoken_interaction']['level'] %> &
|
45
|
-
<%= language['spoken_interaction']['description'] %> &
|
46
|
-
<%= language['spoken_production']['level'] %> &
|
47
|
-
<%= language['spoken_production']['description'] %> &
|
48
|
-
<%= language['written_production']['level'] %> &
|
49
|
-
<%= language['written_production']['description'] %> \\\\
|
50
|
-
<% end %>
|
51
|
-
\\hline
|
52
|
-
|
53
|
-
\\end{tabular}
|
54
|
-
}
|
55
|
-
|
56
|
-
CODE
|
57
|
-
|
58
|
-
evaluate(input, context).gsub(/^\s+/,'').gsub(/\n/,'') + "\n\n"
|
59
|
-
end
|
13
|
+
protected
|
14
|
+
|
15
|
+
def get_self_assessment(context)
|
16
|
+
context.merge!({'titles' => get_value('titles')})
|
17
|
+
|
18
|
+
input = <<-CODE
|
19
|
+
|
20
|
+
\\cvitem{<%= @titles['S_5']['self_assessment'] %>}
|
21
|
+
|
22
|
+
{
|
23
|
+
\\scriptsize
|
24
|
+
\\begin{tabular}{l|l|l|l|l|l|l|l|l|l|l}
|
60
25
|
|
26
|
+
\\multicolumn{1}{c|}{<%= ' ' %>} &
|
27
|
+
\\multicolumn{4}{|c|}{\\textbf{<%= @titles['S_5']['understanding'] %>}} &
|
28
|
+
\\multicolumn{4}{|c|}{\\textbf{<%= @titles['S_5']['speaking'] %>}} &
|
29
|
+
\\multicolumn{2}{|c|}{\\textbf{<%= @titles['S_5']['writing'] %>}} \\\\
|
30
|
+
|
31
|
+
\\multicolumn{1}{c|}{<%= ' ' %>} &
|
32
|
+
\\multicolumn{2}{|c|}{<%= @titles['S_5']['listening'] %>} &
|
33
|
+
\\multicolumn{2}{|c|}{<%= @titles['S_5']['reading'] %>} &
|
34
|
+
\\multicolumn{2}{|c|}{<%= @titles['S_5']['spoken_interaction'] %>} &
|
35
|
+
\\multicolumn{2}{|c|}{<%= @titles['S_5']['spoken_production'] %>} &
|
36
|
+
\\multicolumn{2}{|c|}{<%= @titles['S_5']['written_production'] %>} \\\\
|
37
|
+
\\hline
|
38
|
+
|
39
|
+
<% @languages.each do |language| %>
|
40
|
+
\\hline
|
41
|
+
\\textbf{<%= language['name'] %>} &
|
42
|
+
<%= language['listening']['level'] %> &
|
43
|
+
<%= language['listening']['description'] %> &
|
44
|
+
<%= language['reading']['level'] %> &
|
45
|
+
<%= language['reading']['description'] %> &
|
46
|
+
<%= language['spoken_interaction']['level'] %> &
|
47
|
+
<%= language['spoken_interaction']['description'] %> &
|
48
|
+
<%= language['spoken_production']['level'] %> &
|
49
|
+
<%= language['spoken_production']['description'] %> &
|
50
|
+
<%= language['written_production']['level'] %> &
|
51
|
+
<%= language['written_production']['description'] %> \\\\
|
52
|
+
<% end %>
|
53
|
+
\\hline
|
54
|
+
|
55
|
+
\\end{tabular}
|
56
|
+
}
|
57
|
+
|
58
|
+
CODE
|
59
|
+
|
60
|
+
evaluate(input, context).gsub(/^\s+/,'').gsub(/\n/,'') + "\n\n"
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
61
65
|
end
|
@@ -1,81 +1,85 @@
|
|
1
|
-
|
1
|
+
module CurriculumGenerator
|
2
|
+
module Generator
|
3
|
+
class WorkExperience < BasicGenerator
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
5
|
+
def initialize(param, data, lang)
|
6
|
+
super(param, data, lang)
|
7
|
+
end
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
def generate
|
10
|
+
value = get_value(param)
|
11
|
+
value.collect do |elem|
|
12
|
+
get_work_experience(elem)
|
13
|
+
end.join("\n")
|
14
|
+
end
|
13
15
|
|
14
|
-
|
16
|
+
protected
|
15
17
|
|
16
|
-
|
18
|
+
def get_work_experience(context)
|
17
19
|
|
18
|
-
|
20
|
+
context.merge!({'titles' => get_value('titles')})
|
19
21
|
|
20
|
-
|
22
|
+
input = <<-CODE
|
21
23
|
|
22
|
-
|
24
|
+
\\cventry
|
25
|
+
|
26
|
+
<% if @date.nil? %>
|
27
|
+
{}
|
28
|
+
<% elsif @date.is_a?(Hash) && @date.has_key?('from') && @date.has_key?('to') %>
|
29
|
+
{<%= @date['from'] %>\\\\<%= @date['to'] %>}
|
30
|
+
<% else %>
|
31
|
+
{<%= @date %>}
|
32
|
+
<% end %>
|
23
33
|
|
24
|
-
|
25
|
-
{}
|
26
|
-
<% elsif @date.is_a?(Hash) && @date.has_key?('from') && @date.has_key?('to') %>
|
27
|
-
{<%= @date['from'] %>\\\\<%= @date['to'] %>}
|
28
|
-
<% else %>
|
29
|
-
{<%= @date %>}
|
30
|
-
<% end %>
|
34
|
+
{<%= @occupation.nil? ? '' : @occupation %>}
|
31
35
|
|
32
|
-
|
36
|
+
<% if @employer_name %>
|
33
37
|
|
34
|
-
|
38
|
+
{
|
39
|
+
<%= @employer_name %>
|
40
|
+
<% if @type_of_business %>
|
41
|
+
(<%= @type_of_business %>)
|
42
|
+
<% end %>
|
43
|
+
}
|
35
44
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
(<%= @type_of_business %>)
|
40
|
-
<% end %>
|
41
|
-
}
|
45
|
+
<% if @employer_address %>
|
46
|
+
{<%= @employer_address %>}
|
47
|
+
<% end %>
|
42
48
|
|
43
|
-
|
44
|
-
{<%= @employer_address %>}
|
45
|
-
<% end %>
|
49
|
+
<% end %>
|
46
50
|
|
47
|
-
|
51
|
+
{}
|
48
52
|
|
49
|
-
|
53
|
+
{
|
54
|
+
<% if @main_activities %>
|
50
55
|
|
51
|
-
|
52
|
-
|
56
|
+
<% unless @main_activities.is_a?(Array) %>
|
57
|
+
<% @main_activities = Array[@main_activities] %>
|
58
|
+
<% end %>
|
53
59
|
|
54
|
-
|
55
|
-
<% @main_activities = Array[@main_activities] %>
|
56
|
-
<% end %>
|
60
|
+
<% @main_activities.compact! %>
|
57
61
|
|
58
|
-
|
62
|
+
<% if @main_activities.length > 0 %>
|
59
63
|
|
60
|
-
|
64
|
+
\\textit{<%= @titles['S_3']['main_activities'] %>}:
|
65
|
+
\\begin{itemize}
|
61
66
|
|
62
|
-
|
63
|
-
|
67
|
+
<% @main_activities.each do |main_activity| %>
|
68
|
+
\\item <%= main_activity %>
|
69
|
+
<% end %>
|
64
70
|
|
65
|
-
|
66
|
-
\\item <%= main_activity %>
|
67
|
-
<% end %>
|
71
|
+
\\end{itemize}
|
68
72
|
|
69
|
-
|
73
|
+
<% end %>
|
70
74
|
|
71
|
-
|
75
|
+
<% end %>
|
76
|
+
}
|
72
77
|
|
73
|
-
|
74
|
-
}
|
78
|
+
CODE
|
75
79
|
|
76
|
-
|
80
|
+
evaluate(input, context).gsub(/^\s+/,'').gsub(/\n/,'') + "\n\n"
|
81
|
+
end
|
77
82
|
|
78
|
-
|
83
|
+
end
|
79
84
|
end
|
80
|
-
|
81
85
|
end
|
@@ -1,61 +1,65 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
input_file_name, input_dir, resources_pths, out_dir, log_file,
|
5
|
-
halt_on_error=true, shell_enabled=true, interpreter='xelatex', additional_args=[])
|
6
|
-
@interpreter = interpreter
|
7
|
-
@halt_on_error = !!halt_on_error
|
8
|
-
@shell_enabled = !!shell_enabled
|
9
|
-
@out_dir = out_dir
|
10
|
-
@input_file_name = input_file_name
|
11
|
-
@input_dir = input_dir
|
12
|
-
@resources_pths = resources_pths
|
13
|
-
@log_file = log_file
|
14
|
-
@additional_args = additional_args.is_a?(Array) ? additional_args : []
|
15
|
-
end
|
1
|
+
module CurriculumGenerator
|
2
|
+
module Util
|
3
|
+
class LatexToPdf
|
16
4
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
bind -> { gen_pdf_cmd.run }
|
31
|
-
bind -> { gen_pdf_cmd.run }
|
32
|
-
bind -> {
|
33
|
-
# ==> Cleanup resources files
|
34
|
-
dirty_files = resources_files - starting_resources
|
35
|
-
dirty_files.length > 0 ? system("rm #{dirty_files.join(' ')}") : false
|
36
|
-
}
|
37
|
-
end
|
38
|
-
end
|
5
|
+
def initialize(
|
6
|
+
input_file_name, input_dir, resources_pths, out_dir, log_file,
|
7
|
+
halt_on_error=true, shell_enabled=true, interpreter='xelatex', additional_args=[])
|
8
|
+
@interpreter = interpreter
|
9
|
+
@halt_on_error = !!halt_on_error
|
10
|
+
@shell_enabled = !!shell_enabled
|
11
|
+
@out_dir = out_dir
|
12
|
+
@input_file_name = input_file_name
|
13
|
+
@input_dir = input_dir
|
14
|
+
@resources_pths = resources_pths
|
15
|
+
@log_file = log_file
|
16
|
+
@additional_args = additional_args.is_a?(Array) ? additional_args : []
|
17
|
+
end
|
39
18
|
|
40
|
-
|
19
|
+
def generate
|
41
20
|
|
42
|
-
|
43
|
-
|
44
|
-
args << '-halt-on-error' if @halt_on_error # halt on error
|
45
|
-
args += %w(-shell-escape --enable-write18) if @shell_enabled # shell escape
|
46
|
-
args << "-output-directory=#{@out_dir}" # output directory
|
47
|
-
args += @additional_args # add the additional arguments to the computed ones
|
48
|
-
args << @input_file_name
|
21
|
+
# Store the starting resources for later cleanup
|
22
|
+
starting_resources = resources_files
|
49
23
|
|
50
|
-
|
51
|
-
|
24
|
+
# Create the command used to generate the PDF
|
25
|
+
gen_pdf_cmd = ShellCommand.new(get_tex_cmd, @input_dir, @log_file)
|
26
|
+
# Create the command used to generate the bibliography
|
27
|
+
gen_bib_cmd = ShellCommand.new(get_bibtex_cmd, @out_dir, @log_file)
|
52
28
|
|
53
|
-
|
54
|
-
|
55
|
-
|
29
|
+
Either.chain do
|
30
|
+
bind -> { gen_pdf_cmd.run }
|
31
|
+
bind -> { gen_bib_cmd.run }
|
32
|
+
bind -> { gen_pdf_cmd.run }
|
33
|
+
bind -> { gen_pdf_cmd.run }
|
34
|
+
bind -> {
|
35
|
+
# ==> Cleanup resources files
|
36
|
+
dirty_files = resources_files - starting_resources
|
37
|
+
dirty_files.length > 0 ? system("rm #{dirty_files.join(' ')}") : false
|
38
|
+
}
|
39
|
+
end
|
40
|
+
end
|
56
41
|
|
57
|
-
|
58
|
-
Dir.glob(@resources_pths)
|
59
|
-
end
|
42
|
+
protected
|
60
43
|
|
44
|
+
def get_tex_cmd
|
45
|
+
args = %w(-synctex=1 -interaction=batchmode) # default arguments
|
46
|
+
args << '-halt-on-error' if @halt_on_error # halt on error
|
47
|
+
args += %w(-shell-escape --enable-write18) if @shell_enabled # shell escape
|
48
|
+
args << "-output-directory=#{@out_dir}" # output directory
|
49
|
+
args += @additional_args # add the additional arguments to the computed ones
|
50
|
+
args << @input_file_name
|
51
|
+
|
52
|
+
"#{@interpreter} #{args.join(' ')}" # build the tex command and return it
|
53
|
+
end
|
54
|
+
|
55
|
+
def get_bibtex_cmd
|
56
|
+
"BIBINPUTS=\"#{@input_dir}\" " + "bibtex #{@input_file_name}" # build the bibtex command and return it
|
57
|
+
end
|
58
|
+
|
59
|
+
def resources_files
|
60
|
+
Dir.glob(@resources_pths)
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
61
65
|
end
|
@@ -1,27 +1,31 @@
|
|
1
|
-
module CurriculumGenerator
|
1
|
+
module CurriculumGenerator
|
2
|
+
module Util
|
3
|
+
class Logging
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
5
|
+
def self.log(name, opts={})
|
6
|
+
case name
|
7
|
+
when :fatal_error
|
8
|
+
puts "#{prefix} Fatal error: #{opts[:msg].light_black}. Aborting...".red
|
9
|
+
when :loading_curriculum_data
|
10
|
+
puts "#{prefix} Loading the curriculum data for ".cyan + opts[:trgt_lang].to_s.light_black
|
11
|
+
puts "#{indent} using ".cyan + opts[:master_lang].to_s.light_black + ' as the default'.cyan
|
12
|
+
when :executing_command
|
13
|
+
puts "#{prefix} Executing ".cyan + opts[:cmd].to_s.light_black
|
14
|
+
puts "#{indent} from the directory ".cyan + opts[:exec_dir].to_s.light_black if opts.has_key? :exec_dir
|
15
|
+
puts "#{indent} logging to ".cyan + opts[:log_file].to_s.light_black if opts.has_key? :log_file
|
16
|
+
else
|
17
|
+
# nothing to do
|
18
|
+
end
|
19
|
+
end
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
def self.prefix
|
22
|
+
">>"
|
23
|
+
end
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
|
25
|
+
def self.indent
|
26
|
+
" "
|
27
|
+
end
|
26
28
|
|
29
|
+
end
|
30
|
+
end
|
27
31
|
end
|
@@ -1,48 +1,52 @@
|
|
1
|
-
|
1
|
+
module CurriculumGenerator
|
2
|
+
module Util
|
3
|
+
class ShellCommand
|
4
|
+
|
5
|
+
def initialize(command, execution_dir, log_file=nil)
|
6
|
+
@command = command
|
7
|
+
@execution_dir = execution_dir
|
8
|
+
@log_file = log_file
|
9
|
+
end
|
2
10
|
|
3
|
-
|
4
|
-
|
5
|
-
@execution_dir = execution_dir
|
6
|
-
@log_file = log_file
|
7
|
-
end
|
11
|
+
def run
|
12
|
+
Logging.log(:executing_command, cmd: @command, exec_dir: @execution_dir, log_file: @log_file)
|
8
13
|
|
9
|
-
|
10
|
-
CurriculumGenerator::Util::Logging.log(:executing_command, cmd: @command, exec_dir: @execution_dir, log_file: @log_file)
|
14
|
+
status = true
|
11
15
|
|
12
|
-
|
16
|
+
Process.waitpid(
|
17
|
+
fork do
|
18
|
+
original_stdout, original_stderr = $stdout, $stderr
|
19
|
+
FileUtils.chdir @execution_dir do
|
20
|
+
File.open(@log_file, 'a') do |log_file|
|
21
|
+
$stderr = $stdout = log_file
|
22
|
+
system @command
|
23
|
+
$stdout, $stderr = original_stdout, original_stderr
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end)
|
13
27
|
|
14
|
-
|
15
|
-
|
16
|
-
original_stdout, original_stderr = $stdout, $stderr
|
17
|
-
FileUtils.chdir @execution_dir do
|
18
|
-
File.open(@log_file, 'a') do |log_file|
|
19
|
-
$stderr = $stdout = log_file
|
20
|
-
system @command
|
21
|
-
$stdout, $stderr = original_stdout, original_stderr
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end)
|
28
|
+
status # return
|
29
|
+
end
|
25
30
|
|
26
|
-
|
27
|
-
|
31
|
+
def self.exist?(command)
|
32
|
+
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
33
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
34
|
+
exts.collect do |ext|
|
35
|
+
exe = File.join(path, "#{command}#{ext}")
|
36
|
+
return true if File.executable? exe
|
37
|
+
end
|
38
|
+
end
|
39
|
+
false # return
|
40
|
+
end
|
28
41
|
|
29
|
-
|
30
|
-
|
31
|
-
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
32
|
-
exts.collect do |ext|
|
33
|
-
exe = File.join(path, "#{command}#{ext}")
|
34
|
-
return true if File.executable? exe
|
42
|
+
def exist?
|
43
|
+
self.class.exist? @command
|
35
44
|
end
|
36
|
-
end
|
37
|
-
false # return
|
38
|
-
end
|
39
45
|
|
40
|
-
|
41
|
-
|
42
|
-
|
46
|
+
def find_executable_part(command)
|
47
|
+
command.split(' ').first
|
48
|
+
end
|
43
49
|
|
44
|
-
|
45
|
-
command.split(' ').first
|
50
|
+
end
|
46
51
|
end
|
47
|
-
|
48
52
|
end
|