Gonne
4ea0471683
Delete dead code and remove named return arguments to avoid confusion between them and the returned values. Add documentation.
133 lines
4.5 KiB
Go
133 lines
4.5 KiB
Go
// timetable.go
|
|
package controllers
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"html/template"
|
|
"log"
|
|
"officeHours/models"
|
|
"officeHours/templating"
|
|
)
|
|
|
|
// A function that takes a slice of office hours and
|
|
// constructs a timetable t such that t[date][slot] is an
|
|
// office hour that takes place at this time and no such cell has more than one
|
|
// office hour and each officehour is in exactly one slot.
|
|
// It also indicates how many slots exist per day.
|
|
func (b *BaseHandler) GetTimetable(officeHours []models.OfficeHour) (map[models.Date]map[int]models.OfficeHour, []int) {
|
|
var timetable = make(map[models.Date]map[int]models.OfficeHour)
|
|
for _, officeHour := range officeHours {
|
|
var slot int = 0
|
|
for minute := 0; minute < officeHour.Duration; minute += b.config.Date.MinuteGranularity { // find slot id
|
|
_, exists := timetable[models.GetEndDate(officeHour.Date, minute, true)]
|
|
if exists {
|
|
_, exists := timetable[models.GetEndDate(officeHour.Date, minute, true)][slot]
|
|
if exists {
|
|
slot += 1
|
|
minute = 0
|
|
continue
|
|
}
|
|
} else {
|
|
timetable[models.GetEndDate(officeHour.Date, minute, true)] = make(map[int]models.OfficeHour)
|
|
}
|
|
}
|
|
for minute := 0; minute < officeHour.Duration; minute += b.config.Date.MinuteGranularity { // write officeHour id to timetable
|
|
timetable[models.GetEndDate(officeHour.Date, minute, true)][slot] = officeHour
|
|
}
|
|
}
|
|
slots := []int{1, 1, 1, 1, 1}
|
|
for date, _ := range timetable {
|
|
if slots[date.Day] < len(timetable[date]) {
|
|
slots[date.Day] = len(timetable[date])
|
|
}
|
|
}
|
|
return timetable, slots
|
|
}
|
|
|
|
// A function to generate the HTML code for the table of office hours from a timetable.
|
|
func (b *BaseHandler) printTimetable(timetable map[models.Date]map[int]models.OfficeHour, slots []int, deleteIcons bool) template.HTML {
|
|
if len(timetable) == 0 { // no office hours to display
|
|
return template.HTML("<p class=\"text-center\">Aktuell sind keine passenden Sprechstunden eingetragen.</p>")
|
|
}
|
|
var tableBody string
|
|
for hour := 8; hour < 19; hour += 1 {
|
|
for minute := 0; minute < 60; minute += b.config.Date.MinuteGranularity {
|
|
tableBody += "<tr>"
|
|
if minute == 0 {
|
|
tableBody += fmt.Sprintf("<td class=\"timetableRightBorder\">%d Uhr</td>\n", hour)
|
|
} else {
|
|
tableBody += "<td class=\"timetableRightBorder\"></td>\n"
|
|
}
|
|
for day := 0; day < 5; day += 1 {
|
|
for slot := 0; slot < slots[day]; slot += 1 {
|
|
current, currentExists := timetable[models.Date{Week: 0, Day: day, Hour: hour, Minute: minute}][slot]
|
|
|
|
if currentExists { // This slot is taken by some office hour
|
|
var continued bool = false // is this slot occupied by the same office hour the previous minute?
|
|
var predecessorExists bool
|
|
var predecessor models.OfficeHour
|
|
if hour > 0 && minute < b.config.Date.MinuteGranularity {
|
|
predecessor, predecessorExists = timetable[models.Date{Week: 0, Day: day, Hour: hour - 1, Minute: 60 - b.config.Date.MinuteGranularity}][slot]
|
|
} else {
|
|
predecessor, predecessorExists = timetable[models.Date{Week: 0, Day: day, Hour: hour, Minute: minute - b.config.Date.MinuteGranularity}][slot]
|
|
}
|
|
if predecessorExists {
|
|
continued = (predecessor == current)
|
|
} else {
|
|
continued = false
|
|
}
|
|
if continued {
|
|
continue
|
|
} else {
|
|
var celldata bytes.Buffer
|
|
data := struct {
|
|
OfficeHour models.OfficeHour
|
|
MinuteGranularity int
|
|
DeleteIcons bool
|
|
}{OfficeHour: current, MinuteGranularity: b.config.Date.MinuteGranularity, DeleteIcons: deleteIcons}
|
|
err := templating.WriteTemplate(&celldata, "td", data)
|
|
if err != nil {
|
|
err = fmt.Errorf("writing table cell failed:\n%w", err)
|
|
log.Println(err.Error())
|
|
// TODO: better error wrapping up to top-level request handler
|
|
}
|
|
tableBody += celldata.String()
|
|
}
|
|
} else {
|
|
if slot+1 == slots[day] {
|
|
tableBody += "<td class=\"timetableRightBorder\"></td>\n"
|
|
} else {
|
|
tableBody += "<td></td>\n"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
tableBody += "</tr>\n"
|
|
}
|
|
}
|
|
var table bytes.Buffer
|
|
|
|
tableData := struct {
|
|
ColspanMon int
|
|
ColspanTue int
|
|
ColspanWed int
|
|
ColspanThu int
|
|
ColspanFri int
|
|
TableBody template.HTML
|
|
}{
|
|
slots[0],
|
|
slots[1],
|
|
slots[2],
|
|
slots[3],
|
|
slots[4],
|
|
template.HTML(tableBody),
|
|
}
|
|
err := templating.WriteTemplate(&table, "officeHourTable", tableData)
|
|
if err != nil {
|
|
err = fmt.Errorf("writing table failed:\n%w", err)
|
|
log.Println(err.Error())
|
|
// TODO: better error wrapping up to top-level request handler
|
|
}
|
|
return template.HTML(table.String())
|
|
}
|