Skip to content

Commit edd85f9

Browse files
committed
feat: add external time handling for exams from other faculties
1 parent 42ad455 commit edd85f9

9 files changed

Lines changed: 216 additions & 18 deletions

File tree

cmd/plan.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"log"
77
"os"
88
"strconv"
9+
"time"
910

1011
"github.com/spf13/cobra"
1112
)
@@ -18,6 +19,7 @@ var (
1819
pre-plan-exam ancode day slot --- move [ancode] to [day number] [slot number]
1920
pre-plan-room ancode roomname [mtknr/reserve] --- plan [room name] for [ancode]
2021
move-to ancode day slot --- move [ancode] to [day number] [slot number]
22+
other-fk ancode time --- plan [ancode] from other faculty to [time]
2123
change-room ancode oldroom newroom --- change room for [ancode] from [oldroom] to [newroom]
2224
lock-exam ancode --- lock exam to slot
2325
unlock-exam ancode --- unlock / allow moving
@@ -80,6 +82,33 @@ var (
8082
log.Fatalf("got error: %v\n", err)
8183
}
8284
fmt.Println(str)
85+
case "other-fk":
86+
if len(args) < 3 {
87+
log.Fatal("need ancode, time")
88+
}
89+
ancode, err := strconv.Atoi(args[1])
90+
if err != nil {
91+
log.Fatalf("cannot convert %s to int", args[1])
92+
}
93+
slottime, err := time.ParseInLocation("02.01.06,15:04", args[2], time.Local)
94+
if err != nil {
95+
log.Fatalf("cannot convert \"%s\" to time, must be in format \"02.01.06,15:04\"\n", args[2])
96+
}
97+
98+
success, err := plexams.AddExamToSlottime(context.Background(), ancode, slottime)
99+
100+
if err != nil {
101+
fmt.Printf("error: %v\n", err)
102+
os.Exit(1)
103+
}
104+
if success {
105+
fmt.Printf("successfully moved exam %d to (%s)\n", ancode, slottime.String())
106+
}
107+
str, err := plexams.ExamInfo(ancode)
108+
if err != nil {
109+
log.Fatalf("got error: %v\n", err)
110+
}
111+
fmt.Println(str)
83112

84113
case "pre-plan-room":
85114
if len(args) < 3 {

db/generatedExams.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func (db *DB) GetGeneratedExam(ctx context.Context, ancode int) (*model.Generate
7979

8080
res := collection.FindOne(ctx, bson.D{{Key: "ancode", Value: ancode}})
8181
if res.Err() != nil {
82-
log.Error().Err(res.Err()).Int("ancode", ancode).Msg("cannot get generated exam")
82+
log.Debug().Err(res.Err()).Int("ancode", ancode).Msg("cannot get generated exam")
8383
return nil, res.Err()
8484
}
8585

graph/generated/generated.go

Lines changed: 63 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

graph/model/plan.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package model
22

3+
import "time"
4+
35
type PlanEntry struct {
4-
DayNumber int `json:"dayNumber"`
5-
SlotNumber int `json:"slotNumber"`
6-
Ancode int `json:"ancode"`
7-
Locked bool `json:"locked"`
6+
DayNumber int `json:"dayNumber"`
7+
SlotNumber int `json:"slotNumber"`
8+
ExternalTime *time.Time `json:"externalTime"`
9+
Ancode int `json:"ancode"`
10+
Locked bool `json:"locked"`
811
}

graph/plan.graphqls

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ type PlanEntry {
5757
dayNumber: Int!
5858
slotNumber: Int!
5959
starttime: Time!
60+
externalTime: Time # only for exams from other faculties
6061
ancode: Int!
6162
locked: Boolean!
6263
}

plexams/exam.go

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -243,19 +243,44 @@ func (p *Plexams) ConnectExam(ancode int, program string) error {
243243

244244
func (p *Plexams) ExamInfo(ancode int) (string, error) {
245245
ctx := context.Background()
246+
found := false
246247
exam, err := p.PlannedExam(ctx, ancode)
248+
module, mainExamer := "", ""
249+
var planEntry *model.PlanEntry
247250
if err != nil {
248-
return "", err
251+
exam, err := p.GetZpaExamByAncode(ctx, ancode)
252+
if err != nil {
253+
// TODO: maybe external exam?
254+
} else {
255+
found = true
256+
module = exam.Module
257+
mainExamer = exam.MainExamer
258+
planEntry, err = p.dbClient.PlanEntry(ctx, ancode)
259+
if err != nil {
260+
log.Debug().Int("ancode", ancode).
261+
Msg("not planned yet")
262+
}
263+
}
264+
} else {
265+
found = true
266+
module = exam.ZpaExam.Module
267+
mainExamer = exam.ZpaExam.MainExamer
268+
planEntry = exam.PlanEntry
249269
}
250-
if exam == nil {
251-
return "", fmt.Errorf("no planned exam for ancode %d", ancode)
270+
271+
if !found {
272+
return fmt.Sprintf("no exam for ancode %d found", ancode), nil
252273
}
274+
253275
var sb strings.Builder
254276

255-
fmt.Fprintf(&sb, "%5d. %s (%s)", exam.Ancode, exam.ZpaExam.Module, exam.ZpaExam.MainExamer)
256-
if exam.PlanEntry != nil {
257-
starttime := p.getSlotTime(exam.PlanEntry.DayNumber, exam.PlanEntry.SlotNumber)
258-
fmt.Fprintf(&sb, "\n Termin: %s (Tag %d / Slot %d)", starttime.Local().Format("02.01.06, 15:04 Uhr"), exam.PlanEntry.DayNumber, exam.PlanEntry.SlotNumber)
277+
fmt.Fprintf(&sb, "%5d. %s (%s)", ancode, module, mainExamer)
278+
if planEntry != nil {
279+
starttime := p.getSlotTime(planEntry.DayNumber, planEntry.SlotNumber)
280+
if planEntry.ExternalTime != nil {
281+
starttime = *planEntry.ExternalTime
282+
}
283+
fmt.Fprintf(&sb, "\n Termin: %s (Tag %d / Slot %d)", starttime.Local().Format("02.01.06, 15:04 Uhr"), planEntry.DayNumber, planEntry.SlotNumber)
259284
} else {
260285
sb.WriteString("\n Termin: fehlt")
261286
}

plexams/plan.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,48 @@ import (
1111
"github.com/rs/zerolog/log"
1212
)
1313

14+
func (p *Plexams) AddExamToSlottime(ctx context.Context, ancode int, time time.Time) (bool, error) {
15+
exam, err := p.GetZpaExamByAncode(ctx, ancode)
16+
duration := 90 // good default
17+
if err != nil {
18+
// TODO: maybe external exam?
19+
} else {
20+
// ZPA exam
21+
constraints, err := p.ConstraintForAncode(ctx, ancode)
22+
if err != nil {
23+
log.Error().Err(err).Int("ancode", ancode).
24+
Msg("error while trying to get constraints")
25+
return false, err
26+
}
27+
if !constraints.NotPlannedByMe {
28+
err := fmt.Errorf("add exam to slot time is only allowed for exams not planned by me")
29+
return false, err
30+
}
31+
duration = exam.Duration
32+
}
33+
if exam == nil {
34+
err = fmt.Errorf("exam with ancode %d not found", ancode)
35+
return false, err
36+
}
37+
log.Debug().Str("module", exam.Module).Str("main-examer", exam.MainExamer).
38+
Msg("found exam")
39+
slot, err := p.getSlotForTime(time, duration)
40+
if err != nil {
41+
log.Error().Err(err).Time("slottime", time).
42+
Msg("no slot for slottime found")
43+
}
44+
log.Debug().Int("day", slot.DayNumber).Int("slot", slot.SlotNumber).
45+
Msg("found slot")
46+
47+
return p.dbClient.AddExamToSlot(ctx, &model.PlanEntry{
48+
DayNumber: slot.DayNumber,
49+
SlotNumber: slot.SlotNumber,
50+
ExternalTime: &time,
51+
Ancode: ancode,
52+
Locked: false,
53+
})
54+
}
55+
1456
func (p *Plexams) AddExamToSlot(ctx context.Context, ancode int, dayNumber int, timeNumber int, force bool) (bool, error) {
1557
var slot *model.Slot
1658

@@ -325,6 +367,13 @@ func (p *Plexams) PreExamsInSlot(ctx context.Context, day int, time int) ([]*mod
325367

326368
preExams := make([]*model.PreExam, 0, len(planEntries))
327369
for _, planEntry := range planEntries {
370+
371+
if planEntry.ExternalTime != nil {
372+
fmt.Printf("External Time = %s\n", planEntry.ExternalTime.String())
373+
} else {
374+
fmt.Println("no external time")
375+
}
376+
328377
exam, err := p.GetZPAExam(ctx, planEntry.Ancode)
329378
if err != nil {
330379
log.Error().Err(err).Int("ancode", planEntry.Ancode).Msg("cannot get exam")

plexams/plannedExams.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func (p *Plexams) PlanEntries(ctx context.Context) ([]*model.PlanEntry, error) {
2828
func (p *Plexams) PlannedExam(ctx context.Context, ancode int) (*model.PlannedExam, error) {
2929
exam, err := p.GeneratedExam(ctx, ancode)
3030
if err != nil {
31-
log.Error().Err(err).Int("ancode", ancode).Msg("cannot get generated exam")
31+
log.Debug().Err(err).Int("ancode", ancode).Msg("cannot get generated exam")
3232
return nil, err
3333
}
3434

plexams/plexams.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,39 @@ func (p *Plexams) getSlotTime(dayNumber, slotNumber int) time.Time {
337337
return time.Date(0, 0, 0, 0, 0, 0, 0, nil)
338338
}
339339

340+
func (p *Plexams) getSlotForTime(starttime time.Time, duration int) (*model.Slot, error) {
341+
var slotWithStarttimeInSlot, slotWithEndtimeInSlot *model.Slot
342+
endtime := starttime.Add(time.Duration(duration) * time.Minute)
343+
for _, slot := range p.semesterConfig.Slots {
344+
if starttime.After(slot.Starttime.Add(-1*time.Minute)) &&
345+
starttime.Before(slot.Starttime.Add(119*time.Minute)) {
346+
slotWithStarttimeInSlot = slot
347+
}
348+
if endtime.After(slot.Starttime.Add(-1*time.Minute)) &&
349+
endtime.Before(slot.Starttime.Add(119*time.Minute)) {
350+
slotWithEndtimeInSlot = slot
351+
}
352+
if slotWithStarttimeInSlot != nil &&
353+
slotWithEndtimeInSlot != nil {
354+
break
355+
}
356+
}
357+
358+
if slotWithStarttimeInSlot == nil {
359+
return slotWithEndtimeInSlot, nil
360+
}
361+
if slotWithEndtimeInSlot == nil {
362+
return slotWithStarttimeInSlot, nil
363+
}
364+
365+
minutesInEndtimeSlot := int(endtime.Sub(slotWithEndtimeInSlot.Starttime).Minutes())
366+
if minutesInEndtimeSlot > duration/2 {
367+
return slotWithEndtimeInSlot, nil
368+
}
369+
370+
return slotWithStarttimeInSlot, nil
371+
}
372+
340373
func (p *Plexams) PrintInfo() {
341374
fmt.Println(aurora.Sprintf(aurora.Magenta(" --- Planning Semester: %s --- \n"), p.semester))
342375
}

0 commit comments

Comments
 (0)