diff --git a/.gitignore b/.gitignore
index 2ca337e..9589158 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,9 @@
*.dylib
sprechstundentool
+#Databases
+*.db
+
# Test binary, built with `go test -c`
*.test
@@ -17,3 +20,5 @@ vendor/
# Go workspace file
go.work
+go.mod
+go.sum
diff --git a/controllers/handlers.go b/controllers/handlers.go
new file mode 100644
index 0000000..5e613c8
--- /dev/null
+++ b/controllers/handlers.go
@@ -0,0 +1,77 @@
+package controllers
+
+import (
+ "fmt"
+ "html/template"
+ "net/http"
+ "sprechstundentool/models"
+ "strconv"
+)
+
+// BaseHandler will hold everything that controller needs
+type BaseHandler struct {
+ roomRepo models.RoomRepository
+ officeHourRepo models.OfficeHourRepository
+ courseRepo models.CourseRepository
+ tutorRepo models.TutorRepository
+}
+
+// NewBaseHandler returns a new BaseHandler
+func NewBaseHandler(roomRepo models.RoomRepository, officeHourRepo models.OfficeHourRepository, courseRepo models.CourseRepository, tutorRepo models.TutorRepository) *BaseHandler {
+ return &BaseHandler{roomRepo, officeHourRepo, courseRepo, tutorRepo}
+}
+
+func (b *BaseHandler) RootHandler(w http.ResponseWriter, req *http.Request) {
+ b.writeTimetablePage(w, req, template.HTML(""))
+}
+
+func (b *BaseHandler) GetByRoomHandler(w http.ResponseWriter, req *http.Request) {
+ roomId, _ := strconv.Atoi(req.FormValue("raum"))
+ room, err := b.roomRepo.FindById(roomId)
+ if err != nil {
+ fmt.Println(err)
+ b.RootHandler(w, req)
+ return
+ }
+ officeHours, _ := b.officeHourRepo.FindByRoom(room)
+ b.writeTimetablePage(w, req, printTimetable(GetTimetable(officeHours)))
+}
+
+func (b *BaseHandler) GetByCourseHandler(w http.ResponseWriter, req *http.Request) {
+ courseid, err := strconv.Atoi(req.FormValue("veranstaltung"))
+ if err != nil {
+ b.RootHandler(w, req)
+ }
+ course, err := b.courseRepo.FindById(courseid)
+ if err != nil {
+ b.RootHandler(w, req)
+ return
+ }
+ officeHours, _ := b.officeHourRepo.FindByCourse(course)
+ b.writeTimetablePage(w, req, printTimetable(GetTimetable(officeHours)))
+}
+
+func (b *BaseHandler) writeTimetablePage(w http.ResponseWriter, req *http.Request, timetable template.HTML) {
+ courses, _ := b.courseRepo.GetAll()
+ rooms, _ := b.roomRepo.GetAll()
+ selectedRoom, _ := strconv.Atoi(req.FormValue("raum"))
+ selectedCourse, _ := strconv.Atoi(req.FormValue("veranstaltung"))
+ data := struct {
+ Courses []models.Course
+ Rooms []models.Room
+ Timetable template.HTML
+ SelectedRoom int
+ SelectedCourse int
+ }{courses, rooms, timetable, selectedRoom, selectedCourse}
+ 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
+ }
+}
diff --git a/controllers/timetable.go b/controllers/timetable.go
new file mode 100644
index 0000000..5a8cb9a
--- /dev/null
+++ b/controllers/timetable.go
@@ -0,0 +1,137 @@
+// timetable.go
+package controllers
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "sprechstundentool/models"
+)
+
+func GetTimetable(officeHours []models.OfficeHour) (timetable map[models.Date]map[int]models.OfficeHour, slots []int) {
+ var fullTimetable = make(map[models.Date]map[int]models.OfficeHour)
+ for _, officeHour := range officeHours {
+ var slot int = 0
+ for minute := 0; minute < officeHour.Duration; minute += models.MinuteGranularity { // find slot id
+ _, exists := fullTimetable[models.Date{officeHour.Day, officeHour.Hour + (officeHour.Minute+minute)/60, (officeHour.Minute + minute) % 60}]
+ if exists {
+ _, exists := fullTimetable[models.Date{officeHour.Day, officeHour.Hour + (officeHour.Minute+minute)/60, (officeHour.Minute + minute) % 60}][slot]
+ if exists {
+ slot += 1
+ minute = 0
+ continue
+ }
+ } else {
+ fullTimetable[models.Date{officeHour.Day, officeHour.Hour + (officeHour.Minute+minute)/60, (officeHour.Minute + minute) % 60}] = make(map[int]models.OfficeHour)
+ }
+ }
+ for minute := 0; minute < officeHour.Duration; minute += models.MinuteGranularity { // write officeHour id to timetable
+ fullTimetable[models.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[models.Date]map[int]models.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]models.OfficeHour)
+ timetable[officeHour.Date][slot] = officeHour
+ }
+ }
+ }
+ return fullTimetable, slots
+}
+
+func printTimetable(timetable map[models.Date]map[int]models.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 += models.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[models.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 models.OfficeHour
+ if hour > 0 && minute < models.MinuteGranularity {
+ predecessor, predecessorExists = timetable[models.Date{day, hour - 1, 60 - models.MinuteGranularity}][slot]
+ } else {
+ predecessor, predecessorExists = timetable[models.Date{day, hour, minute - models.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 / models.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())
+}
diff --git a/course.go b/course.go
deleted file mode 100644
index b6dccbf..0000000
--- a/course.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// 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},
- }
-}
diff --git a/dummydatasqlite.sql b/dummydatasqlite.sql
new file mode 100644
index 0000000..802af70
--- /dev/null
+++ b/dummydatasqlite.sql
@@ -0,0 +1,4 @@
+INSERT INTO `room` (name, max_occupy) VALUES ('S2 15 345',2),('S2 15 415',1),('S2 15 336',2),('S2 15 444',1),('S2 15 333',1),('S2 14 420',1),('Sonstige',1024);
+INSERT INTO `officeHour` VALUES (0,1,1,12,0,1,1,0,'',true,60),(1,1,1,12,15,2,1,0,'',true,60),(2,1,1,12,30,1,2,0,'',true,60);
+INSERT INTO `tutor` (name, email) VALUES ('Dummyname','dummy@example.com');
+INSERT INTO `course` (name) VALUES ('Integrationstheorie'),('Analysis II (engl.)'),('Analysis II'),('Mathe II für Informatik'),('Mathe II für Bauwesen'),('Diskrete Optimierung'),('Lineare Algebra II'),('Einführung in die Algebra'),('FGdI I&II'),('Algorithmic Discrete Mathematics'),('Einführung in die Stochastik'),('Mathe II für ET'),('Mathe II für Maschinenbau'),('Mathe IV für Maschinenbau'),('Num Mathe für MB (IV)'),('Höhere Mathematik II'),('Elementare PDE'),('LA für Physik und Lehramt'),('Analysis I'),('Mathe III ET'),('Mathe I für Informatik'),('Complex Analysis'),('Mathe & Statistik für Biologen'),('Mathe I für Maschinenbau'),('Mathe I für Bau'),('Nichtlineare Optimierung'),('Einführung in die Numerische Mathematik'),('Differentialgeometrie'),('Mathe I für ET'),('Mathe III (Bau)'),('W. Theorie'),('Gewöhnliche Differentialgleichungen'),('Geometrie für Lehramt'),('Mathe III MB'),('Statistik I für Humanwissenschaftler'),('Einführung in die Optimierung'),('Algebra'),('Lineare Algebra I'),('Höhere Mathematik 1'),('Darstellende Geometrie'),('Statistik 1 für WI'),('Diskrete Mathematik'),('Linear Algebra I (engl.)'),('Introduction to mathematical logic'),('Statistik I für WI'),('Weihnachtsknobelstraße'),('Numerische Lineare Algebra'),('Mathe IV (ET) / Mathe III (Inf) / Praktische Mathe (MEd)'),('Topologie'),('Linear Algebra II (engl.)'),('Einführung in die Finanzmathematik'),('Einführung in die mathematische Software'),('Mathematische Statistik'),('Algebraische Kurven'),('Analysis I (engl.)'),('Funktionalanalysis'),('Lebensversicherungsmathematik'),('Automaten, Formale Sprachen und Entscheidbarkeit (FGdI)'),('Mathematik für Chemiker'),('Numerik gewöhnlicher Differentialgleichungen'),('Darstellungstheorie'),('Aussagen- und Prädikatenlogik'),('Riemannsche Flächen'),('Mathematische Grundlagen der Quantenmechanik'),('Elementare Zahlentheorie'),('Einführung in die mathematische Modellierung'),('Stochastische Prozesse I'),('Mathematik im Kontext'),('Funktionalanalysis II'),('Mathematik IV (für ET) /Mathematik III (für Inf) /PraktischeMathematik (für M.Ed.Math)'),('Differentialgeometrie fuer VI'),('Probability Theory'),('Mathe für MINT'),('Mathematik als gemeinsame Sprache der Naturwissenschaften'),('Lineare Algebra I für Physiker'),('Manifolds'),('Kurvenschätzung'),('Spieltheorie'),('Einführung in die Programmierung'),('Algebraische Topologie'),('Schadenversicherungsmathematik'),('Partial Differential Equations I');
diff --git a/main.go b/main.go
index d2b00e4..30c6721 100644
--- a/main.go
+++ b/main.go
@@ -1,68 +1,27 @@
package main
import (
- "fmt"
- "html/template"
"net/http"
- "strconv"
+ "sprechstundentool/controllers"
+ "sprechstundentool/repositories"
+ "sprechstundentool/sqldb"
)
-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)
+ db := sqldb.ConnectDB()
- http.HandleFunc("/", root)
+ // Create repos
+ roomRepo := repositories.NewRoomRepo(db)
+ courseRepo := repositories.NewCourseRepo(db)
+ tutorRepo := repositories.NewTutorRepo(db)
+ officeHourRepo := repositories.NewOfficeHourRepo(db, roomRepo, tutorRepo, courseRepo)
+
+ h := controllers.NewBaseHandler(roomRepo, officeHourRepo, courseRepo, tutorRepo)
+
+ http.HandleFunc("/getByRoom", h.GetByRoomHandler)
+ http.HandleFunc("/getByCourse", h.GetByCourseHandler)
+
+ http.HandleFunc("/", h.RootHandler)
http.ListenAndServe(":8080", nil)
}
diff --git a/models/course.go b/models/course.go
new file mode 100644
index 0000000..42d80b5
--- /dev/null
+++ b/models/course.go
@@ -0,0 +1,14 @@
+// course
+package models
+
+type Course struct {
+ Id int
+ Name string
+}
+
+type CourseRepository interface {
+ FindByName(name string) (Course, error)
+ GetAll() ([]Course, error)
+ FindById(id int) (Course, error)
+ GetActive() ([]Course, error)
+}
diff --git a/date.go b/models/date.go
similarity index 57%
rename from date.go
rename to models/date.go
index be16b80..1b71272 100644
--- a/date.go
+++ b/models/date.go
@@ -1,8 +1,10 @@
// date
-package main
+package models
type Date struct {
Day int
Hour int
Minute int
}
+
+const MinuteGranularity int = 5
diff --git a/models/officeHour.go b/models/officeHour.go
new file mode 100644
index 0000000..aadf0ce
--- /dev/null
+++ b/models/officeHour.go
@@ -0,0 +1,23 @@
+// officeHour
+package models
+
+type OfficeHour struct {
+ Id int
+ Tutor Tutor
+ Week int
+ Date
+ Room Room
+ Course Course
+ Info string
+ Active bool
+ Duration int
+}
+
+type OfficeHourRepository interface {
+ FindById(id int) (OfficeHour, error)
+ FindByCourse(course Course) ([]OfficeHour, error)
+ FindByRoom(room Room) ([]OfficeHour, error)
+ GetAll() ([]OfficeHour, error)
+ Delete(officeHour OfficeHour) error
+ Add(officeHour OfficeHour) error
+}
diff --git a/models/room.go b/models/room.go
new file mode 100644
index 0000000..5bc2b6c
--- /dev/null
+++ b/models/room.go
@@ -0,0 +1,14 @@
+// raum
+package models
+
+type Room struct {
+ Id int
+ Name string
+ MaxOccupy int
+}
+
+type RoomRepository interface {
+ FindByName(name string) (Room, error)
+ GetAll() ([]Room, error)
+ FindById(id int) (Room, error)
+}
diff --git a/models/tutor.go b/models/tutor.go
new file mode 100644
index 0000000..2a317cd
--- /dev/null
+++ b/models/tutor.go
@@ -0,0 +1,15 @@
+// tutor
+package models
+
+type Tutor struct {
+ Id int
+ Name string
+ Email string
+}
+
+type TutorRepository interface {
+ FindByEmail(Email string) ([]Tutor, error)
+ FindById(Id int) (Tutor, error)
+ GetAll() ([]Tutor, error)
+ Add(tutor Tutor) error
+}
diff --git a/officeHour.go b/officeHour.go
deleted file mode 100644
index 08425f1..0000000
--- a/officeHour.go
+++ /dev/null
@@ -1,217 +0,0 @@
-// 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())
-}
diff --git a/repositories/course.go b/repositories/course.go
new file mode 100644
index 0000000..afc02f2
--- /dev/null
+++ b/repositories/course.go
@@ -0,0 +1,67 @@
+// course
+package repositories
+
+import (
+ "database/sql"
+ "sprechstundentool/models"
+)
+
+type CourseRepo struct {
+ db *sql.DB
+}
+
+func NewCourseRepo(db *sql.DB) *CourseRepo {
+ return &CourseRepo{
+ db: db,
+ }
+}
+
+func (r *CourseRepo) FindByName(name string) (models.Course, error) {
+ row := r.db.QueryRow("SELECT * FROM course WHERE name=?", name)
+ var course models.Course
+ if err := row.Scan(&course.Id, &course.Name); err != nil {
+ return models.Course{}, err
+ }
+ return course, nil
+}
+
+func (r *CourseRepo) FindById(id int) (models.Course, error) {
+ row := r.db.QueryRow("SELECT * FROM course WHERE id=?", id)
+ var course models.Course
+ if err := row.Scan(&course.Id, &course.Name); err != nil {
+ return models.Course{}, err
+ }
+ return course, nil
+}
+
+func (r *CourseRepo) GetAll() ([]models.Course, error) {
+ rows, err := r.db.Query("SELECT * FROM course")
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ return r.getFromRows(rows)
+}
+
+func (r *CourseRepo) GetActive() ([]models.Course, error) {
+ rows, err := r.db.Query("SELECT * FROM course WHERE active")
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ return r.getFromRows(rows)
+}
+
+func (r *CourseRepo) getFromRows(rows *sql.Rows) ([]models.Course, error) {
+ var courses []models.Course
+ for rows.Next() {
+ var course models.Course
+ if err := rows.Scan(&course.Id, &course.Name); err != nil {
+ return courses, err
+ }
+ courses = append(courses, course)
+ }
+ return courses, nil
+}
diff --git a/repositories/officeHour.go b/repositories/officeHour.go
new file mode 100644
index 0000000..5e142d1
--- /dev/null
+++ b/repositories/officeHour.go
@@ -0,0 +1,95 @@
+// officeHour
+package repositories
+
+import (
+ "database/sql"
+ "sprechstundentool/models"
+)
+
+type OfficeHourRepo struct {
+ db *sql.DB
+ roomRepo *RoomRepo
+ tutorRepo *TutorRepo
+ courseRepo *CourseRepo
+}
+
+func NewOfficeHourRepo(db *sql.DB, roomRepo *RoomRepo, tutorRepo *TutorRepo, courseRepo *CourseRepo) *OfficeHourRepo {
+ return &OfficeHourRepo{
+ db: db,
+ roomRepo: roomRepo,
+ tutorRepo: tutorRepo,
+ courseRepo: courseRepo,
+ }
+}
+
+func (r *OfficeHourRepo) GetAll() ([]models.OfficeHour, error) {
+ rows, err := r.db.Query("SELECT * FROM officeHour")
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+ return r.getFromRows(rows)
+}
+
+func (r *OfficeHourRepo) FindByCourse(course models.Course) ([]models.OfficeHour, error) {
+ rows, err := r.db.Query("SELECT * FROM officeHour WHERE course=?", course.Id)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+ return r.getFromRows(rows)
+}
+
+func (r *OfficeHourRepo) FindByRoom(room models.Room) ([]models.OfficeHour, error) {
+ rows, err := r.db.Query("SELECT * FROM officeHour WHERE room=?", room.Id)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+ return r.getFromRows(rows)
+}
+
+func (r *OfficeHourRepo) FindById(id int) (models.OfficeHour, error) {
+ return r.getFromRow(r.db.QueryRow("SELECT * FROM officeHour WHERE id=?", id))
+
+}
+
+func (r *OfficeHourRepo) Add(officeHour models.OfficeHour) error {
+ return nil
+}
+
+func (r *OfficeHourRepo) Delete(officeHour models.OfficeHour) error {
+ return nil
+}
+
+func (r *OfficeHourRepo) getFromRow(row *sql.Row) (models.OfficeHour, error) {
+ var officeHour models.OfficeHour
+ var day, hour, minute, tutorid int
+ var roomName, courseName string
+ err := row.Scan(&officeHour.Id, &tutorid, &day, &hour, &minute, &roomName, &courseName, &officeHour.Week, &officeHour.Info, &officeHour.Active, &officeHour.Duration)
+ if err != nil {
+ return models.OfficeHour{}, err
+ }
+ officeHour.Date = models.Date{day, hour, minute}
+ officeHour.Room, _ = r.roomRepo.FindByName(roomName)
+ officeHour.Tutor, _ = r.tutorRepo.FindById(tutorid)
+ officeHour.Course, _ = r.courseRepo.FindByName(courseName)
+ return officeHour, nil
+}
+
+func (r *OfficeHourRepo) getFromRows(rows *sql.Rows) ([]models.OfficeHour, error) {
+ var officeHours []models.OfficeHour
+ for rows.Next() {
+ var officeHour models.OfficeHour
+ var day, hour, minute, tutorId, roomId, courseId int
+ if err := rows.Scan(&officeHour.Id, &tutorId, &day, &hour, &minute, &roomId, &courseId, &officeHour.Week, &officeHour.Info, &officeHour.Active, &officeHour.Duration); err != nil {
+ return officeHours, err
+ }
+ officeHour.Date = models.Date{day, hour, minute}
+ officeHour.Room, _ = r.roomRepo.FindById(roomId)
+ officeHour.Tutor, _ = r.tutorRepo.FindById(tutorId)
+ officeHour.Course, _ = r.courseRepo.FindById(courseId)
+ officeHours = append(officeHours, officeHour)
+ }
+ return officeHours, nil
+}
diff --git a/repositories/room.go b/repositories/room.go
new file mode 100644
index 0000000..63f434b
--- /dev/null
+++ b/repositories/room.go
@@ -0,0 +1,59 @@
+// raum
+package repositories
+
+import (
+ "database/sql"
+ "sprechstundentool/models"
+)
+
+type RoomRepo struct {
+ db *sql.DB
+}
+
+func NewRoomRepo(db *sql.DB) *RoomRepo {
+ return &RoomRepo{
+ db: db,
+ }
+}
+
+func (r *RoomRepo) FindByName(name string) (models.Room, error) {
+ row := r.db.QueryRow("SELECT * FROM room WHERE name=?", name)
+ var room models.Room
+ if err := row.Scan(&room.Name, &room.MaxOccupy); err != nil {
+ return models.Room{}, err
+ }
+ return room, nil
+}
+
+func (r *RoomRepo) FindById(id int) (models.Room, error) {
+ row := r.db.QueryRow("SELECT * FROM room WHERE id=?", id)
+ var room models.Room
+ if err := row.Scan(&room.Id, &room.Name, &room.MaxOccupy); err != nil {
+ return models.Room{}, err
+ }
+ return room, nil
+}
+
+func (r *RoomRepo) GetAll() ([]models.Room, error) {
+ rows, err := r.db.Query("SELECT * FROM room")
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ var rooms []models.Room
+ for rows.Next() {
+ var room models.Room
+ if err := rows.Scan(&room.Id, &room.Name, &room.MaxOccupy); err != nil {
+ return rooms, err
+ }
+ rooms = append(rooms, room)
+ }
+ return rooms, nil
+}
+func (r *RoomRepo) Save(room models.Room) error {
+ return nil
+}
+func (r *RoomRepo) Add(room models.Room) error {
+ return nil
+}
diff --git a/repositories/tutor.go b/repositories/tutor.go
new file mode 100644
index 0000000..f78b702
--- /dev/null
+++ b/repositories/tutor.go
@@ -0,0 +1,68 @@
+// tutor
+package repositories
+
+import (
+ "database/sql"
+ "sprechstundentool/models"
+)
+
+type TutorRepo struct {
+ db *sql.DB
+}
+
+func NewTutorRepo(db *sql.DB) *TutorRepo {
+ return &TutorRepo{
+ db: db,
+ }
+}
+
+func (r *TutorRepo) FindByEmail(email string) ([]models.Tutor, error) {
+ rows, err := r.db.Query("SELECT * FROM tutor WHERE email=?", email)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ var tutors []models.Tutor
+ for rows.Next() {
+ var tutor models.Tutor
+ if err := rows.Scan(&tutor.Id, &tutor.Name, &tutor.Email); err != nil {
+ return tutors, err
+ }
+ tutors = append(tutors, tutor)
+ }
+ return tutors, nil
+}
+
+func (r *TutorRepo) FindById(id int) (models.Tutor, error) {
+ row := r.db.QueryRow("SELECT * FROM tutor WHERE id=?", id)
+ var tutor models.Tutor
+ if err := row.Scan(&tutor.Id, &tutor.Name, &tutor.Email); err != nil {
+ return models.Tutor{}, err
+ }
+ return tutor, nil
+}
+
+func (r *TutorRepo) GetAll() ([]models.Tutor, error) {
+ rows, err := r.db.Query("SELECT * FROM tutor")
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ var tutors []models.Tutor
+ for rows.Next() {
+ var tutor models.Tutor
+ if err := rows.Scan(&tutor.Id, &tutor.Name, &tutor.Email); err != nil {
+ return tutors, err
+ }
+ tutors = append(tutors, tutor)
+ }
+ return tutors, nil
+}
+func (r *TutorRepo) Save(tutor models.Tutor) error {
+ return nil
+}
+func (r *TutorRepo) Add(tutor models.Tutor) error {
+ return nil
+}
diff --git a/room.go b/room.go
deleted file mode 100644
index 1022fc4..0000000
--- a/room.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// 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}}
-}
diff --git a/sqldb/sqldb.go b/sqldb/sqldb.go
new file mode 100644
index 0000000..5596e81
--- /dev/null
+++ b/sqldb/sqldb.go
@@ -0,0 +1,17 @@
+package sqldb
+
+import (
+ "database/sql"
+
+ _ "github.com/mattn/go-sqlite3"
+)
+
+// ConnectDB opens a connection to the database
+func ConnectDB() *sql.DB {
+ db, err := sql.Open("sqlite3", "sprechstunden.db")
+ if err != nil {
+ panic(err.Error())
+ }
+
+ return db
+}
diff --git a/sqlite.sql b/sqlite.sql
new file mode 100644
index 0000000..d4569e9
--- /dev/null
+++ b/sqlite.sql
@@ -0,0 +1,62 @@
+--
+-- Table structure for table `room`
+--
+
+DROP TABLE IF EXISTS `room`;
+CREATE TABLE `room` (
+ `id` INTEGER PRIMARY KEY,
+ `name` text NOT NULL,
+ `max_occupy` int DEFAULT NULL
+);
+
+--
+-- Table structure for table `request`
+--
+
+DROP TABLE IF EXISTS `request`;
+CREATE TABLE `request` (
+ `id` INTEGER PRIMARY KEY,
+ `officeHour` int DEFAULT NULL,
+ `type` int DEFAULT NULL,
+ `code` text DEFAULT NULL
+);
+
+--
+-- Table structure for table `officeHour`
+--
+
+DROP TABLE IF EXISTS `officeHour`;
+CREATE TABLE `officeHour` (
+ `id` INTEGER PRIMARY KEY,
+ `tutor` int DEFAULT NULL,
+ `day` int DEFAULT NULL,
+ `hour` int DEFAULT NULL,
+ `minute` int DEFAULT NULL,
+ `room` int DEFAULT NULL,
+ `course` int DEFAULT NULL,
+ `week` int DEFAULT NULL,
+ `info` text DEFAULT NULL,
+ `active` bool DEFAULT NULL,
+ `duration` int DEFAULT NULL
+);
+
+--
+-- Table structure for table `tutor`
+--
+
+DROP TABLE IF EXISTS `tutor`;
+CREATE TABLE `tutor` (
+ `id` INTEGER PRIMARY KEY,
+ `name` tinytext DEFAULT NULL,
+ `email` tinytext DEFAULT NULL
+);
+
+--
+-- Table structure for table `course`
+--
+
+DROP TABLE IF EXISTS `course`;
+CREATE TABLE `course` (
+ `id` INTEGER PRIMARY KEY,
+ `name` varchar(255) DEFAULT NULL
+);
diff --git a/templates/index.html b/templates/index.html
index c02cd48..48344c7 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -6,7 +6,7 @@