mo2tex 1.0.0
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/.rspec +3 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/LICENSE +674 -0
- data/README.md +29 -0
- data/Rakefile +8 -0
- data/config/courses.yml +165 -0
- data/config/templates/latex/body.tex.erb +5 -0
- data/config/templates/latex/header.tex +20 -0
- data/config/templates/latex/trailer.tex +1 -0
- data/config/templates/pic/body.pic.erb +14 -0
- data/config/templates/pic/header.pic +13 -0
- data/config/templates/pic/objects.pic +46 -0
- data/config/templates/pic/trailer.pic.erb +3 -0
- data/exe/m2c +16 -0
- data/exe/m2l +16 -0
- data/exe/m2p +16 -0
- data/lib/mo2tex/calendar.rb +54 -0
- data/lib/mo2tex/course.rb +198 -0
- data/lib/mo2tex/course_helper.rb +123 -0
- data/lib/mo2tex/datetime_helper.rb +29 -0
- data/lib/mo2tex/day_schedule.rb +135 -0
- data/lib/mo2tex/event.rb +77 -0
- data/lib/mo2tex/exceptions.rb +21 -0
- data/lib/mo2tex/exclude_date.rb +68 -0
- data/lib/mo2tex/exclusion_manager.rb +59 -0
- data/lib/mo2tex/extensions/date_time.rb +66 -0
- data/lib/mo2tex/latex.rb +66 -0
- data/lib/mo2tex/main.rb +60 -0
- data/lib/mo2tex/pic.rb +315 -0
- data/lib/mo2tex/school.rb +68 -0
- data/lib/mo2tex/version.rb +5 -0
- data/lib/mo2tex.rb +31 -0
- data/sig/mo2tex.rbs +4 -0
- data/tmp/.gitkeep +1 -0
- metadata +136 -0
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# `mo2tex` - A pure `ruby` monteore-to-`latex` table generator
|
2
|
+
|
3
|
+
](https://gitlab.com/SMELAT/mo2tex/badges/master/pipeline.svg)
|
4
|
+
|
5
|
+
`mo2tex` is a pure `ruby` monteore-to-`latex` table generator
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Install the gem and add to the application's Gemfile by executing:
|
10
|
+
|
11
|
+
$ bundle add mo2tex
|
12
|
+
|
13
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
14
|
+
|
15
|
+
$ gem install mo2tex
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
TODO: Write usage instructions here
|
20
|
+
|
21
|
+
## Development
|
22
|
+
|
23
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
24
|
+
|
25
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
26
|
+
|
27
|
+
## Contributing
|
28
|
+
|
29
|
+
Bug reports and pull requests are welcome on Gitlab at https://gitlab.com/SMELAT/mo2tex.
|
data/Rakefile
ADDED
data/config/courses.yml
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
calendar:
|
2
|
+
start_date: 20241104
|
3
|
+
end_date: 20251031
|
4
|
+
exclude: [ 20241221-20250106, 20250220-20250301, 20250417-20250422, 20250425, 20250501, 20250602, 20250625-20251011 ]
|
5
|
+
file: Bernardini-A.A.2024-2025.ics
|
6
|
+
day_schedule:
|
7
|
+
lunedì:
|
8
|
+
orario:
|
9
|
+
- '9:00'
|
10
|
+
- '15:00'
|
11
|
+
pausa:
|
12
|
+
- '13:30'
|
13
|
+
- '14:00'
|
14
|
+
martedì:
|
15
|
+
orario:
|
16
|
+
- '9:00'
|
17
|
+
- '17:00'
|
18
|
+
pausa:
|
19
|
+
- '12:00'
|
20
|
+
- '13:00'
|
21
|
+
|
22
|
+
courses:
|
23
|
+
Bernardini_-_Composizione_Musicale_Elettroacustica_TR_I:
|
24
|
+
studenti: Timpone, Valle
|
25
|
+
ore: 30
|
26
|
+
tipologia: individuale
|
27
|
+
tip_effettiva: individuale
|
28
|
+
inizio: 20241104
|
29
|
+
frequenza: settimanale
|
30
|
+
giorno: lunedì
|
31
|
+
orario: 9:00
|
32
|
+
durata_lezione: 1:30
|
33
|
+
aula: 18s
|
34
|
+
online: [ 20241125 ]
|
35
|
+
|
36
|
+
Bernardini_-_Composizione_Musicale_Elettroacustica_TR_II:
|
37
|
+
studenti: Freddoneve, De Paolis
|
38
|
+
ore: 30
|
39
|
+
tipologia: individuale
|
40
|
+
tip_effettiva: individuale
|
41
|
+
inizio: 20241104
|
42
|
+
frequenza: settimanale
|
43
|
+
giorno: lunedì
|
44
|
+
orario: 10:30
|
45
|
+
durata_lezione: 1:30
|
46
|
+
aula: 18s
|
47
|
+
online: [ 20241125 ]
|
48
|
+
|
49
|
+
Bernardini_-_Composizione_Musicale_Elettroacustica_TR_III_A:
|
50
|
+
studenti: Diaz, Erdi
|
51
|
+
studenti_fc: Corsi
|
52
|
+
ore: 30
|
53
|
+
tipologia: individuale
|
54
|
+
tip_effettiva: individuale
|
55
|
+
inizio: 20241104
|
56
|
+
frequenza: settimanale
|
57
|
+
giorno: lunedì
|
58
|
+
orario: 12:00
|
59
|
+
durata_lezione: 1:30
|
60
|
+
aula: 18s
|
61
|
+
online: [ 20241125 ]
|
62
|
+
|
63
|
+
Bernardini_-_Composizione_Musicale_Elettroacustica_TR_III_B:
|
64
|
+
studenti: Pellegrino, Cutini, De Caro
|
65
|
+
ore: 30
|
66
|
+
tipologia: individuale
|
67
|
+
tip_effettiva: collettiva
|
68
|
+
inizio: 20241112
|
69
|
+
frequenza: quindicinale
|
70
|
+
giorno: martedì
|
71
|
+
orario: 15:00
|
72
|
+
durata_lezione: 2:00
|
73
|
+
aula: ottofonia
|
74
|
+
online: [ 20241126 ]
|
75
|
+
|
76
|
+
Bernardini_-_Composizione_Musicale_Informatica_TR_I_TS:
|
77
|
+
studenti: Noto, Varone, Mauti, Savastano, Vona, Cannuciari
|
78
|
+
ore: 20
|
79
|
+
tipologia: collettiva
|
80
|
+
tip_effettiva: collettiva
|
81
|
+
inizio: 20241104
|
82
|
+
frequenza: settimanale
|
83
|
+
giorno: lunedì
|
84
|
+
orario: 14:00
|
85
|
+
durata_lezione: 1:30
|
86
|
+
aula: 18s
|
87
|
+
online: [ 20241125 ]
|
88
|
+
|
89
|
+
Bernardini_-_Composizione_Musicale_Informatica_TR_II_TS:
|
90
|
+
studenti: Chierici, Rossi
|
91
|
+
ore: 20
|
92
|
+
tipologia: collettiva
|
93
|
+
tip_effettiva: collettiva
|
94
|
+
inizio: 20241105
|
95
|
+
frequenza: settimanale
|
96
|
+
giorno: martedì
|
97
|
+
orario: 9:00
|
98
|
+
durata_lezione: 1:00
|
99
|
+
aula: ottofonia
|
100
|
+
online: [ 20241126 ]
|
101
|
+
|
102
|
+
Bernardini_-_Composizione_Audiovisiva_Integrata_TR_I_A_MA:
|
103
|
+
studenti: Di Girolamo, Bonfè, Bongiovanni
|
104
|
+
ore: 30
|
105
|
+
tipologia: individuale
|
106
|
+
tip_effettiva: collettiva
|
107
|
+
inizio: 20241105
|
108
|
+
frequenza: settimanale
|
109
|
+
giorno: martedì
|
110
|
+
orario: 13:00
|
111
|
+
durata_lezione: 2:00
|
112
|
+
aula: ottofonia
|
113
|
+
online: [ 20241126 ]
|
114
|
+
|
115
|
+
Bernardini_-_Composizione_Audiovisiva_Integrata_TR_I_B_MA:
|
116
|
+
studenti: Becherucci, Filippi, Barbarossa
|
117
|
+
ore: 30
|
118
|
+
tipologia: individuale
|
119
|
+
tip_effettiva: collettiva
|
120
|
+
inizio: 20250318
|
121
|
+
frequenza: settimanale
|
122
|
+
giorno: martedì
|
123
|
+
orario: 13:00
|
124
|
+
durata_lezione: 2:00
|
125
|
+
aula: ottofonia
|
126
|
+
online: [ 20241126 ]
|
127
|
+
|
128
|
+
Bernardini_-_Composizione_Musicale_Elettroacustica_BN_II_ME:
|
129
|
+
studenti: Ferracuti
|
130
|
+
ore: 20
|
131
|
+
tipologia: individuale
|
132
|
+
tip_effettiva: individuale
|
133
|
+
inizio: 20241105
|
134
|
+
frequenza: settimanale
|
135
|
+
giorno: martedì
|
136
|
+
orario: 10:00
|
137
|
+
durata_lezione: 1:00
|
138
|
+
aula: ottofonia
|
139
|
+
online: [ 20241126 ]
|
140
|
+
|
141
|
+
Bernardini_-_Composizione_Audiovisiva_Integrata_BN_II_ME:
|
142
|
+
studenti: Ferracuti
|
143
|
+
ore: 20
|
144
|
+
tipologia: individuale
|
145
|
+
tip_effettiva: individuale
|
146
|
+
inizio: 20250318
|
147
|
+
frequenza: settimanale
|
148
|
+
giorno: martedì
|
149
|
+
orario: 10:00
|
150
|
+
durata_lezione: 1:00
|
151
|
+
aula: ottofonia
|
152
|
+
online: [ 20241126 ]
|
153
|
+
|
154
|
+
Bernardini_-_Composizione_Audiovisiva_Integrata_BN_I_MA:
|
155
|
+
studenti: Rossi Minelli
|
156
|
+
ore: 20
|
157
|
+
tipologia: individuale
|
158
|
+
tip_effettiva: individuale
|
159
|
+
inizio: 20241105
|
160
|
+
frequenza: settimanale
|
161
|
+
giorno: martedì
|
162
|
+
orario: 11:00
|
163
|
+
durata_lezione: 1:00
|
164
|
+
aula: ottofonia
|
165
|
+
online: [ 20241126 ]
|
@@ -0,0 +1,20 @@
|
|
1
|
+
\documentclass[10pt]{scrartcl}
|
2
|
+
\usepackage[italian]{babel}
|
3
|
+
\usepackage[margin=1cm]{geometry}
|
4
|
+
\usepackage{longtable}
|
5
|
+
\usepackage{needspace}
|
6
|
+
\usepackage{xspace}
|
7
|
+
|
8
|
+
\newcommand{\AAcc}{A.A. 2024--2025\xspace}
|
9
|
+
|
10
|
+
\title{Conservatorio ``Ottorino Respighi'' Latina\\%
|
11
|
+
Scuola di Musica Elettronica\\%
|
12
|
+
\AAcc\\%
|
13
|
+
Docente: Nicola Bernardini\\%
|
14
|
+
Orari delle lezioni}
|
15
|
+
|
16
|
+
\date{~}
|
17
|
+
|
18
|
+
\begin{document}
|
19
|
+
|
20
|
+
\maketitle
|
@@ -0,0 +1 @@
|
|
1
|
+
\end{document}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
.PS
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
#
|
5
|
+
# Page n.<%= page.number %>
|
6
|
+
#
|
7
|
+
page_frame(<%= page.number -%>)
|
8
|
+
<% page.containers.each do |cont| -%>
|
9
|
+
container(<%= cont.number %>, <%= cont.location_tag %>, "\s[-2]\fB<%= cont.wdate %>\fP\s0")
|
10
|
+
<% cont.slots.each do |ev| -%>
|
11
|
+
event(<%= ev.number %>, <%= ev.location_tag %>, "\s[-3]<%= ev.pic_time %>\s0", <%= ev.pic_dur %>, "\s[-2]\fB<%= ev.pic_title %>\fP\s0", <%= ev.color %>)
|
12
|
+
<% end %>
|
13
|
+
<% end %>
|
14
|
+
.PE
|
@@ -0,0 +1,46 @@
|
|
1
|
+
.PS
|
2
|
+
#
|
3
|
+
# page frame:
|
4
|
+
#
|
5
|
+
# +page_frame(npage)+
|
6
|
+
#
|
7
|
+
# creates a page where to insert containers
|
8
|
+
#
|
9
|
+
framewid = textwid
|
10
|
+
frameht = textht
|
11
|
+
define page_frame {
|
12
|
+
PageFrame$1: box invis wid framewid ht frameht
|
13
|
+
}
|
14
|
+
#
|
15
|
+
# main container:
|
16
|
+
#
|
17
|
+
# +container(container_number, placement, daystring)+
|
18
|
+
#
|
19
|
+
# will produce a Container<container_number> box where to put each day
|
20
|
+
#
|
21
|
+
containerht = frameht/4
|
22
|
+
containerwid = framewid/4
|
23
|
+
subcontainerwid = containerwid*0.65
|
24
|
+
subcontainerht = containerht*0.93
|
25
|
+
define container {
|
26
|
+
Container$1: box wid containerwid ht containerht with .nw at $2
|
27
|
+
Subcontainer$1: box wid subcontainerwid ht subcontainerht with .se at Container$1.se
|
28
|
+
line invis from Container$1.nw to Container$1.ne $3 below
|
29
|
+
}
|
30
|
+
#
|
31
|
+
# event:
|
32
|
+
#
|
33
|
+
# +event(event_number, placement, time, dur, title, color)+
|
34
|
+
#
|
35
|
+
# will produce a Event<event_number> box where to put the weeks
|
36
|
+
#
|
37
|
+
totdaydur = 8
|
38
|
+
dayoffset = 9
|
39
|
+
define event {
|
40
|
+
event_ht = (subcontainerht/totdaydur)*$4
|
41
|
+
Event$1: box wid subcontainerwid ht event_ht with .nw at $2 $5 shaded $6
|
42
|
+
tag_wid = containerwid - subcontainerwid
|
43
|
+
Ttag$1: box invis wid tag_wid ht event_ht with .e at Event$1.w
|
44
|
+
line invis from Ttag$1.nw to Ttag$1.ne $3 below
|
45
|
+
}
|
46
|
+
.PE
|
data/exe/m2c
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
version = '1.0.0'
|
4
|
+
ourlib = File.join(ENV['HOME'], '.rvm', 'gems', 'ruby-3.4.0-preview1@mo2tex', 'gems', "mo2tex-#{version}", 'lib')
|
5
|
+
$:<< File.join('.', 'lib')
|
6
|
+
$:<< ourlib
|
7
|
+
require 'mo2tex'
|
8
|
+
|
9
|
+
begin
|
10
|
+
puts(Mo2tex::m2ical(ARGV))
|
11
|
+
rescue ArgumentError => msg
|
12
|
+
STDERR.puts(msg)
|
13
|
+
exit(-1)
|
14
|
+
end
|
15
|
+
|
16
|
+
exit(0)
|
data/exe/m2l
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
version = '1.0.0'
|
4
|
+
ourlib = File.join(ENV['HOME'], '.rvm', 'gems', 'ruby-3.4.0-preview1@mo2tex', 'gems', "mo2tex-#{version}", 'lib')
|
5
|
+
$:<< File.join('.', 'lib')
|
6
|
+
$:<< ourlib
|
7
|
+
require 'mo2tex'
|
8
|
+
|
9
|
+
begin
|
10
|
+
puts(Mo2tex::m2latex(ARGV))
|
11
|
+
rescue ArgumentError => msg
|
12
|
+
STDERR.puts(msg)
|
13
|
+
exit(-1)
|
14
|
+
end
|
15
|
+
|
16
|
+
exit(0)
|
data/exe/m2p
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
version = '1.0.0'
|
4
|
+
ourlib = File.join(ENV['HOME'], '.rvm', 'gems', 'ruby-3.4.0-preview1@mo2tex', 'gems', "mo2tex-#{version}", 'lib')
|
5
|
+
$:<< File.join('.', 'lib')
|
6
|
+
$:<< ourlib
|
7
|
+
require 'mo2tex'
|
8
|
+
|
9
|
+
begin
|
10
|
+
puts(Mo2tex::m2pic(ARGV))
|
11
|
+
rescue ArgumentError => msg
|
12
|
+
STDERR.puts(msg)
|
13
|
+
exit(-1)
|
14
|
+
end
|
15
|
+
|
16
|
+
exit(0)
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'date'
|
5
|
+
require 'icalendar'
|
6
|
+
|
7
|
+
module Mo2tex
|
8
|
+
|
9
|
+
class Calendar
|
10
|
+
|
11
|
+
attr_reader :filename, :start_date, :end_date, :exclude, :events, :day_schedule_templates
|
12
|
+
|
13
|
+
class UnknownEvent < Error; end
|
14
|
+
|
15
|
+
def initialize(config)
|
16
|
+
@filename = config['file']
|
17
|
+
@start_date = DateTime.parse(config['start_date'].to_s)
|
18
|
+
@end_date = DateTime.parse(config['end_date'].to_s)
|
19
|
+
@exclude = ExclusionManager.new(config['exclude'], self.start_date, self.end_date)
|
20
|
+
@day_schedule_templates = parse_day_schedule_templates(config['day_schedule'])
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_icalendar(school)
|
24
|
+
ical = Icalendar::Calendar.new
|
25
|
+
school.courses.each do
|
26
|
+
|title, course|
|
27
|
+
course.events.each do
|
28
|
+
|ev|
|
29
|
+
ev.to_ical(ical)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
return ical.publish
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_pic_schedule(school)
|
36
|
+
pic = Pic.new(school)
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_file(school, fname = nil)
|
40
|
+
fname ||= self.filename
|
41
|
+
ical = self.create_icalendar(school)
|
42
|
+
File.open(fname, 'w') { |fh| fh.puts(ical.to_ical) }
|
43
|
+
return fname
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def parse_day_schedule_templates(conf)
|
49
|
+
return conf
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
module Mo2tex
|
6
|
+
|
7
|
+
class Course
|
8
|
+
|
9
|
+
include CourseHelper
|
10
|
+
|
11
|
+
attr :title, :hours, :type, :real_type, :students, :students_fc,
|
12
|
+
:start, :freq, :wday, :dur, :when, :events, :excl_mgr, :warnings,
|
13
|
+
:hours_done, :where, :online
|
14
|
+
|
15
|
+
def initialize(title, desc, exmgr)
|
16
|
+
@warnings = {}
|
17
|
+
@hours_done = 0
|
18
|
+
@excl_mgr = exmgr
|
19
|
+
self.excl_mgr << desc['exclude'] if desc.has_key?('exclude')
|
20
|
+
@title = normalize_title(title)
|
21
|
+
@hours = desc['ore']
|
22
|
+
@type = desc['tipologia']
|
23
|
+
@real_type = desc['tip_effettiva']
|
24
|
+
@students = desc['studenti']
|
25
|
+
@students_fc = desc['studenti_fc']
|
26
|
+
@start = DateTime.parse(desc['inizio'].to_s)
|
27
|
+
@freq = parse_frequency(desc['frequenza'])
|
28
|
+
@wday = desc['giorno']
|
29
|
+
@dur = parse_dur(desc['durata_lezione']) # beware! YAML converts in seconds!
|
30
|
+
@when = parse_dur(desc['orario']) # beware! YAML converts in seconds!
|
31
|
+
@where = 'aula ' + desc['aula']
|
32
|
+
@online = desc['online']
|
33
|
+
@events = generate_events
|
34
|
+
end
|
35
|
+
|
36
|
+
def generate(&block)
|
37
|
+
result = ''
|
38
|
+
self.events.each do
|
39
|
+
|ev|
|
40
|
+
result += yield(self.title, self.number_of_lessons, ev)
|
41
|
+
end
|
42
|
+
return result
|
43
|
+
end
|
44
|
+
|
45
|
+
def course_dur_in_seconds
|
46
|
+
return self.academic_hours * 3600
|
47
|
+
end
|
48
|
+
|
49
|
+
def lesson_dur_in_seconds
|
50
|
+
return ((self.dur * 24)*3600).round.to_i
|
51
|
+
end
|
52
|
+
|
53
|
+
def number_of_lessons
|
54
|
+
result = (self.course_dur_in_seconds.to_f / self.lesson_dur_in_seconds.to_f).round.to_i
|
55
|
+
return result
|
56
|
+
end
|
57
|
+
|
58
|
+
class <<self
|
59
|
+
|
60
|
+
def create(title, desc, exm)
|
61
|
+
result = nil
|
62
|
+
case desc['tip_effettiva']
|
63
|
+
when 'collettiva'
|
64
|
+
result = CollectiveCourse.new(title, desc, exm)
|
65
|
+
when 'individuale'
|
66
|
+
result = IndividualCourse.new(title, desc, exm)
|
67
|
+
else
|
68
|
+
raise UnknownCourseType, "Unknown type #{desc['tipologia']}"
|
69
|
+
end
|
70
|
+
return result
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
def num_students
|
76
|
+
split_studs = self.students.split(/, */)
|
77
|
+
return split_studs.size
|
78
|
+
end
|
79
|
+
|
80
|
+
def total_hours
|
81
|
+
raise PureVirtualMethodCalled, 'Course#total_hours'
|
82
|
+
end
|
83
|
+
|
84
|
+
def academic_hours
|
85
|
+
return self.total_hours
|
86
|
+
end
|
87
|
+
|
88
|
+
def all_students
|
89
|
+
return self.students + ' ' + self.students_fc
|
90
|
+
end
|
91
|
+
|
92
|
+
def hours_done_per_lesson(dts, dte)
|
93
|
+
raise PureVirtualMethodCalled, 'Course#hours_done_per_lesson'
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def latex_title
|
99
|
+
return "\\multicolumn{3}{\\bfseries #{self.title}}\\\\\n"
|
100
|
+
end
|
101
|
+
|
102
|
+
def parse_frequency(f)
|
103
|
+
result = nil
|
104
|
+
case f
|
105
|
+
when 'settimanale'
|
106
|
+
result = 7
|
107
|
+
when 'quindicinale'
|
108
|
+
result = 14
|
109
|
+
else
|
110
|
+
raise UnknownCourseFrequency, f
|
111
|
+
end
|
112
|
+
return result
|
113
|
+
end
|
114
|
+
|
115
|
+
#
|
116
|
+
# +parse_dur(d)+
|
117
|
+
#
|
118
|
+
# the argument is a number converted in seconds (usually, directly by YAML)
|
119
|
+
# so, in order to get it palatable to DateTime, we reconvert it in fraction of days.
|
120
|
+
#
|
121
|
+
def parse_dur(d)
|
122
|
+
frac_hours = d.to_f/3600.0
|
123
|
+
result = (frac_hours/24.0).to_r
|
124
|
+
return result
|
125
|
+
end
|
126
|
+
|
127
|
+
def generate_events
|
128
|
+
result = []
|
129
|
+
tot_nlessons = self.number_of_lessons
|
130
|
+
current_date = self.start
|
131
|
+
nless = 1
|
132
|
+
while (nless <= tot_nlessons) do
|
133
|
+
if self.excl_mgr.skip?(current_date)
|
134
|
+
current_date += self.freq
|
135
|
+
break if self.excl_mgr.out_of_range?(current_date)
|
136
|
+
next
|
137
|
+
end
|
138
|
+
lesson_start = calc_lesson_start(current_date)
|
139
|
+
lesson_end = calc_lesson_end(current_date)
|
140
|
+
result << Event.new(lesson_start, lesson_end, nless, tot_nlessons, self.title, self.students, self.where, self.online)
|
141
|
+
current_date += self.freq
|
142
|
+
raise WrongWeekDay, "#{current_date.to_it_wday} != #{self.wday} for course \"#{self.title}\"" unless current_date.wday == DateTime.from_it_wday(self.wday)
|
143
|
+
nless += 1
|
144
|
+
@hours_done += self.hours_done_per_lesson(lesson_start, lesson_end) # hours spent teaching
|
145
|
+
end
|
146
|
+
raise EventsNotGenerated, "no events generated for course \"#{self.title}\" (#{self.type})" unless result && !result.empty?
|
147
|
+
self. warnings[:not_enough_lessons] = "n.lessons(#{result.size}) != expected number of lessons(#{self.number_of_lessons}) for course \"#{self.title}\" (#{self.type})" unless result.size == self.number_of_lessons
|
148
|
+
return result
|
149
|
+
end
|
150
|
+
|
151
|
+
def calc_lesson_start(dt)
|
152
|
+
return calc_time(dt, mceil(self.when))
|
153
|
+
end
|
154
|
+
|
155
|
+
def calc_lesson_end(dt)
|
156
|
+
return calc_time(dt, mceil(self.when) + mceil(self.dur))
|
157
|
+
end
|
158
|
+
|
159
|
+
def calc_time(dt, t)
|
160
|
+
return dt + t
|
161
|
+
end
|
162
|
+
|
163
|
+
def mceil(n, prec = 10000)
|
164
|
+
return ((n.to_f*prec.to_f).ceil/prec.to_f)
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
class CollectiveCourse < Course
|
170
|
+
|
171
|
+
def total_hours
|
172
|
+
return self.hours
|
173
|
+
end
|
174
|
+
|
175
|
+
def hours_done_per_lesson(dts, dte)
|
176
|
+
return (dte - dts).to_f * 24.0
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
class IndividualCourse < Course
|
182
|
+
|
183
|
+
def total_hours
|
184
|
+
return self.hours * self.num_students
|
185
|
+
end
|
186
|
+
|
187
|
+
def academic_hours
|
188
|
+
return (self.total_hours * 0.75)
|
189
|
+
end
|
190
|
+
|
191
|
+
def hours_done_per_lesson(dts, dte)
|
192
|
+
return ((dte - dts).to_f/0.75) * 24.0
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|