// officeHour package main import ( "bytes" "fmt" "html/template" ) const minuteGranularity int = 5 type OfficeHour struct { Id int Tutor Tutor Week int Date Room Room Course Course Info string Active bool Duration int } func getOfficeHours() []OfficeHour { return []OfficeHour{ OfficeHour{ Id: 1, Tutor: Tutor{1, "Dummy", "dummy@mathebau.de"}, Week: 0, Date: Date{ Day: 0, Hour: 12, Minute: 0}, Room: getRooms()[0], Course: getCourses()[0], Info: "", Active: true, Duration: 60}, OfficeHour{ Id: 2, Tutor: Tutor{1, "Dummy", "dummy@mathebau.de"}, Week: 0, Date: Date{ Day: 0, Hour: 13, Minute: 30}, Room: getRooms()[0], Course: getCourses()[1], Info: "", Active: true, Duration: 90}, OfficeHour{ Id: 3, Tutor: Tutor{1, "Dummy", "dummy@mathebau.de"}, Week: 0, Date: Date{Day: 0, Hour: 12, Minute: 45}, Room: getRooms()[1], Course: getCourses()[1], Info: "", Active: true, Duration: 60}} } func getOfficeHoursByCourse(courseId int) []OfficeHour { var result []OfficeHour for _, option := range getOfficeHours() { if option.Course.Id == courseId { result = append(result, option) } } return result } func getOfficeHoursByRoom(roomId int) []OfficeHour { var result []OfficeHour for _, option := range getOfficeHours() { if option.Room.Id == roomId { result = append(result, option) } } return result } func getOfficeHourById(id int) OfficeHour { return OfficeHour{} } func getTimetable(officeHours []OfficeHour) (timetable map[Date]map[int]OfficeHour, slots []int) { var fullTimetable = make(map[Date]map[int]OfficeHour) for _, officeHour := range officeHours { var slot int = 0 for minute := 0; minute < officeHour.Duration; minute += minuteGranularity { // find slot id _, exists := fullTimetable[Date{officeHour.Day, officeHour.Hour + (officeHour.Minute+minute)/60, (officeHour.Minute + minute) % 60}] if exists { _, exists := fullTimetable[Date{officeHour.Day, officeHour.Hour + (officeHour.Minute+minute)/60, (officeHour.Minute + minute) % 60}][slot] if exists { slot += 1 minute = 0 continue } } else { fullTimetable[Date{officeHour.Day, officeHour.Hour + (officeHour.Minute+minute)/60, (officeHour.Minute + minute) % 60}] = make(map[int]OfficeHour) } } for minute := 0; minute < officeHour.Duration; minute += minuteGranularity { // write officeHour id to timetable fullTimetable[Date{officeHour.Day, officeHour.Hour + (officeHour.Minute+minute)/60, (officeHour.Minute + minute) % 60}][slot] = officeHour } } slots = []int{1, 1, 1, 1, 1} for date, _ := range fullTimetable { if slots[date.Day] < len(fullTimetable[date]) { slots[date.Day] = len(fullTimetable[date]) } } timetable = make(map[Date]map[int]OfficeHour) for _, officeHour := range officeHours { for slot := 0; slot < slots[officeHour.Date.Day]; slot += 1 { if fullTimetable[officeHour.Date][slot] == officeHour { timetable[officeHour.Date] = make(map[int]OfficeHour) timetable[officeHour.Date][slot] = officeHour } } } return fullTimetable, slots } func printTimetable(timetable map[Date]map[int]OfficeHour, slots []int) template.HTML { var tableBody string tableCell, _ := template.ParseFiles("templates/td.html") for hour := 8; hour < 19; hour += 1 { for minute := 0; minute < 60; minute += minuteGranularity { tableBody += "" if minute == 0 { tableBody += fmt.Sprintf("%d Uhr\n", hour) } else { tableBody += "\n" } for day := 0; day < 5; day += 1 { for slot := 0; slot < slots[day]; slot += 1 { current, currentExists := timetable[Date{day, hour, 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 OfficeHour if hour > 0 && minute < minuteGranularity { predecessor, predecessorExists = timetable[Date{day, hour - 1, 60 - minuteGranularity}][slot] } else { predecessor, predecessorExists = timetable[Date{day, hour, minute - minuteGranularity}][slot] } if predecessorExists { continued = (predecessor == current) } else { continued = false } if continued { continue } else { var celldata bytes.Buffer data := struct { Rowspan int StartHour int StartMinute int EndHour int EndMinute int CourseName string TutorName string RoomName string }{current.Duration / minuteGranularity, current.Hour, current.Minute, current.Hour + ((current.Minute + current.Duration) / 60), (current.Minute + current.Duration) % 60, template.HTMLEscapeString(current.Course.Name), current.Tutor.Name, current.Room.Name, } tableCell.Execute(&celldata, data) tableBody += celldata.String() } } else { if slot+1 == slots[day] { tableBody += "\n" } else { tableBody += "\n" } } } } tableBody += "\n" } } var table bytes.Buffer tableTemplate, _ := template.ParseFiles("templates/officeHourTable.html") 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), } tableTemplate.Execute(&table, tableData) return template.HTML(table.String()) }