Erster Commit

This commit is contained in:
Gonne 2022-08-24 08:16:27 +02:00
commit b26544756a
11 changed files with 405 additions and 0 deletions

19
.gitignore vendored Normal file
View File

@ -0,0 +1,19 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
sprechstundentool
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
vendor/
# Go workspace file
go.work

15
course.go Normal file
View File

@ -0,0 +1,15 @@
// course
package main
type Course struct {
Id int
Name string
Active bool
}
func getCourses() []Course {
return []Course{
Course{1, "Dummyveranstaltung", true},
Course{2, "Dummyveranstaltung 2", true},
}
}

8
date.go Normal file
View File

@ -0,0 +1,8 @@
// date
package main
type Date struct {
Day int
Hour int
Minute int
}

6
doc.go Normal file
View File

@ -0,0 +1,6 @@
// sprechstundentool project doc.go
/*
sprechstundentool document
*/
package main

68
main.go Normal file
View File

@ -0,0 +1,68 @@
package main
import (
"fmt"
"html/template"
"net/http"
"strconv"
)
func root(w http.ResponseWriter, req *http.Request) {
writeTimetablePage(w, req, template.HTML(""))
}
func getByRoom(w http.ResponseWriter, req *http.Request) {
room, err := strconv.Atoi(req.FormValue("raum"))
if err != nil || room == 0 {
root(w, req)
return
}
writeTimetablePage(w, req, printTimetable(getTimetable(getOfficeHoursByRoom(room))))
}
func getByCourse(w http.ResponseWriter, req *http.Request) {
course, err := strconv.Atoi(req.FormValue("veranstaltung"))
if err != nil || course == 0 {
root(w, req)
return
}
writeTimetablePage(w, req, printTimetable(getTimetable(getOfficeHoursByCourse(course))))
}
func writeTimetablePage(w http.ResponseWriter, req *http.Request, timetable template.HTML) {
room, err := strconv.Atoi(req.FormValue("raum"))
if err != nil {
room = 0
}
course, err := strconv.Atoi(req.FormValue("veranstaltung"))
if err != nil {
course = 0
}
data := struct {
Courses []Course
Rooms []Room
Timetable template.HTML
SelectedRoom int
SelectedCourse int
}{getCourses(), getRooms(), timetable, room, course}
tmpl, err := template.ParseFiles("templates/index.html")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("Template konnte nicht geparst werden : %s", string(err.Error()))))
return
}
err = tmpl.Execute(w, data)
if err != nil {
w.Write([]byte(fmt.Sprintf("Template konnte nicht geparst werden : %s", string(err.Error()))))
return
}
}
func main() {
http.HandleFunc("/getByRoom", getByRoom)
http.HandleFunc("/getByCourse", getByCourse)
http.HandleFunc("/", root)
http.ListenAndServe(":8080", nil)
}

217
officeHour.go Normal file
View File

@ -0,0 +1,217 @@
// 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 += "<tr>"
if minute == 0 {
tableBody += fmt.Sprintf("<td>%d Uhr</td>\n", hour)
} else {
tableBody += "<td></td>\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 += "<td style=\"border-right: 1px dotted\"></td>\n"
} else {
tableBody += "<td></td>\n"
}
}
}
}
tableBody += "</tr>\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())
}

20
room.go Normal file
View File

@ -0,0 +1,20 @@
// raum
package main
type Room struct {
Id int
Name string
Max_occupy int
Active bool
}
func getRooms() []Room {
return []Room{
Room{1, "S2 15 345", 2, true},
Room{2, "S2 15 415", 1, true},
Room{3, "S2 15 336", 2, true},
Room{4, "S2 15 444", 1, true},
Room{5, "S2 15 333", 1, true},
Room{6, "S2 14 420", 1, false},
Room{7, "Sonstige", 255, true}}
}

27
templates/index.html Normal file
View File

@ -0,0 +1,27 @@
<html>
<head>
<title>Sprechstunden</title>
</head>
<body>
<form method="GET" action="/getByCourse">
<label for="veranstaltung">Veranstaltung: </label>
<select name="veranstaltung" size="1" onchange="document.forms[0].submit()">
<option value="0">Alle</option>
{{range $course := .Courses}}
<option value="{{$course.Id}}"{{if eq $course.Id $.SelectedCourse}} selected{{end}}>{{$course.Name}}</option>{{end}}
</select>
<input type="submit" value="Auswählen" />
</form>
<form method="GET" action="/getByRoom">
<label for="raum">Raum: </label>
<select name="raum" size="1" onchange="document.forms[1].submit()">
<option value="0">Alle</option>
{{range $room := .Rooms}}
<option value="{{$room.Id}}"{{if eq $room.Id $.SelectedRoom}} selected{{end}}>{{$room.Name}}</option>{{end}}
</select>
<input type="submit" value="Auswählen" />
</form>
{{.Timetable}}
Technische Fragen an <a href="mailto:sprechstundentool@mathebau.de">sprechstundentool@mathebau.de</a>
</body>
</html>

View File

@ -0,0 +1,11 @@
<table>
<tr>
<th>&nbsp;</th>
<th colspan="{{.ColspanMon}}" style="padding-left: 10px; padding-right: 10px; border-right: 1px dotted">Montag</th>
<th colspan="{{.ColspanTue}}" style="padding-left: 10px; padding-right: 10px; border-right: 1px dotted">Dienstag</th>
<th colspan="{{.ColspanWed}}" style="padding-left: 10px; padding-right: 10px; border-right: 1px dotted">Mittwoch</th>
<th colspan="{{.ColspanThu}}" style="padding-left: 10px; padding-right: 10px; border-right: 1px dotted">Donnerstag</th>
<th colspan="{{.ColspanFri}}" style="padding-left: 10px; padding-right: 10px; border-right: 1px dotted">Freitag</th>
</tr>
{{.TableBody}}
</table>

6
templates/td.html Normal file
View File

@ -0,0 +1,6 @@
<td rowspan="{{.Rowspan}}" style="border: 1px solid">
{{.StartHour}}:{{printf "%02d" .StartMinute}} - {{.EndHour}}:{{printf "%02d" .EndMinute}}<br />
{{.CourseName}}<br />
{{.TutorName}}<br />
{{.RoomName}}
</td>

8
tutor.go Normal file
View File

@ -0,0 +1,8 @@
// tutor
package main
type Tutor struct {
Id int
Name string
Email string
}