|
| 1 | +package plexams |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + "fmt" |
| 6 | + "time" |
| 7 | + |
| 8 | + "github.com/logrusorgru/aurora" |
| 9 | + "github.com/obcode/plexams.go/graph/model" |
| 10 | + "github.com/rs/zerolog/log" |
| 11 | + "github.com/theckman/yacspin" |
| 12 | +) |
| 13 | + |
| 14 | +func (p *Plexams) ValidatePrePlannedExahmRooms() error { |
| 15 | + ctx := context.Background() |
| 16 | + cfg := yacspin.Config{ |
| 17 | + Frequency: 100 * time.Millisecond, |
| 18 | + CharSet: yacspin.CharSets[69], |
| 19 | + Suffix: aurora.Sprintf(aurora.Cyan(" validating pre-planned exahm rooms (booked and enough seats)")), |
| 20 | + SuffixAutoColon: true, |
| 21 | + StopCharacter: "✓", |
| 22 | + StopColors: []string{"fgGreen"}, |
| 23 | + StopFailMessage: "error", |
| 24 | + StopFailCharacter: "✗", |
| 25 | + StopFailColors: []string{"fgRed"}, |
| 26 | + } |
| 27 | + |
| 28 | + spinner, err := yacspin.New(cfg) |
| 29 | + if err != nil { |
| 30 | + log.Debug().Err(err).Msg("cannot create spinner") |
| 31 | + } |
| 32 | + err = spinner.Start() |
| 33 | + if err != nil { |
| 34 | + log.Debug().Err(err).Msg("cannot start spinner") |
| 35 | + } |
| 36 | + |
| 37 | + validationMessages := make([]string, 0) |
| 38 | + |
| 39 | + exams := make([]*model.GeneratedExam, 0) |
| 40 | + generatedExams, err := p.dbClient.GetGeneratedExams(ctx) |
| 41 | + if err != nil { |
| 42 | + log.Error().Err(err). |
| 43 | + Msg("cannot get generated exams") |
| 44 | + return err |
| 45 | + } |
| 46 | + |
| 47 | + for _, exam := range generatedExams { |
| 48 | + if exam.Constraints != nil && exam.Constraints.RoomConstraints != nil && |
| 49 | + (exam.Constraints.RoomConstraints.Exahm || exam.Constraints.RoomConstraints.Seb) { |
| 50 | + exams = append(exams, exam) |
| 51 | + } |
| 52 | + } |
| 53 | + |
| 54 | + rooms, err := p.Rooms(ctx) |
| 55 | + if err != nil { |
| 56 | + log.Error().Err(err). |
| 57 | + Msg("cannot get rooms") |
| 58 | + } |
| 59 | + roomsMap := make(map[string]*model.Room) |
| 60 | + for _, room := range rooms { |
| 61 | + roomsMap[room.Name] = room |
| 62 | + } |
| 63 | + |
| 64 | + for _, exam := range exams { |
| 65 | + prePlannedRooms, err := p.dbClient.PrePlannedRoomsForExam(ctx, exam.Ancode) |
| 66 | + if err != nil { |
| 67 | + log.Error().Err(err). |
| 68 | + Int("ancode", exam.Ancode). |
| 69 | + Msg("error while trying to get prePlannedRooms") |
| 70 | + } |
| 71 | + for _, prePlannedRoom := range prePlannedRooms { |
| 72 | + room := roomsMap[prePlannedRoom.RoomName] |
| 73 | + if exam.Constraints.RoomConstraints.Seb && !room.Seb { |
| 74 | + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("Room %s for %d. %s (%s) is not SEB-Room"), |
| 75 | + aurora.Magenta(room.Name), aurora.Cyan(exam.Ancode), aurora.Cyan(exam.ZpaExam.Module), aurora.Cyan(exam.ZpaExam.MainExamer))) |
| 76 | + } |
| 77 | + |
| 78 | + if exam.Constraints.RoomConstraints.Exahm && !room.Exahm { |
| 79 | + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("Room %s for %d. %s (%s) is not EXaHM-Room"), |
| 80 | + aurora.Magenta(room.Name), aurora.Cyan(exam.Ancode), aurora.Cyan(exam.ZpaExam.Module), aurora.Cyan(exam.ZpaExam.MainExamer))) |
| 81 | + } |
| 82 | + } |
| 83 | + |
| 84 | + // check if exam is planned in this slot if room is allowed |
| 85 | + planEntry, err := p.dbClient.PlanEntry(ctx, exam.Ancode) |
| 86 | + if err != nil { |
| 87 | + log.Error().Err(err). |
| 88 | + Int("ancode", exam.Ancode). |
| 89 | + Msg("cannot get plan entry for exam") |
| 90 | + } |
| 91 | + if planEntry == nil { |
| 92 | + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("Exam %d. %s (%s) has no plan entry yet"), |
| 93 | + aurora.Cyan(exam.Ancode), aurora.Cyan(exam.ZpaExam.Module), aurora.Cyan(exam.ZpaExam.MainExamer))) |
| 94 | + } else { |
| 95 | + roomsForSlot, err := p.RoomsForSlot(ctx, planEntry.DayNumber, planEntry.SlotNumber) |
| 96 | + if err != nil { |
| 97 | + log.Error().Err(err). |
| 98 | + Int("day", planEntry.DayNumber). |
| 99 | + Int("slot", planEntry.SlotNumber). |
| 100 | + Msg("cannot rooms for slot") |
| 101 | + } |
| 102 | + for _, prePlannedRoom := range prePlannedRooms { |
| 103 | + found := false |
| 104 | + for _, roomInSlot := range roomsForSlot.RoomNames { |
| 105 | + if prePlannedRoom.RoomName == roomInSlot { |
| 106 | + found = true |
| 107 | + break |
| 108 | + } |
| 109 | + } |
| 110 | + if !found { |
| 111 | + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("Room %s for Exam %d. %s (%s) in slot (%d/%d) is not allowed"), |
| 112 | + aurora.Magenta(prePlannedRoom.RoomName), aurora.Cyan(exam.Ancode), aurora.Cyan(exam.ZpaExam.Module), aurora.Cyan(exam.ZpaExam.MainExamer), |
| 113 | + aurora.Blue(planEntry.DayNumber), aurora.Blue(planEntry.SlotNumber))) |
| 114 | + } |
| 115 | + } |
| 116 | + } |
| 117 | + |
| 118 | + // check if rooms have enough seats |
| 119 | + seats := 0 |
| 120 | + for _, prePlannedRoom := range prePlannedRooms { |
| 121 | + room := roomsMap[prePlannedRoom.RoomName] |
| 122 | + seats += room.Seats |
| 123 | + } |
| 124 | + if seats < exam.StudentRegsCount { |
| 125 | + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("Not enough seats for Exam %d. %s (%s): %d seats planned, but %d students"), |
| 126 | + aurora.Cyan(exam.Ancode), aurora.Cyan(exam.ZpaExam.Module), aurora.Cyan(exam.ZpaExam.MainExamer), |
| 127 | + aurora.Cyan(seats), aurora.Cyan(exam.StudentRegsCount))) |
| 128 | + } |
| 129 | + } |
| 130 | + |
| 131 | + if len(validationMessages) > 0 { |
| 132 | + spinner.StopFailMessage(aurora.Sprintf(aurora.Red("%d problems found"), len(validationMessages))) |
| 133 | + err = spinner.StopFail() |
| 134 | + if err != nil { |
| 135 | + log.Debug().Err(err).Msg("cannot stop spinner") |
| 136 | + } |
| 137 | + for _, msg := range validationMessages { |
| 138 | + fmt.Printf(" ↪ %s\n", msg) |
| 139 | + } |
| 140 | + |
| 141 | + } else { |
| 142 | + err = spinner.Stop() |
| 143 | + if err != nil { |
| 144 | + log.Debug().Err(err).Msg("cannot stop spinner") |
| 145 | + } |
| 146 | + } |
| 147 | + |
| 148 | + return nil |
| 149 | +} |
0 commit comments