tmis 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +674 -0
  3. data/README.md +44 -0
  4. data/Rakefile +64 -0
  5. data/bin/tmis +4 -0
  6. data/lib/tmis/engine/database.rb +58 -0
  7. data/lib/tmis/engine/export/timetable_exporter.rb +366 -0
  8. data/lib/tmis/engine/import/abstract_spreadsheet.rb +53 -0
  9. data/lib/tmis/engine/import/spreadsheet_roo.rb +136 -0
  10. data/lib/tmis/engine/import/timetable_manager.rb +110 -0
  11. data/lib/tmis/engine/import/timetable_reader.rb +79 -0
  12. data/lib/tmis/engine/mailer/mailer.rb +51 -0
  13. data/lib/tmis/engine/migrations/10_create_speciality_subjects.rb +17 -0
  14. data/lib/tmis/engine/migrations/11_create_emails.rb +10 -0
  15. data/lib/tmis/engine/migrations/12_add_indexes.rb +32 -0
  16. data/lib/tmis/engine/migrations/1_create_groups.rb +11 -0
  17. data/lib/tmis/engine/migrations/2_create_subgroups.rb +10 -0
  18. data/lib/tmis/engine/migrations/3_create_subjects.rb +11 -0
  19. data/lib/tmis/engine/migrations/4_create_cabinets.rb +12 -0
  20. data/lib/tmis/engine/migrations/5_create_lecturers.rb +14 -0
  21. data/lib/tmis/engine/migrations/6_create_studies.rb +15 -0
  22. data/lib/tmis/engine/migrations/7_create_courses.rb +9 -0
  23. data/lib/tmis/engine/migrations/8_create_specialities.rb +9 -0
  24. data/lib/tmis/engine/migrations/9_create_semesters.rb +10 -0
  25. data/lib/tmis/engine/models/cabinet.rb +18 -0
  26. data/lib/tmis/engine/models/course.rb +11 -0
  27. data/lib/tmis/engine/models/email.rb +19 -0
  28. data/lib/tmis/engine/models/group.rb +31 -0
  29. data/lib/tmis/engine/models/lecturer.rb +45 -0
  30. data/lib/tmis/engine/models/semester.rb +4 -0
  31. data/lib/tmis/engine/models/speciality.rb +3 -0
  32. data/lib/tmis/engine/models/speciality_subject.rb +6 -0
  33. data/lib/tmis/engine/models/study.rb +56 -0
  34. data/lib/tmis/engine/models/subgroup.rb +21 -0
  35. data/lib/tmis/engine/models/subject.rb +19 -0
  36. data/lib/tmis/engine/verificator.rb +96 -0
  37. data/lib/tmis/interface/forms/about.rb +24 -0
  38. data/lib/tmis/interface/forms/console.rb +28 -0
  39. data/lib/tmis/interface/forms/debug_console.rb +32 -0
  40. data/lib/tmis/interface/forms/edit_study.rb +110 -0
  41. data/lib/tmis/interface/forms/expand_changes.rb +128 -0
  42. data/lib/tmis/interface/forms/export_general_timetable.rb +68 -0
  43. data/lib/tmis/interface/forms/export_group_timetable.rb +158 -0
  44. data/lib/tmis/interface/forms/export_lecturer_timetable.rb +171 -0
  45. data/lib/tmis/interface/forms/find.rb +71 -0
  46. data/lib/tmis/interface/forms/import.rb +36 -0
  47. data/lib/tmis/interface/forms/settings.rb +125 -0
  48. data/lib/tmis/interface/forms/ui_about.rb +88 -0
  49. data/lib/tmis/interface/forms/ui_console.rb +68 -0
  50. data/lib/tmis/interface/forms/ui_debug_console.rb +82 -0
  51. data/lib/tmis/interface/forms/ui_edit_study.rb +202 -0
  52. data/lib/tmis/interface/forms/ui_expand_changes.rb +134 -0
  53. data/lib/tmis/interface/forms/ui_export_general_timetable.rb +142 -0
  54. data/lib/tmis/interface/forms/ui_export_group_timetable.rb +160 -0
  55. data/lib/tmis/interface/forms/ui_export_lecturer_timetable.rb +160 -0
  56. data/lib/tmis/interface/forms/ui_find.rb +77 -0
  57. data/lib/tmis/interface/forms/ui_import.rb +134 -0
  58. data/lib/tmis/interface/forms/ui_settings.rb +417 -0
  59. data/lib/tmis/interface/mainwindow.rb +933 -0
  60. data/lib/tmis/interface/models/cabinet_table_model.rb +133 -0
  61. data/lib/tmis/interface/models/course_table_model.rb +87 -0
  62. data/lib/tmis/interface/models/group_table_model.rb +190 -0
  63. data/lib/tmis/interface/models/lecturer_table_model.rb +111 -0
  64. data/lib/tmis/interface/models/semester_table_model.rb +137 -0
  65. data/lib/tmis/interface/models/speciality_subject_table_model.rb +288 -0
  66. data/lib/tmis/interface/models/speciality_table_model.rb +87 -0
  67. data/lib/tmis/interface/models/study_table_model.rb +323 -0
  68. data/lib/tmis/interface/models/subgroup_table_model.rb +136 -0
  69. data/lib/tmis/interface/models/subject_table_model.rb +90 -0
  70. data/lib/tmis/interface/ui_mainwindow.rb +928 -0
  71. data/lib/tmis.rb +45 -0
  72. data/spec/config.rb +49 -0
  73. data/spec/database_spec.rb +18 -0
  74. data/spec/export/timetable_exporter_mocks.rb +20 -0
  75. data/spec/export/timetable_exporter_spec.rb +34 -0
  76. data/spec/factories/factories.rb +65 -0
  77. data/spec/import/test_data/raspisanie_2013.csv +104 -0
  78. data/spec/import/timetable_importer_mocks.rb +6 -0
  79. data/spec/import/timetable_manager_spec.rb +16 -0
  80. data/spec/import/timetable_reader_spec.rb +111 -0
  81. data/spec/import/timetable_roo_spec.rb +48 -0
  82. data/spec/mailer/mailer_spec.rb +37 -0
  83. data/spec/mainwindow_spec.rb +18 -0
  84. data/spec/models/cabinet_spec.rb +33 -0
  85. data/spec/models/course_spec.rb +26 -0
  86. data/spec/models/group_spec.rb +33 -0
  87. data/spec/models/lecturer_spec.rb +38 -0
  88. data/spec/models/semester_spec.rb +26 -0
  89. data/spec/models/speciality_spec.rb +26 -0
  90. data/spec/models/speciality_subject_spec.rb +9 -0
  91. data/spec/models/study_spec.rb +9 -0
  92. data/spec/models/subgroup_spec.rb +26 -0
  93. data/spec/models/subject_spec.rb +39 -0
  94. metadata +290 -0
data/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # Timetable Management Information System
2
+
3
+ Информационная система управления расписанием, предназначенная для учебных заведений среднего профессионального образования.
4
+
5
+ Возможности:
6
+ * Импорт и экспорт расписания в распространенные форматы;
7
+ * Экспорт расписания для преподавателей и групп на основе общего;
8
+ * Рассылка по электронной почте;
9
+ * Отображение расписания в табличной форме по дням и группам;
10
+ * Удобство редактирования засчёт ассоциирования предметов, преподавателей и кабинетов;
11
+ * Отслеживание ошибок;
12
+ * Хранение расписания за любой период;
13
+ * Работа с базой данных, как с простым файлом;
14
+ * Широкие возможности настройки;
15
+ * Кроссплатформенность.
16
+
17
+ Запланированы:
18
+ * Интерактивная справка;
19
+ * Веб-интерфейс;
20
+ * Генерация расписания;
21
+ * Оптимизация расписания.
22
+
23
+ Для получения дополнительной информации воспользуйтесь [вики проекта](https://github.com/Noein/TMIS/wiki).
24
+
25
+ Copyright © 2012 Милешкин Владислав <noein93@gmail.com>
26
+
27
+ TMIS является свободным программным обеспечением и распространяется на условиях GNU GPLv3. Текст лицензии можно найти в файле COPYING, а также по ссылке: [www.gnu.org/licenses/gpl](http://www.gnu.org/licenses/gpl).
28
+
29
+ ## Скриншоты
30
+ | [![Main](http://i.imgur.com/ZbSEbbn.png)](http://i.imgur.com/lG7gdit.png) | [![DragAndDrop](http://i.imgur.com/6aHY7L1.png)](http://i.imgur.com/YjFu5ok.png) |
31
+ | ----------------------------------------------------------------------------- |----------------------------------------------------------------------------------|
32
+ | [![Edit](http://i.imgur.com/JVsMNi2.png)](http://i.imgur.com/qGHDB9L.png) | [![Table](http://i.imgur.com/8z1E9Fz.png)](http://i.imgur.com/OmSapi0.png) |
33
+ | [![Coloring](http://i.imgur.com/yTOfexh.png)](http://i.imgur.com/9N8GGQn.png) | [![Coloring2](http://i.imgur.com/eb9j3Cu.png)](http://i.imgur.com/JUKmxzA.png) |
34
+ | [![Expand](http://i.imgur.com/gWi1ErD.png)](http://i.imgur.com/OJS5v2v.png) | [![Settings](http://i.imgur.com/1efXwqm.png)](http://i.imgur.com/pOBbGDg.png) |
35
+ | [![Export](http://i.imgur.com/k4afo9v.png)](http://i.imgur.com/cf43WDC.png) | |
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+ ## Сообщения об ошибках
44
+ Для сообщений об ошибках вы можете использовать баг-трекер на github или связаться с автором по почте.
data/Rakefile ADDED
@@ -0,0 +1,64 @@
1
+ require 'rake/testtask'
2
+ require 'rspec/core/rake_task'
3
+
4
+ def rbuic4(arg)
5
+ puts "rbuic4 #{arg}"
6
+ %x[rbuic4 #{arg}]
7
+ end
8
+
9
+ def compile_form(path)
10
+ path = "lib/tmis/" + path
11
+ path[/([a-z_0-9\/]+\/)([a-z_0-9\.]+)/i]
12
+ dirs, file = $1, $2
13
+ rbuic4(path << ' -o ' << dirs << 'ui_' << file.sub('.ui', '.rb'))
14
+ end
15
+
16
+ def remove_form(path)
17
+ rm ("lib/tmis/" + path)
18
+ end
19
+
20
+ desc "Run tests"
21
+
22
+ #Rake::TestTask.new do |t|
23
+ # t.libs << 'test'
24
+ # t.libs << 'lib/tmis'
25
+ #end
26
+
27
+ task :test => [:compile, :spec]
28
+ task :default => [:test]
29
+
30
+ task :spec do
31
+ puts %x[rspec]
32
+ end
33
+
34
+ #RSpec::Core::RakeTask.new(:spec)
35
+
36
+ task :compile do
37
+ compile_form 'interface/mainwindow.ui'
38
+ compile_form 'interface/forms/settings.ui'
39
+ compile_form 'interface/forms/import.ui'
40
+ compile_form 'interface/forms/export_general_timetable.ui'
41
+ compile_form 'interface/forms/export_lecturer_timetable.ui'
42
+ compile_form 'interface/forms/export_group_timetable.ui'
43
+ compile_form 'interface/forms/edit_study.ui'
44
+ compile_form 'interface/forms/console.ui'
45
+ compile_form 'interface/forms/about.ui'
46
+ compile_form 'interface/forms/expand_changes.ui'
47
+ compile_form 'interface/forms/find.ui'
48
+ compile_form 'interface/forms/debug_console.ui'
49
+ end
50
+
51
+ task :clean do
52
+ remove_form 'interface/ui_mainwindow.rb'
53
+ remove_form 'interface/forms/ui_settings.rb'
54
+ remove_form 'interface/forms/ui_import.rb'
55
+ remove_form 'interface/forms/ui_export_general_timetable.rb'
56
+ remove_form 'interface/forms/ui_export_lecturer_timetable.rb'
57
+ remove_form 'interface/forms/ui_export_group_timetable.rb'
58
+ remove_form 'interface/forms/ui_edit_study.rb'
59
+ remove_form 'interface/forms/ui_console.rb'
60
+ remove_form 'interface/forms/ui_about.rb'
61
+ remove_form 'interface/forms/ui_expand_changes.rb'
62
+ remove_form 'interface/forms/ui_find.rb'
63
+ remove_form 'interface/forms/ui_debug_console.rb'
64
+ end
data/bin/tmis ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'tmis'
4
+ TMIS.run
@@ -0,0 +1,58 @@
1
+ # coding: UTF-8
2
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
+ # Copyright (C) 2013 Vladislav Mileshkin
4
+ #
5
+ # This file is part of TMIS.
6
+ #
7
+ # TMIS is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # TMIS is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with TMIS. If not, see <http://www.gnu.org/licenses/>.
19
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20
+ require 'active_record'
21
+ require 'singleton'
22
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23
+ class Database
24
+ include Singleton
25
+
26
+ attr_reader :path
27
+
28
+ def connect_to(path)
29
+ @path = path
30
+ if ActiveRecord::Base.connected?
31
+ ActiveRecord::Base.remove_connection
32
+ connect path
33
+ else
34
+ connect path
35
+ end
36
+ self
37
+ end
38
+
39
+ def connected?
40
+ ActiveRecord::Base.connected?
41
+ end
42
+
43
+ def disconnect
44
+ ActiveRecord::Base.remove_connection; self
45
+ end
46
+
47
+ def transaction(&block)
48
+ ActiveRecord::Base.transaction(&block); self
49
+ end
50
+
51
+ private
52
+ def connect(path)
53
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: path)
54
+ ActiveRecord::Base.timestamped_migrations = false
55
+ ActiveRecord::Migrator.up (File.dirname(__FILE__) << '/migrations')
56
+ self
57
+ end
58
+ end
@@ -0,0 +1,366 @@
1
+ # coding: UTF-8
2
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
+ require 'contracts'
4
+ require 'spreadsheet'
5
+ require 'benchmark'
6
+ require_relative '../import/abstract_spreadsheet'
7
+ require_relative '../models/lecturer'
8
+ require_relative '../models/group'
9
+ require_relative '../models/study'
10
+ #include Contracts
11
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12
+ class AbstractTimetableExportStratagy
13
+ #Contract Or[Range,Array] => Any
14
+ def initialize(dates)
15
+ raise NotImplementedError
16
+ end
17
+
18
+ #Contract None => Or[Range,Array]
19
+ def rows
20
+ raise NotImplementedError
21
+ end
22
+
23
+ #Contract None => Or[Range,Array]
24
+ def columns
25
+ raise NotImplementedError
26
+ end
27
+
28
+ #Contract Any => Any
29
+ def row_value(row_entity)
30
+ raise NotImplementedError
31
+ end
32
+
33
+ #Contract Any => Any
34
+ def column_value(col_entity)
35
+ raise NotImplementedError
36
+ end
37
+
38
+ #Contract Any, Any => ArrayOf[Study]
39
+ def studies(row_entity, col_entity)
40
+ raise NotImplementedError
41
+ end
42
+ end
43
+
44
+ class TimetableExporter
45
+ #Contract IsA[AbstractSpreadsheet], IsA[AbstractTimetableExportStratagy] => Any
46
+ def initialize(table, stratagy)
47
+ @table = table
48
+ @stratagy = stratagy
49
+ end
50
+
51
+ #Contract None => IsA[AbstractSpreadsheet]
52
+ def export
53
+ rows_export
54
+ @table
55
+ end
56
+
57
+ private
58
+ def rows_export
59
+ rows.each do |entity, rows|
60
+ rows_format(rows)
61
+ @table[rows[0] + 1, 1] = @stratagy.row_value(entity)
62
+ (1..6).each do |row|
63
+ pair_format(rows, row)
64
+ @table[(rows[0] - 1) + row * 2, 2] = "#{row} пара"
65
+ end
66
+ columns_export(entity, rows)
67
+ end
68
+ end
69
+
70
+ def columns_export(row_ent, rows)
71
+ columns.each do |ent, cols|
72
+ columns_format(rows, cols)
73
+ @table[rows[0], cols[0]] = @stratagy.column_value(ent)
74
+ export_studies(@stratagy.studies(row_ent, ent), rows, cols)
75
+ end
76
+ end
77
+
78
+ #Contract ArrayOf[Study], [Pos, Pos], [Pos, Pos] => Any
79
+ def export_studies(studies, rows, cols)
80
+ prepare_studies(studies).each do |number, studies|
81
+ if studies.size == 1
82
+ @table.merge(real_row(rows, number), cols[0], real_row(rows, number) + 1, cols[0])
83
+ @table.merge(real_row(rows, number), cols[1], real_row(rows, number) + 1, cols[1])
84
+ end
85
+ studies.each_with_index do |study, i|
86
+ @table[real_row(rows, number) + i, cols[0]] = study.to_s
87
+ @table[real_row(rows, number) + i, cols[1]] = study.cabinet.title
88
+ end
89
+ end
90
+ end
91
+
92
+ def rows
93
+ @stratagy.rows.zip((1..(13 * @stratagy.rows.to_a.size)).each_slice(13).map{ |i| [i.first, i.last] })
94
+ end
95
+
96
+ def columns
97
+ @stratagy.columns.zip((3..(@stratagy.columns.to_a.size * 2) + (3 - 1)).each_slice(2))
98
+ end
99
+
100
+ #Contract ArrayOf[Study] => ({ Pos => ArrayOf[Study] })
101
+ def prepare_studies(studies)
102
+ studies.sort_by(&:number).group_by(&:number)
103
+ end
104
+
105
+ #Contract ArrayOf[Pos], Pos => Pos
106
+ def real_row(rows, number)
107
+ (rows[0] - 1) + (number * 2)
108
+ end
109
+
110
+ def rows_format(rows)
111
+ @table.merge(rows[0] + 1, 1, rows[1], 1)
112
+ format = Spreadsheet::Format.new
113
+ format.rotation = 90
114
+ format.horizontal_align = :center
115
+ format.vertical_align = :middle
116
+ format.top = :medium
117
+ format.bottom = :medium
118
+ format.right = :medium
119
+ format.left = :medium
120
+ @table.format(rows[0] + 1, 1, format)
121
+ end
122
+
123
+ def pair_format(rows, row)
124
+ @table.row((rows[0] - 1) + row * 2).height = 30
125
+ @table.row(rows[0] + row * 2).height = 30
126
+ @table.merge((rows[0] - 1) + row * 2, 2, rows[0] + row * 2, 2)
127
+ end
128
+
129
+ def columns_format(rows, cols)
130
+ @table.column(cols[0]).width = 25
131
+ @table.merge(rows[0], cols[0], rows[0], cols[1])
132
+ end
133
+ end
134
+
135
+ class GeneralTimetableExportStratagy < AbstractTimetableExportStratagy
136
+ #Contract Or[Range,Array] => Any
137
+ def initialize(dates)
138
+ @dates = dates
139
+ end
140
+
141
+ #Contract None => Or[Range,Array]
142
+ def rows
143
+ @dates
144
+ end
145
+
146
+ #Contract None => Or[Range,Array]
147
+ def columns
148
+ Group.all.sort_by(&:title_for_sort)
149
+ end
150
+
151
+ #Contract Any => Any
152
+ def row_value(date)
153
+ date.strftime('%A')
154
+ end
155
+
156
+ #Contract Any => Any
157
+ def column_value(group)
158
+ group.title
159
+ end
160
+
161
+ #Contract Any, Any => ArrayOf[Study]
162
+ def studies(date, group)
163
+ Study.of_group_and_its_subgroups(group).where(date: date).to_a
164
+ end
165
+ end
166
+
167
+ class LecturerTimetableExportStratagy < AbstractTimetableExportStratagy
168
+ #Contract Or[Range,Array], Lecturer => Any
169
+ def initialize(dates, lecturer)
170
+ @dates = dates
171
+ @lecturer = lecturer
172
+ end
173
+
174
+ #Contract None => Or[Range,Array]
175
+ def rows
176
+ @dates
177
+ end
178
+
179
+ # TODO Изменить контракты
180
+ #Contract None => RespondTo[:zip]
181
+ def columns
182
+ Group.where(id: @lecturer.studies.where(date: @dates, groupable_type: 'Group').select(:groupable_id))
183
+ end
184
+
185
+ #Contract Any => Any
186
+ def row_value(date)
187
+ date.strftime('%A')
188
+ end
189
+
190
+ #Contract Any => Any
191
+ def column_value(group)
192
+ group.title
193
+ end
194
+
195
+ #Contract Any, Any => ArrayOf[Study]
196
+ def studies(date, group)
197
+ Study.of_group_and_its_subgroups(group).where(date: date, lecturer_id: @lecturer).to_a
198
+ end
199
+ end
200
+
201
+ class TimetableExporter2
202
+ #Contract IsA[AbstractSpreadsheet], IsA[AbstractTimetableExportStratagy] => Any
203
+ def initialize(table, stratagy)
204
+ @table = table
205
+ @stratagy = stratagy
206
+ end
207
+
208
+ #Contract None => IsA[AbstractSpreadsheet]
209
+ def export
210
+ rows_export
211
+ @table
212
+ end
213
+
214
+ private
215
+ def rows_export
216
+ rows.each do |entity, rows|
217
+ rows_format(rows)
218
+ @table[rows[0] + 1, 1] = @stratagy.row_value(entity)
219
+ (1..6).each do |row|
220
+ pair_format(rows, row)
221
+ @table[(rows[0] - 1) + row * 2, 2] = "#{row} пара"
222
+ end
223
+ columns_export(entity, rows)
224
+ end
225
+ end
226
+
227
+ def columns_export(row_ent, rows)
228
+ columns.each do |ent, cols|
229
+ columns_format(rows, cols)
230
+ @table[rows[0], cols[0]] = @stratagy.column_value(ent)
231
+ export_studies(@stratagy.studies(row_ent, ent), rows, cols)
232
+ end
233
+ end
234
+
235
+ #Contract ArrayOf[Study], [Pos, Pos], [Pos, Pos] => Any
236
+ def export_studies(studies, rows, cols)
237
+ prepare_studies(studies).each do |number, studies|
238
+ @table.merge(real_row(rows, number), cols[0], real_row(rows, number) + 1, cols[0])
239
+ @table.merge(real_row(rows, number), cols[1], real_row(rows, number) + 1, cols[1])
240
+ studies.each_with_index do |study, i|
241
+ @table[real_row(rows, number) + i, cols[0]] =
242
+ "#{study.subject.title}\n#{study.groupable.get_group.title} " +
243
+ (study.groupable.subgroup? ? "(#{study.groupable.number}п)" : '')
244
+ @table[real_row(rows, number) + i, cols[1]] = study.cabinet.title
245
+ end
246
+ end
247
+ end
248
+
249
+ def rows
250
+ @stratagy.rows.zip((1..(7 * @stratagy.rows.to_a.size)).each_slice(7).map{ |i| [i.first, i.last] })
251
+ end
252
+
253
+ def columns
254
+ @stratagy.columns.zip((3..(@stratagy.columns.to_a.size * 2) + (3 - 1)).each_slice(2))
255
+ end
256
+
257
+ #Contract ArrayOf[Study] => ({ Pos => ArrayOf[Study] })
258
+ def prepare_studies(studies)
259
+ studies.sort_by(&:number).group_by(&:number)
260
+ end
261
+
262
+ #Contract ArrayOf[Pos], Pos => Pos
263
+ def real_row(rows, number)
264
+ (rows[0] - 1) + (number * 2)
265
+ end
266
+
267
+ def rows_format(rows)
268
+ @table.merge(rows[0] + 1, 1, rows[1], 1)
269
+ format = Spreadsheet::Format.new
270
+ format.rotation = 90
271
+ format.horizontal_align = :center
272
+ format.vertical_align = :middle
273
+ format.top = :medium
274
+ format.bottom = :medium
275
+ format.right = :medium
276
+ format.left = :medium
277
+ @table.format(rows[0] + 1, 1, format)
278
+ end
279
+
280
+ def pair_format(rows, row)
281
+ @table.row((rows[0] - 1) + row * 2).height = 30
282
+ @table.row(rows[0] + row * 2).height = 30
283
+ @table.merge((rows[0] - 1) + row * 2, 2, rows[0] + row * 2, 2)
284
+ end
285
+
286
+ def columns_format(rows, cols)
287
+ @table.column(cols[0]).width = 25
288
+ @table.merge(rows[0], cols[0], rows[0], cols[1])
289
+ end
290
+ end
291
+
292
+ class LecturerTimetableExportStratagy2 < AbstractTimetableExportStratagy
293
+ #Contract Or[Range,Array], Lecturer => Any
294
+ def initialize(dates, lecturer)
295
+ @dates = dates
296
+ @lecturer = lecturer
297
+ end
298
+
299
+ #Contract None => Or[Range,Array]
300
+ def rows
301
+ ['']
302
+ end
303
+
304
+ # TODO Изменить контракты
305
+ #Contract None => RespondTo[:zip]
306
+ def columns
307
+ @dates
308
+ end
309
+
310
+ #Contract Any => Any
311
+ def row_value(none)
312
+ ""
313
+ end
314
+
315
+ #Contract Any => Any
316
+ def column_value(date)
317
+ date.strftime('%A')
318
+ end
319
+
320
+ #Contract Any, Any => ArrayOf[Study]
321
+ def studies(none, date)
322
+ Study.find_by_sql("select studies.* "+
323
+ "from studies "+
324
+ "join groups on groups.id = studies.groupable_id and studies.groupable_type = 'Group' "+
325
+ "where date = '#{date.to_s}' and lecturer_id = #{@lecturer.id} "+
326
+ "union "+
327
+ "select studies.* "+
328
+ "from studies "+
329
+ "join subgroups on subgroups.id = studies.groupable_id and studies.groupable_type = 'Subgroup' "+
330
+ "where date = '#{date.to_s}' and lecturer_id = #{@lecturer.id}")
331
+ #Study.of_group_and_its_subgroups(group).where(date: date, lecturer_id: @lecturer).to_a
332
+ end
333
+ end
334
+
335
+ class GroupTimetableExportStratagy < AbstractTimetableExportStratagy
336
+ #Contract Or[Range,Array], Group => Any
337
+ def initialize(dates, group)
338
+ @dates = dates
339
+ @group = group
340
+ end
341
+
342
+ #Contract None => Or[Range,Array]
343
+ def rows
344
+ ['']
345
+ end
346
+
347
+ #Contract None => RespondTo[:zip]
348
+ def columns
349
+ @dates
350
+ end
351
+
352
+ #Contract Any => Any
353
+ def row_value(none)
354
+ ""
355
+ end
356
+
357
+ #Contract Any => Any
358
+ def column_value(date)
359
+ date.strftime('%A')
360
+ end
361
+
362
+ #Contract Any, Any => ArrayOf[Study]
363
+ def studies(none, date)
364
+ Study.of_group_and_its_subgroups(@group).where(date: date).to_a
365
+ end
366
+ end
@@ -0,0 +1,53 @@
1
+ # coding: UTF-8
2
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
+ require 'contracts'
4
+ #include Contracts
5
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6
+ class AbstractSpreadsheet
7
+ #Contract String => Any
8
+ def initialize(filepath)
9
+ raise NotImplementedError
10
+ end
11
+
12
+ #Contract None => Pos
13
+ def last_row
14
+ raise NotImplementedError
15
+ end
16
+
17
+ #Contract None => Pos
18
+ def last_column
19
+ raise NotImplementedError
20
+ end
21
+
22
+ #Contract Not[Neg] => Any
23
+ def sheet(n)
24
+ raise NotImplementedError
25
+ end
26
+
27
+ #Contract Pos => Any
28
+ def row(n)
29
+ raise NotImplementedError
30
+ end
31
+
32
+ #Contract Pos => Any
33
+ def column(n)
34
+ raise NotImplementedError
35
+ end
36
+
37
+ #Contract Pos, Pos => Any
38
+ def [](r, c)
39
+ raise NotImplementedError
40
+ end
41
+ end
42
+
43
+ module WritableSpreadsheet
44
+ #Contract Pos, Pos, Any => Any
45
+ def []=(r, c, obj)
46
+ raise NotImplementedError
47
+ end
48
+
49
+ #Contract None => Any
50
+ def save
51
+ raise NotImplementedError
52
+ end
53
+ end