-
Notifications
You must be signed in to change notification settings - Fork 0
/
generateExercise
executable file
·257 lines (215 loc) · 5.59 KB
/
generateExercise
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
#!/bin/bash
make > /dev/null
binDir=./bin
clefArg="$1"
seedArg="$2"
pagesArg="$3"
sizeArg="$4"
readWriteArg="$5"
realNotes=""
fakeNotes=""
clefNotes=""
function syntax() {
echo "Syntax: $0 --help"
echo " Prints this help"
echo ""
echo "Syntax: $0 [bass|treble|grandstaff|grand] [id] [nPages] [size] [write|read]"
echo "Optional arguments:"
echo " First argument: defines the clef (treble is the default)"
echo " Second argument: [id] is used to reproduce an exercise. Set to 0 to generate a random one"
echo " Third argument: [nPages] tells how many pages of exercise to generate"
echo " Fourth argument: [size] can be wither 'big' or 'small' default is 'big'"
echo " Fifth argument: defines whether it's a reading or writing exercise."
echo " Writing exercise is the default"
}
# Clef definition
function setClef() {
myClefArg="$1"
if [ "$myClefArg" == "treble" ] ; then
realNotes="notes_treble"
fakeNotes="fake_treble"
clefNotes="treble"
elif [ "$myClefArg" == "bass" ] ; then
realNotes="notes_bass"
fakeNotes="fake_bass"
clefNotes="bass"
else
echo "Unknown clef: '$myClefArg'"
syntax
return -1
fi
return 0
}
#
## lilypond-generating functions
#
# Header of .ly file
function generateHeader() {
cat << @EOF
% Default layout:
\version "2.20.0"
\pointAndClickOff
\header {
tagline = ""
}
\layout {
indent = #0
line-width = #180
#(layout-set-staff-size $staff_size)
}
\paper {
%bottom-margin = 1\cm
last-bottom-spacing.basic-distance = #14
oddHeaderMarkup = ""
evenHeaderMarkup = ""
oddFooterMarkup = \markup {
\fill-line {
"Exercise $text_seed" \line {"Page" \fromproperty #'page:page-number-string }
}
}
evenFooterMarkup = \oddFooterMarkup
}
@EOF
}
# A single staff
function generateStaff() {
# Exercise needs aways the same note, so we generate fake ones
# Whereas solutions need "real" notes
whichOne="$1"
if [ "$whichOne" == "writeExercise" ] ; then
whichNotes="$fakeNotes"
hideNotes="\\hide NoteHead"
elif [ "$whichOne" == "readExercise" ] ; then
whichNotes="$realNotes"
hideNotes=""
else
echo "Error: unknown staff type: '$whichOne'"
exit -1
fi
cat << @EOF
\new Staff \with { \omit TimeSignature } \new Voice = melody {
\clef "$clefNotes"
\hide KeySignature
\hide Stem
\time ${notesPerLine}/4
$hideNotes
@EOF
${binDir}/generaNote $numeroNote $num_seed 2 $whichNotes $notesPerLine
echo '}'
}
# The lyrics (note names)
function generateLyrics() {
testo=`${binDir}/generaNote $numeroNote $num_seed 2 name 0`
cat >> $test_ly_name << @EOF
\new Lyrics \lyricsto melody {
\override LyricText.font-name = #"Source Serif Pro"
\override LyricText.font-size = #-2
$testo
}
@EOF
}
#
# Parsing arguments
#
# Clef argument
# First argument could be also --help
if [ "$clefArg" == "--help" ] ; then
syntax
exit 0
fi
# Otherwise the default clef is 'treble'. Of course it is
[ "$clefArg" == "" ] && clefArg="treble"
[ "$clefArg" == "grand" ] && clefArg="grandstaff"
if [ "$clefArg" == "grandstaff" ] ; then
setClef "treble"
else
setClef "$clefArg" || exit -1
fi
# Seed (key or id) argument
if [ "$seedArg" == "" ] || [ "$seedArg" == "0" ] ; then
seed=`date +%s%N`
text_seed=`${binDir}/timeToKey encode $seed`
else
text_seed="$seedArg"
fi
# Number of pages
nPages=$(($pagesArg))
[ "$nPages" == "0" ] && nPages=1
# Size
if [ "$sizeArg" == "small" ]; then
size="small"
elif [ "$sizeArg" == "" ] || [ "$sizeArg" == "big" ]; then
size="big"
else
echo "Error: unknown size selection argument: '$sizeArg'"
exit -1
fi
# Read/write selection
if [ "$readWriteArg" == "read" ] ; then
whichExercise="readExercise"
elif [ "$readWriteArg" == "" ] || [ "$readWriteArg" == "write" ] ; then
whichExercise="writeExercise"
else
echo "Error: unknown read/write selection argument: '$readWriteArg'"
exit -1
fi
num_seed=`${binDir}/timeToKey decode $text_seed`
test_ly_name="test_$text_seed.ly"
test_pdf_name="$whichExercise"
if [ "$size" == "big" ] ; then
notesPerLine=10
staff_size=26
# for the solution it would be staff_size=18
else
notesPerLine=16
staff_size=20
# for the solution it would be staff_size=14
fi
if [ "$clefArg" == "grandstaff" ] ; then
if [ "$size" == "big" ] ; then
numberOfLines=7
else
numberOfLines=8
fi
else
numberOfLines=13
fi
numeroNote=$((notesPerLine*numberOfLines*nPages))
# echo number of pages is $nPages
# echo notes per line is $notesPerLine
# echo number of line per page is $numberOfLines
# echo total number of lines is $((numberOfLines*nPages))
# echo generating $numeroNote notes
# Let's start to generate the actual
# lilypond file
generateHeader > $test_ly_name
# If grandstaff we need to open it
if [ "$clefArg" == "grandstaff" ] ; then
echo "\\new GrandStaff" >> $test_ly_name
fi
# We open a system anyway
echo "<<" >> $test_ly_name
# Then the first staff
generateStaff "$whichExercise" >> $test_ly_name
# Then the "lyrics" (if it's a writing exercise)
if [ "$whichExercise" == "writeExercise" ] ; then
generateLyrics >> $test_ly_name
fi
# If grandstaff we need the bass line too
if [ "$clefArg" == "grandstaff" ] ; then
setClef "bass"
generateStaff "$whichExercise" >> $test_ly_name
fi
# Then we close everything
cat >> $test_ly_name << @EOF
>>
@EOF
lilypond -o "$test_pdf_name" "$test_ly_name" 2>/dev/null && good=yes || good=no
if [ "$good" == "no" ]; then
echo Error: there was some problem with lilypond
echo You can try debugging by running the following command
echo lilypond -o \""$test_pdf_name"\" \""$test_ly_name"\"
else
rm -f "$test_ly_name"
which evince > /dev/null && evince "$test_pdf_name.pdf" &
fi