From b0823177df4d661598af03986012ebe9658f7a33 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Wed, 12 Jul 2023 15:14:51 +0200 Subject: [PATCH 01/78] change zpa exams to plan --- README.md | 31 ++--- db/cli/main.go | 10 +- db/collection.go | 11 +- db/constraints.go | 22 +-- db/database.go | 2 +- db/exam.go | 24 ++-- db/examgroup.go | 8 +- db/log.go | 2 +- db/mongo.go | 24 ++-- db/nta.go | 6 +- db/plan.go | 22 +-- db/prepare_studentregs.go | 4 +- db/primuss.go | 2 +- db/primuss_studentregs.go | 4 +- db/rooms.go | 2 +- db/studentregs.go | 6 +- db/zpa.go | 6 +- db/zpa_exams.go | 257 ++++++++++++++++------------------- graph/generated/generated.go | 38 ++---- graph/mutation.graphqls | 4 +- graph/mutation.resolvers.go | 10 +- graph/primuss.resolvers.go | 2 +- graph/query.resolvers.go | 2 +- graph/room.resolvers.go | 2 +- plexams/plexams.go | 10 +- plexams/prepare.go | 8 +- plexams/zpa_get.go | 16 +-- 27 files changed, 251 insertions(+), 284 deletions(-) diff --git a/README.md b/README.md index 8688585..3fc05a9 100644 --- a/README.md +++ b/README.md @@ -3,22 +3,17 @@ # plexams.go -Rewrite of obcode/plexams in Go - -## Config `plexams.yaml` - -## Run GraphQL server - -``` -plexams.go server -``` - -## Fetch from ZPA - -``` -plexams.go zpa teacher -``` - -``` -plexams.go zpa exams +- Import aus ZPA -- daher nicht verändern! + - teachers + - zpaexams + +```mermaid +erDiagram + teachers + zpaexams + zpaexamsToPlan { + int ancode + bool toPlan + } + zpaexams ||--|| zpaexamsToPlan: references ``` diff --git a/db/cli/main.go b/db/cli/main.go index 49cabf8..f6ed868 100644 --- a/db/cli/main.go +++ b/db/cli/main.go @@ -16,7 +16,15 @@ func main() { panic(fmt.Errorf("fatal error config file: %w", err)) } - client, _ := db.NewDB(viper.GetString("db.uri"), viper.GetString("semester")) + dbName := viper.GetString("db.database") + var databaseName *string + if dbName == "" { + databaseName = nil + } else { + databaseName = &dbName + } + + client, _ := db.NewDB(viper.GetString("db.uri"), viper.GetString("semester"), databaseName) semester, _ := client.AllSemesterNames() diff --git a/db/collection.go b/db/collection.go index 256b4b0..5903699 100644 --- a/db/collection.go +++ b/db/collection.go @@ -25,9 +25,8 @@ const ( collectionStudentRegsPerStudentPlanned = "studentregs_per_student_planned" collectionStudentRegsPerStudentAll = "studentregs_per_student_all" - collectionAll = "zpaexams" - collectionToPlan = "zpaexams-to-plan" - collectionNotToPlan = "zpaexams-not-to-plan" + collectionAll = "zpaexams" + collectionToPlan = "zpaexamsToPlan" collectionExamsInPlan = "exams_in_plan" @@ -50,13 +49,13 @@ const ( ) func (db *DB) getCollection(program string, primussType PrimussType) *mongo.Collection { - return db.Client.Database(databaseName(db.semester)).Collection(fmt.Sprintf("%s_%s", primussType, program)) + return db.Client.Database(db.databaseName).Collection(fmt.Sprintf("%s_%s", primussType, program)) } func (db *DB) getCollectionSemester(collectionName string) *mongo.Collection { - return db.Client.Database(databaseName(db.semester)).Collection(collectionName) + return db.Client.Database(db.databaseName).Collection(collectionName) } func (db *DB) getCollectionSemesterFromContext(ctx context.Context) *mongo.Collection { - return db.Client.Database(databaseName(db.semester)).Collection(ctx.Value(CollectionName("collectionName")).(string)) + return db.Client.Database(db.databaseName).Collection(ctx.Value(CollectionName("collectionName")).(string)) } diff --git a/db/constraints.go b/db/constraints.go index 2d4d717..11b7f5a 100644 --- a/db/constraints.go +++ b/db/constraints.go @@ -26,7 +26,7 @@ func (db *DB) NotPlannedByMe(ctx context.Context, ancode int) (bool, error) { constraint.NotPlannedByMe = true - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionConstraints) + collection := db.Client.Database(db.databaseName).Collection(collectionConstraints) if update { _, err = collection.ReplaceOne(ctx, bson.D{{Key: "ancode", Value: ancode}}, constraint) } else { @@ -54,7 +54,7 @@ func (db *DB) Online(ctx context.Context, ancode int) (bool, error) { constraint.Online = true - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionConstraints) + collection := db.Client.Database(db.databaseName).Collection(collectionConstraints) if update { _, err = collection.ReplaceOne(ctx, bson.D{{Key: "ancode", Value: ancode}}, constraint) } else { @@ -82,7 +82,7 @@ func (db *DB) ExcludeDays(ctx context.Context, ancode int, days []*time.Time) (b constraint.ExcludeDays = days - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionConstraints) + collection := db.Client.Database(db.databaseName).Collection(collectionConstraints) if update { _, err = collection.ReplaceOne(ctx, bson.D{{Key: "ancode", Value: ancode}}, constraint) @@ -111,7 +111,7 @@ func (db *DB) PossibleDays(ctx context.Context, ancode int, days []*time.Time) ( constraint.PossibleDays = days - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionConstraints) + collection := db.Client.Database(db.databaseName).Collection(collectionConstraints) if update { _, err = collection.ReplaceOne(ctx, bson.D{{Key: "ancode", Value: ancode}}, constraint) @@ -157,7 +157,7 @@ func (db *DB) SameSlot(ctx context.Context, ancode int, ancodes []int) (bool, er sort.Ints(list) constraint.SameSlot = list - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionConstraints) + collection := db.Client.Database(db.databaseName).Collection(collectionConstraints) if update { _, err = collection.ReplaceOne(ctx, bson.D{{Key: "ancode", Value: ancode}}, constraint) } else { @@ -188,7 +188,7 @@ func (db *DB) PlacesWithSockets(ctx context.Context, ancode int) (bool, error) { constraint.RoomConstraints.PlacesWithSocket = true - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionConstraints) + collection := db.Client.Database(db.databaseName).Collection(collectionConstraints) if update { _, err = collection.ReplaceOne(ctx, bson.D{{Key: "ancode", Value: ancode}}, constraint) } else { @@ -219,7 +219,7 @@ func (db *DB) Lab(ctx context.Context, ancode int) (bool, error) { constraint.RoomConstraints.Lab = true - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionConstraints) + collection := db.Client.Database(db.databaseName).Collection(collectionConstraints) if update { _, err = collection.ReplaceOne(ctx, bson.D{{Key: "ancode", Value: ancode}}, constraint) } else { @@ -250,7 +250,7 @@ func (db *DB) ExahmRooms(ctx context.Context, ancode int) (bool, error) { constraint.RoomConstraints.ExahmRooms = true - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionConstraints) + collection := db.Client.Database(db.databaseName).Collection(collectionConstraints) if update { _, err = collection.ReplaceOne(ctx, bson.D{{Key: "ancode", Value: ancode}}, constraint) } else { @@ -281,7 +281,7 @@ func (db *DB) SafeExamBrowser(ctx context.Context, ancode int) (bool, error) { constraint.RoomConstraints.Seb = true - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionConstraints) + collection := db.Client.Database(db.databaseName).Collection(collectionConstraints) if update { _, err = collection.ReplaceOne(ctx, bson.D{{Key: "ancode", Value: ancode}}, constraint) } else { @@ -295,7 +295,7 @@ func (db *DB) SafeExamBrowser(ctx context.Context, ancode int) (bool, error) { } func (db *DB) GetConstraintsForAncode(ctx context.Context, ancode int) (*model.Constraints, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionConstraints) + collection := db.Client.Database(db.databaseName).Collection(collectionConstraints) var constraint model.Constraints res := collection.FindOne(ctx, bson.D{{Key: "ancode", Value: ancode}}) @@ -313,7 +313,7 @@ func (db *DB) GetConstraintsForAncode(ctx context.Context, ancode int) (*model.C } func (db *DB) GetConstraints(ctx context.Context) ([]*model.Constraints, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionConstraints) + collection := db.Client.Database(db.databaseName).Collection(collectionConstraints) constraints := make([]*model.Constraints, 0) diff --git a/db/database.go b/db/database.go index 3bcf434..ba83afa 100644 --- a/db/database.go +++ b/db/database.go @@ -41,7 +41,7 @@ func (db *DB) AllSemesterNames() ([]*model.Semester, error) { } func (db *DB) SaveSemesterConfig(ctx context.Context, semesterConfig *model.SemesterConfig) error { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNameSemesterConfig) + collection := db.Client.Database(db.databaseName).Collection(collectionNameSemesterConfig) err := collection.Drop(ctx) if err != nil { diff --git a/db/exam.go b/db/exam.go index 1c99c3a..24a716d 100644 --- a/db/exam.go +++ b/db/exam.go @@ -12,7 +12,7 @@ import ( ) func (db *DB) AddAdditionalExam(ctx context.Context, exam model.AdditionalExamInput) (bool, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNameAdditionalExams) + collection := db.Client.Database(db.databaseName).Collection(collectionNameAdditionalExams) _, err := collection.InsertOne(ctx, exam) if err != nil { return false, err @@ -22,7 +22,7 @@ func (db *DB) AddAdditionalExam(ctx context.Context, exam model.AdditionalExamIn } func (db *DB) AdditionalExams(ctx context.Context) ([]*model.AdditionalExam, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNameAdditionalExams) + collection := db.Client.Database(db.databaseName).Collection(collectionNameAdditionalExams) exams := make([]*model.AdditionalExam, 0) @@ -58,7 +58,7 @@ func (db *DB) AdditionalExams(ctx context.Context) ([]*model.AdditionalExam, err } func (db *DB) ExamsAlreadyPrepared(ctx context.Context) bool { - collection := db.Client.Database(databaseName(db.semester)).Collection("exams") + collection := db.Client.Database(db.databaseName).Collection("exams") docsCount, err := collection.CountDocuments(ctx, bson.D{}) if err != nil { @@ -69,7 +69,7 @@ func (db *DB) ExamsAlreadyPrepared(ctx context.Context) bool { } func (db *DB) AddExam(ctx context.Context, exam *model.Exam) error { - collection := db.Client.Database(databaseName(db.semester)).Collection("exams") + collection := db.Client.Database(db.databaseName).Collection("exams") result := collection.FindOne(ctx, bson.D{{Key: "ancode", Value: exam.AnCode}}) if result.Err() == nil { @@ -89,7 +89,7 @@ func (db *DB) AddExam(ctx context.Context, exam *model.Exam) error { } func (db *DB) SaveConnectedExam(ctx context.Context, exam *model.ConnectedExam) error { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNameConnectedExams) + collection := db.Client.Database(db.databaseName).Collection(collectionNameConnectedExams) _, err := collection.InsertOne(ctx, exam) if err != nil { @@ -103,7 +103,7 @@ func (db *DB) SaveConnectedExam(ctx context.Context, exam *model.ConnectedExam) } func (db *DB) SaveConnectedExams(ctx context.Context, exams []*model.ConnectedExam) error { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNameConnectedExams) + collection := db.Client.Database(db.databaseName).Collection(collectionNameConnectedExams) err := collection.Drop(ctx) if err != nil { @@ -130,7 +130,7 @@ func (db *DB) SaveConnectedExams(ctx context.Context, exams []*model.ConnectedEx } func (db *DB) ReplaceConnectedExam(ctx context.Context, exam *model.ConnectedExam) error { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNameConnectedExams) + collection := db.Client.Database(db.databaseName).Collection(collectionNameConnectedExams) _, err := collection.ReplaceOne(ctx, bson.D{{Key: "zpaexam.ancode", Value: exam.ZpaExam.AnCode}}, exam) if err != nil { @@ -142,7 +142,7 @@ func (db *DB) ReplaceConnectedExam(ctx context.Context, exam *model.ConnectedExa } func (db *DB) GetConnectedExam(ctx context.Context, ancode int) (*model.ConnectedExam, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNameConnectedExams) + collection := db.Client.Database(db.databaseName).Collection(collectionNameConnectedExams) var result model.ConnectedExam err := collection.FindOne(ctx, bson.D{{Key: "zpaexam.ancode", Value: ancode}}).Decode(&result) @@ -156,7 +156,7 @@ func (db *DB) GetConnectedExam(ctx context.Context, ancode int) (*model.Connecte } func (db *DB) GetConnectedExams(ctx context.Context) ([]*model.ConnectedExam, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNameConnectedExams) + collection := db.Client.Database(db.databaseName).Collection(collectionNameConnectedExams) exams := make([]*model.ConnectedExam, 0) @@ -192,7 +192,7 @@ func (db *DB) GetConnectedExams(ctx context.Context) ([]*model.ConnectedExam, er } func (db *DB) SaveExamsWithRegs(ctx context.Context, exams []*model.ExamWithRegs) error { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNameExamsWithRegs) + collection := db.Client.Database(db.databaseName).Collection(collectionNameExamsWithRegs) err := collection.Drop(ctx) if err != nil { @@ -219,7 +219,7 @@ func (db *DB) SaveExamsWithRegs(ctx context.Context, exams []*model.ExamWithRegs } func (db *DB) ExamWithRegs(ctx context.Context, ancode int) (*model.ExamWithRegs, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNameExamsWithRegs) + collection := db.Client.Database(db.databaseName).Collection(collectionNameExamsWithRegs) res := collection.FindOne(ctx, bson.D{{Key: "ancode", Value: ancode}}) if res.Err() != nil { @@ -237,7 +237,7 @@ func (db *DB) ExamWithRegs(ctx context.Context, ancode int) (*model.ExamWithRegs } func (db *DB) ExamsWithRegs(ctx context.Context) ([]*model.ExamWithRegs, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNameExamsWithRegs) + collection := db.Client.Database(db.databaseName).Collection(collectionNameExamsWithRegs) exams := make([]*model.ExamWithRegs, 0) diff --git a/db/examgroup.go b/db/examgroup.go index cd7d7be..aee136c 100644 --- a/db/examgroup.go +++ b/db/examgroup.go @@ -10,7 +10,7 @@ import ( ) func (db *DB) GetNextExamGroupCode(ctx context.Context) (int, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNameExamGroups) + collection := db.Client.Database(db.databaseName).Collection(collectionNameExamGroups) filter := bson.D{} opts := options.Find().SetSort(bson.D{{Key: "examgroupcode", Value: -1}}).SetLimit(1) @@ -39,7 +39,7 @@ func (db *DB) GetNextExamGroupCode(ctx context.Context) (int, error) { } func (db *DB) SaveExamGroups(ctx context.Context, exams []*model.ExamGroup) error { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNameExamGroups) + collection := db.Client.Database(db.databaseName).Collection(collectionNameExamGroups) err := collection.Drop(ctx) if err != nil { @@ -66,7 +66,7 @@ func (db *DB) SaveExamGroups(ctx context.Context, exams []*model.ExamGroup) erro } func (db *DB) ExamGroup(ctx context.Context, examGroupCode int) (*model.ExamGroup, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNameExamGroups) + collection := db.Client.Database(db.databaseName).Collection(collectionNameExamGroups) res := collection.FindOne(ctx, bson.D{{Key: "examgroupcode", Value: examGroupCode}}) if res.Err() != nil { @@ -102,7 +102,7 @@ func (db *DB) GetExamGroupForAncode(ctx context.Context, ancode int) (*model.Exa } func (db *DB) ExamGroups(ctx context.Context) ([]*model.ExamGroup, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNameExamGroups) + collection := db.Client.Database(db.databaseName).Collection(collectionNameExamGroups) examGroups := make([]*model.ExamGroup, 0) diff --git a/db/log.go b/db/log.go index 6b7df14..d5ce8e0 100644 --- a/db/log.go +++ b/db/log.go @@ -9,7 +9,7 @@ import ( ) func (db *DB) Log(ctx context.Context, subj, msg string) error { - collection := db.Client.Database(databaseName(db.semester)).Collection("log") + collection := db.Client.Database(db.databaseName).Collection("log") doc := bson.D{ {Key: "created", Value: time.Now()}, diff --git a/db/mongo.go b/db/mongo.go index cc3f568..482f673 100644 --- a/db/mongo.go +++ b/db/mongo.go @@ -4,17 +4,19 @@ import ( "context" "strings" + "github.com/rs/zerolog/log" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/readpref" ) type DB struct { - Client *mongo.Client - semester string + Client *mongo.Client + semester string + databaseName string } -func NewDB(uri, semester string) (*DB, error) { +func NewDB(uri, semester string, dbName *string) (*DB, error) { client, err := mongo.Connect(context.Background(), options.Client().ApplyURI(uri)) if err != nil { return nil, err @@ -24,16 +26,20 @@ func NewDB(uri, semester string) (*DB, error) { return nil, err } + databaseName := strings.Replace(semester, " ", "-", 1) + if dbName != nil { + databaseName = *dbName + } + + log.Debug().Str("database name", databaseName).Msg("using database") + return &DB{ - Client: client, - semester: semester, + Client: client, + semester: semester, + databaseName: databaseName, }, nil } -func databaseName(semester string) string { - return strings.Replace(semester, " ", "-", 1) -} - func semesterName(semester string) string { return strings.Replace(semester, "-", " ", 1) } diff --git a/db/nta.go b/db/nta.go index 784b3c4..beb52a5 100644 --- a/db/nta.go +++ b/db/nta.go @@ -45,7 +45,7 @@ func (db *DB) Ntas(ctx context.Context) ([]*model.NTA, error) { } func (db *DB) NtasWithRegs(ctx context.Context) ([]*model.NTAWithRegs, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNameNTAs) + collection := db.Client.Database(db.databaseName).Collection(collectionNameNTAs) findOptions := options.Find() findOptions.SetSort(bson.D{{Key: "nta.name", Value: 1}}) @@ -68,7 +68,7 @@ func (db *DB) NtasWithRegs(ctx context.Context) ([]*model.NTAWithRegs, error) { } func (db *DB) Nta(ctx context.Context, mtknr string) (*model.NTAWithRegs, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNameNTAs) + collection := db.Client.Database(db.databaseName).Collection(collectionNameNTAs) var nta model.NTAWithRegs res := collection.FindOne(ctx, bson.D{{Key: "nta.mtknr", Value: mtknr}}) @@ -86,7 +86,7 @@ func (db *DB) Nta(ctx context.Context, mtknr string) (*model.NTAWithRegs, error) } func (db *DB) SaveSemesterNTAs(ctx context.Context, ntaWithRegs []*model.NTAWithRegs) error { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNameNTAs) + collection := db.Client.Database(db.databaseName).Collection(collectionNameNTAs) err := collection.Drop(ctx) if err != nil { diff --git a/db/plan.go b/db/plan.go index c26eaf9..28a4ec4 100644 --- a/db/plan.go +++ b/db/plan.go @@ -16,7 +16,7 @@ func (db *DB) AddExamGroupToSlot(ctx context.Context, dayNumber int, timeNumber return false, fmt.Errorf("exam group %d is locked", examGroupCode) } - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNamePlan) + collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) _, err := collection.DeleteMany(ctx, bson.D{{Key: "examgroupcode", Value: examGroupCode}}) if err != nil { @@ -45,7 +45,7 @@ func (db *DB) RmExamGroupFromSlot(ctx context.Context, examGroupCode int) (bool, return false, fmt.Errorf("exam group %d is locked", examGroupCode) } - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNamePlan) + collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) _, err := collection.DeleteMany(ctx, bson.D{{Key: "examgroupcode", Value: examGroupCode}}) if err != nil { @@ -58,7 +58,7 @@ func (db *DB) RmExamGroupFromSlot(ctx context.Context, examGroupCode int) (bool, } func (db *DB) ExamGroupsInSlot(ctx context.Context, day int, time int) ([]*model.ExamGroup, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNamePlan) + collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) filter := bson.M{ "$and": []bson.M{ @@ -106,7 +106,7 @@ func (db *DB) ExamGroupsInSlot(ctx context.Context, day int, time int) ([]*model } func (db *DB) PlanEntries(ctx context.Context) ([]*model.PlanEntry, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNamePlan) + collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) cur, err := collection.Find(ctx, bson.M{}) if err != nil { @@ -133,7 +133,7 @@ func (db *DB) PlanEntries(ctx context.Context) ([]*model.PlanEntry, error) { } func (db *DB) PlanEntryForExamGroup(ctx context.Context, examGroupCode int) (*model.PlanEntry, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNamePlan) + collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) res := collection.FindOne(ctx, bson.D{{Key: "examgroupcode", Value: examGroupCode}}) if res.Err() != nil { @@ -259,7 +259,7 @@ func (db *DB) LockExamGroup(ctx context.Context, examGroupCode int) (*model.Plan return nil, err } - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNamePlan) + collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) filter := bson.D{{Key: "examgroupcode", Value: examGroupCode}} update := bson.D{{Key: "$set", Value: bson.D{{Key: "locked", Value: true}}}} @@ -281,7 +281,7 @@ func (db *DB) UnlockExamGroup(ctx context.Context, examGroupCode int) (*model.Pl return nil, err } - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNamePlan) + collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) filter := bson.D{{Key: "examgroupcode", Value: examGroupCode}} update := bson.D{{Key: "$set", Value: bson.D{{Key: "locked", Value: false}}}} @@ -301,7 +301,7 @@ func (db *DB) ExamGroupIsLocked(ctx context.Context, examGroupCode int) bool { } func (db *DB) RemoveUnlockedExamGroupsFromPlan(ctx context.Context) (int, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNamePlan) + collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) res, err := collection.DeleteMany(ctx, bson.D{{Key: "locked", Value: false}}) @@ -316,7 +316,7 @@ func (db *DB) RemoveUnlockedExamGroupsFromPlan(ctx context.Context) (int, error) } func (db *DB) LockPlan(ctx context.Context) error { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionNamePlan) + collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) res, err := collection.UpdateMany(ctx, bson.D{}, bson.D{{Key: "$set", Value: bson.D{{Key: "locked", Value: true}}}}) @@ -344,13 +344,13 @@ func (db *DB) SavePlanEntriesToBackup(ctx context.Context, planEntries []*model. func (db *DB) savePlanEntries(ctx context.Context, planEntries []*model.PlanEntry, backup bool) error { var collection *mongo.Collection if backup { - collection = db.Client.Database(databaseName(db.semester)).Collection(collectionNamePlanBackup) + collection = db.Client.Database(db.databaseName).Collection(collectionNamePlanBackup) err := collection.Drop(ctx) if err != nil { log.Error().Err(err).Msg("cannot drop backup collection") } } else { - collection = db.Client.Database(databaseName(db.semester)).Collection(collectionNamePlan) + collection = db.Client.Database(db.databaseName).Collection(collectionNamePlan) } entries := make([]interface{}, 0, len(planEntries)) diff --git a/db/prepare_studentregs.go b/db/prepare_studentregs.go index dce6602..29a33da 100644 --- a/db/prepare_studentregs.go +++ b/db/prepare_studentregs.go @@ -44,7 +44,7 @@ func (db *DB) SaveStudentRegsPerAncode(ctx context.Context, studentRegsPerAncode collectionName = collectionStudentRegsPerAncodeAll } - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionName) + collection := db.Client.Database(db.databaseName).Collection(collectionName) err := collection.Drop(ctx) if err != nil { @@ -90,7 +90,7 @@ func (db *DB) SaveStudentRegsPerStudent(ctx context.Context, studentRegsPerStude collectionName = collectionStudentRegsPerStudentAll } - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionName) + collection := db.Client.Database(db.databaseName).Collection(collectionName) err := collection.Drop(ctx) if err != nil { diff --git a/db/primuss.go b/db/primuss.go index 1641b36..06c011f 100644 --- a/db/primuss.go +++ b/db/primuss.go @@ -10,7 +10,7 @@ import ( ) func (db *DB) GetPrograms(ctx context.Context) ([]string, error) { - collectionNames, err := db.Client.Database(databaseName(db.semester)).ListCollectionNames(ctx, + collectionNames, err := db.Client.Database(db.databaseName).ListCollectionNames(ctx, bson.D{primitive.E{ Key: "name", Value: bson.D{ diff --git a/db/primuss_studentregs.go b/db/primuss_studentregs.go index 18505e7..73d7e6e 100644 --- a/db/primuss_studentregs.go +++ b/db/primuss_studentregs.go @@ -213,7 +213,7 @@ func (db *DB) ChangeAncodeInStudentRegsCount(ctx context.Context, program string func (db *DB) SetRegsWithErrors(ctx context.Context, regsWithErrors []*model.RegWithError) error { collectionName := "errors-zpa-studentregs" - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionName) + collection := db.Client.Database(db.databaseName).Collection(collectionName) err := collection.Drop(ctx) if err != nil { @@ -238,7 +238,7 @@ func (db *DB) SetRegsWithErrors(ctx context.Context, regsWithErrors []*model.Reg func (db *DB) GetRegsWithErrors(ctx context.Context) ([]*model.RegWithError, error) { collectionName := "errors-zpa-studentregs" - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionName) + collection := db.Client.Database(db.databaseName).Collection(collectionName) regWithErrors := make([]*model.RegWithError, 0) diff --git a/db/rooms.go b/db/rooms.go index bf060fd..d09148f 100644 --- a/db/rooms.go +++ b/db/rooms.go @@ -38,7 +38,7 @@ func (db *DB) Rooms(ctx context.Context) ([]*model.Room, error) { } func (db *DB) SaveRooms(ctx context.Context, slotsWithRooms []*model.SlotWithRooms) error { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionRooms) + collection := db.Client.Database(db.databaseName).Collection(collectionRooms) err := collection.Drop(ctx) if err != nil { diff --git a/db/studentregs.go b/db/studentregs.go index 8dee194..062957a 100644 --- a/db/studentregs.go +++ b/db/studentregs.go @@ -9,7 +9,7 @@ import ( ) func (db *DB) GetStudentRegsPerAncodePlanned(ctx context.Context) ([]*model.StudentRegsPerAncode, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionStudentRegsPerAncodePlanned) + collection := db.Client.Database(db.databaseName).Collection(collectionStudentRegsPerAncodePlanned) studentRegs := make([]*model.StudentRegsPerAncode, 0) @@ -42,7 +42,7 @@ func (db *DB) GetStudentRegsPerAncodePlanned(ctx context.Context) ([]*model.Stud } func (db *DB) StudentRegsPerStudentPlanned(ctx context.Context) ([]*model.StudentRegsPerStudent, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionStudentRegsPerStudentPlanned) + collection := db.Client.Database(db.databaseName).Collection(collectionStudentRegsPerStudentPlanned) cur, err := collection.Find(ctx, bson.M{}) if err != nil { @@ -64,7 +64,7 @@ func (db *DB) StudentRegsPerStudentPlanned(ctx context.Context) ([]*model.Studen } func (db *DB) StudentRegsPerStudentAll(ctx context.Context) ([]*model.StudentRegsPerStudent, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionStudentRegsPerStudentAll) + collection := db.Client.Database(db.databaseName).Collection(collectionStudentRegsPerStudentAll) cur, err := collection.Find(ctx, bson.M{}) if err != nil { diff --git a/db/zpa.go b/db/zpa.go index 6ed8396..8503586 100644 --- a/db/zpa.go +++ b/db/zpa.go @@ -11,7 +11,7 @@ import ( ) func (db *DB) GetTeacher(ctx context.Context, id int) (*model.Teacher, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection("teachers") + collection := db.Client.Database(db.databaseName).Collection("teachers") var teacher model.Teacher @@ -43,7 +43,7 @@ func isInvigilator(teacher model.Teacher, semester string) bool { } func (db *DB) getTeachers(ctx context.Context, predicate func(model.Teacher) bool) ([]*model.Teacher, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection("teachers") + collection := db.Client.Database(db.databaseName).Collection("teachers") teachers := make([]*model.Teacher, 0) @@ -78,7 +78,7 @@ func (db *DB) getTeachers(ctx context.Context, predicate func(model.Teacher) boo } func (db *DB) CacheTeachers(teachers []*model.Teacher, semester string) error { - collection := db.Client.Database(databaseName(semester)).Collection("teachers") + collection := db.Client.Database(db.databaseName).Collection("teachers") teachersIntf := make([]interface{}, 0, len(teachers)) diff --git a/db/zpa_exams.go b/db/zpa_exams.go index 40d10ba..bec12c8 100644 --- a/db/zpa_exams.go +++ b/db/zpa_exams.go @@ -4,94 +4,15 @@ import ( "context" "time" + set "github.com/deckarep/golang-set/v2" "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo/options" ) -func (db *DB) GetZPAExamsToPlan(ctx context.Context) ([]*model.ZPAExam, error) { - ancodes, err := db.getZpaAnCodesFromCollection(ctx, collectionToPlan) - if err != nil { - return nil, err - } - - exams := make([]*model.ZPAExam, 0) - - for _, ancode := range ancodes { - exam, err := db.GetZpaExamByAncode(ctx, ancode.Ancode) - if err != nil { - log.Error().Err(err).Str("semester", db.semester). - Int("ancode", ancode.Ancode).Msg("zpa exam with ancode not found") - } else { - exams = append(exams, exam) - } - } - - return exams, nil -} - -func (db *DB) GetZPAExamsNotToPlan(ctx context.Context) ([]*model.ZPAExam, error) { - ancodes, err := db.getZpaAnCodesFromCollection(ctx, collectionNotToPlan) - if err != nil { - return nil, err - } - - exams := make([]*model.ZPAExam, 0) - - for _, ancode := range ancodes { - exam, err := db.GetZpaExamByAncode(ctx, ancode.Ancode) - if err != nil { - log.Error().Err(err).Str("semester", db.semester). - Int("ancode", ancode.Ancode).Msg("zpa exam with ancode not found") - } else { - exams = append(exams, exam) - } - } - - return exams, nil -} - -func (db *DB) GetZpaAncodesPlanned(ctx context.Context) ([]*model.AnCode, error) { - return db.getZpaAnCodesFromCollection(ctx, collectionToPlan) -} - -func (db *DB) getZpaAnCodesFromCollection(ctx context.Context, collectionName string) ([]*model.AnCode, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionName) - ancodes := make([]*model.AnCode, 0) - findOptions := options.Find() - findOptions.SetSort(bson.D{{Key: "ancode", Value: 1}}) - - cur, err := collection.Find(ctx, bson.M{}, findOptions) - if err != nil { - log.Error().Err(err).Str("semester", db.semester).Str("collection", collectionName).Msg("MongoDB Find") - return ancodes, err - } - defer cur.Close(ctx) - - for cur.Next(ctx) { - var ancode model.AnCode - - err := cur.Decode(&ancode) - if err != nil { - log.Error().Err(err).Str("semester", db.semester).Str("collection", collectionName).Interface("cur", cur). - Msg("Cannot decode to exam") - return ancodes, err - } - - ancodes = append(ancodes, &ancode) - } - - if err := cur.Err(); err != nil { - log.Error().Err(err).Str("semester", db.semester).Str("collection", collectionName).Msg("Cursor returned error") - return ancodes, err - } - - return ancodes, nil -} - func (db *DB) GetZPAExams(ctx context.Context) ([]*model.ZPAExam, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection(collectionAll) + collection := db.Client.Database(db.databaseName).Collection(collectionAll) exams := make([]*model.ZPAExam, 0) @@ -127,7 +48,7 @@ func (db *DB) GetZPAExams(ctx context.Context) ([]*model.ZPAExam, error) { } func (db *DB) GetZpaExamByAncode(ctx context.Context, ancode int) (*model.ZPAExam, error) { - collection := db.Client.Database(databaseName(db.semester)).Collection("zpaexams") + collection := db.Client.Database(db.databaseName).Collection("zpaexams") var result model.ZPAExam err := collection.FindOne(ctx, bson.D{{Key: "ancode", Value: ancode}}).Decode(&result) @@ -141,7 +62,7 @@ func (db *DB) GetZpaExamByAncode(ctx context.Context, ancode int) (*model.ZPAExa } func (db *DB) CacheZPAExams(exams []*model.ZPAExam) error { - collection := db.Client.Database(databaseName(db.semester)).Collection("zpaexams") + collection := db.Client.Database(db.databaseName).Collection("zpaexams") examsIntf := make([]interface{}, 0, len(exams)) @@ -166,105 +87,159 @@ func (db *DB) CacheZPAExams(exams []*model.ZPAExam) error { return nil } -func (db *DB) SetZPAExamsToPlan(ctx context.Context, exams []*model.ZPAExam) error { - return db.setZPAExams(ctx, exams, collectionToPlan) +type ExamToPlanType struct { + Ancode int + ToPlan bool } -func (db *DB) SetZPAExamsNotToPlan(ctx context.Context, exams []*model.ZPAExam) error { - return db.setZPAExams(ctx, exams, collectionNotToPlan) -} +func (db *DB) SetZPAExamsToPlan(ctx context.Context, examsToPlan, examsNotToPlan []*model.ZPAExam) error { + exams := make([]*ExamToPlanType, 0, len(examsToPlan)+len(examsNotToPlan)) -func (db *DB) setZPAExams(ctx context.Context, exams []*model.ZPAExam, toCollection string) error { - collection := db.Client.Database(databaseName(db.semester)).Collection(toCollection) + log.Debug().Interface("examsToPlan", examsToPlan).Interface("examsNotToPlan", examsNotToPlan).Msg("inserting exams to plan") - examsIntf := make([]interface{}, 0, len(exams)) + for _, examToPlan := range examsToPlan { + exams = append(exams, &ExamToPlanType{Ancode: examToPlan.AnCode, ToPlan: true}) + } - for _, v := range exams { - examsIntf = append(examsIntf, v) + for _, examNotToPlan := range examsNotToPlan { + exams = append(exams, &ExamToPlanType{Ancode: examNotToPlan.AnCode, ToPlan: false}) } + collection := db.Client.Database(db.databaseName).Collection(collectionToPlan) + err := collection.Drop(ctx) if err != nil { return err } + log.Debug().Interface("exams", exams).Msg("inserting exams to plan") + + examsIntf := make([]interface{}, 0, len(exams)) + for _, exam := range exams { + examsIntf = append(examsIntf, exam) + } + res, err := collection.InsertMany(ctx, examsIntf) if err != nil { return err } - log.Debug().Str("semester", db.semester).Str("collection", toCollection). - Int("documents", len(res.InsertedIDs)).Msg("inserted zpaexams") + log.Debug().Str("semester", db.semester).Str("collection", collectionToPlan). + Int("documents", len(res.InsertedIDs)).Msg("inserted zpaexams to plan and not to plan") return nil } -func (db *DB) AddZpaExamToPlan(ctx context.Context, ancode int, unknown bool) (bool, error) { - exam, err := db.GetZpaExamByAncode(ctx, ancode) - if err != nil { - return false, err - } +func (db *DB) AddZpaExamToPlan(ctx context.Context, ancode int) (bool, error) { + return db.addZpaExamToPlanOrNot(ctx, ancode, true) +} - // maybe rm exam from not to plan - if !unknown { - collectionNot := db.Client.Database(databaseName(db.semester)).Collection(collectionNotToPlan) +func (db *DB) RmZpaExamFromPlan(ctx context.Context, ancode int) (bool, error) { + return db.addZpaExamToPlanOrNot(ctx, ancode, false) +} - res, err := collectionNot.DeleteOne(ctx, bson.D{{Key: "ancode", Value: ancode}}) - if err != nil { - log.Error().Err(err).Str("semester", db.semester). - Int("ancode", ancode).Msg("cannot remove ZPA exam from not planned exams") - return false, err - } - if res.DeletedCount != 1 { - log.Error().Err(err).Str("semester", db.semester). - Int("ancode", ancode).Int64("deletedCount", res.DeletedCount).Msg("not removed exactly one ZPA exam from not planned exams") - } - } +func (db *DB) addZpaExamToPlanOrNot(ctx context.Context, ancode int, toPlan bool) (bool, error) { + collection := db.Client.Database(db.databaseName).Collection(collectionToPlan) + + res, err := collection.ReplaceOne(ctx, bson.D{{Key: "ancode", Value: ancode}}, ExamToPlanType{Ancode: ancode, ToPlan: toPlan}) - // add exam to to plan - collectionTo := db.Client.Database(databaseName(db.semester)).Collection(collectionToPlan) + log.Debug().Interface("res", res).Msg("changing exam to plan value") - _, err = collectionTo.InsertOne(ctx, exam) if err != nil { - log.Error().Err(err).Str("semester", db.semester). - Int("ancode", ancode).Msg("cannot add ZPA exam to planned exams") + log.Error().Err(err).Int("ancode", ancode).Bool("toPlan", toPlan).Msg("cannot replace exam to plan") return false, err } return true, nil } -func (db *DB) RmZpaExamFromPlan(ctx context.Context, ancode int, unknown bool) (bool, error) { - exam, err := db.GetZpaExamByAncode(ctx, ancode) +func (db *DB) GetZPAExamsToPlan(ctx context.Context) ([]*model.ZPAExam, error) { + log.Debug().Msg("getting zpa exams to plan") + toPlan := true + return db.getZPAExamsPlannedOrNot(ctx, &toPlan) +} + +func (db *DB) GetZPAExamsNotToPlan(ctx context.Context) ([]*model.ZPAExam, error) { + log.Debug().Msg("getting zpa exams not to plan") + toPlan := false + return db.getZPAExamsPlannedOrNot(ctx, &toPlan) +} + +func (db *DB) GetZPAExamsPlannedOrNotPlanned(ctx context.Context) ([]*model.ZPAExam, error) { + return db.getZPAExamsPlannedOrNot(ctx, nil) +} + +func (db *DB) getZPAExamsPlannedOrNot(ctx context.Context, toPlan *bool) ([]*model.ZPAExam, error) { + log.Debug().Interface("toPlan", toPlan).Msg("getting zpam exams") + + ancodeSet, err := db.getZpaAncodesPlannedOrNot(ctx, toPlan) if err != nil { - return false, err + log.Error().Err(err).Msg("cannot get ancodes planned") + return nil, err } - // maybe rm exam from not to plan - if !unknown { - collectionTo := db.Client.Database(databaseName(db.semester)).Collection(collectionToPlan) + // log.Debug().Interface("ancodes", ancodeSet).Msg("got ancodes to plan") - res, err := collectionTo.DeleteOne(ctx, bson.D{{Key: "ancode", Value: ancode}}) - if err != nil { - log.Error().Err(err).Str("semester", db.semester). - Int("ancode", ancode).Msg("cannot remove ZPA exam from planned exams") - return false, err - } - if res.DeletedCount != 1 { - log.Error().Err(err).Str("semester", db.semester). - Int("ancode", ancode).Int64("deletedCount", res.DeletedCount).Msg("not removed exactly one ZPA exam from planned exams") + zpaExams, err := db.GetZPAExams(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get zpa exams") + return nil, err + } + + exams := make([]*model.ZPAExam, 0, (*ancodeSet).Cardinality()) + + for _, zpaExam := range zpaExams { + if (*ancodeSet).Contains(zpaExam.AnCode) { + exams = append(exams, zpaExam) } } - // add exam to to plan - collectionNot := db.Client.Database(databaseName(db.semester)).Collection(collectionNotToPlan) + // log.Debug().Interface("exams", exams).Msg("found exams to plan") + + return exams, nil +} + +func (db *DB) GetZpaAncodesPlanned(ctx context.Context) (*set.Set[int], error) { + toPlan := true + return db.getZpaAncodesPlannedOrNot(ctx, &toPlan) +} + +func (db *DB) GetZpaAncodesNotPlanned(ctx context.Context) (*set.Set[int], error) { + toPlan := false + return db.getZpaAncodesPlannedOrNot(ctx, &toPlan) +} + +func (db *DB) GetZpaAncodesPlannedOrNotPlanned(ctx context.Context) (*set.Set[int], error) { + return db.getZpaAncodesPlannedOrNot(ctx, nil) +} + +func (db *DB) getZpaAncodesPlannedOrNot(ctx context.Context, toPlan *bool) (*set.Set[int], error) { + collection := db.Client.Database(db.databaseName).Collection(collectionToPlan) + + filter := bson.D{} + if toPlan != nil { + filter = bson.D{{Key: "toplan", Value: toPlan}} + } + + cur, err := collection.Find(ctx, filter) + if err != nil { + log.Error().Err(err).Interface("toPlan", toPlan).Msg("cannot get zpa exams to plan") + return nil, err + } + defer cur.Close(ctx) + + result := make([]*ExamToPlanType, 0) - _, err = collectionNot.InsertOne(ctx, exam) + err = cur.All(ctx, &result) if err != nil { - log.Error().Err(err).Str("semester", db.semester). - Int("ancode", ancode).Msg("cannot add ZPA exam to not planned exams") - return false, err + log.Error().Err(err).Interface("toPlan", toPlan).Msg("cannot decode from cursor") + return nil, err } - return true, nil + resultSet := set.NewSet[int]() + for _, examToPlan := range result { + resultSet.Add(examToPlan.Ancode) + } + + return &resultSet, nil } diff --git a/graph/generated/generated.go b/graph/generated/generated.go index c98a47b..bdb1254 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -230,7 +230,7 @@ type ComplexityRoot struct { AddExamGroupToSlot func(childComplexity int, day int, time int, examGroupCode int) int AddNta func(childComplexity int, input model.NTAInput) int AddRoomToExam func(childComplexity int, input model.RoomForExamInput) int - AddZpaExamToPlan func(childComplexity int, ancode int, unknown bool) int + AddZpaExamToPlan func(childComplexity int, ancode int) int ExahmRooms func(childComplexity int, ancode int) int ExcludeDays func(childComplexity int, ancode int, days []string) int Lab func(childComplexity int, ancode int) int @@ -241,7 +241,7 @@ type ComplexityRoot struct { PrepareExams func(childComplexity int, input []*model.PrimussExamInput) int RemovePrimussExam func(childComplexity int, input *model.PrimussExamInput) int RmExamGroupFromSlot func(childComplexity int, examGroupCode int) int - RmZpaExamFromPlan func(childComplexity int, ancode int, unknown bool) int + RmZpaExamFromPlan func(childComplexity int, ancode int) int SameSlot func(childComplexity int, ancode int, ancodes []int) int Seb func(childComplexity int, ancode int) int SetSemester func(childComplexity int, input string) int @@ -550,8 +550,8 @@ type ComplexityRoot struct { type MutationResolver interface { SetSemester(ctx context.Context, input string) (*model.Semester, error) ZpaExamsToPlan(ctx context.Context, input []int) ([]*model.ZPAExam, error) - AddZpaExamToPlan(ctx context.Context, ancode int, unknown bool) (bool, error) - RmZpaExamFromPlan(ctx context.Context, ancode int, unknown bool) (bool, error) + AddZpaExamToPlan(ctx context.Context, ancode int) (bool, error) + RmZpaExamFromPlan(ctx context.Context, ancode int) (bool, error) AddAdditionalExam(ctx context.Context, exam model.AdditionalExamInput) (bool, error) RemovePrimussExam(ctx context.Context, input *model.PrimussExamInput) (bool, error) PrepareExams(ctx context.Context, input []*model.PrimussExamInput) (bool, error) @@ -1450,7 +1450,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Mutation.AddZpaExamToPlan(childComplexity, args["ancode"].(int), args["unknown"].(bool)), true + return e.complexity.Mutation.AddZpaExamToPlan(childComplexity, args["ancode"].(int)), true case "Mutation.exahmRooms": if e.complexity.Mutation.ExahmRooms == nil { @@ -1582,7 +1582,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Mutation.RmZpaExamFromPlan(childComplexity, args["ancode"].(int), args["unknown"].(bool)), true + return e.complexity.Mutation.RmZpaExamFromPlan(childComplexity, args["ancode"].(int)), true case "Mutation.sameSlot": if e.complexity.Mutation.SameSlot == nil { @@ -3367,8 +3367,8 @@ type RoomWithInvigilator { setSemester(input: String!): Semester! # Prepare ZPA-Exams zpaExamsToPlan(input: [Int!]!): [ZPAExam!]! - addZpaExamToPlan(ancode: Int!, unknown: Boolean!): Boolean! - rmZpaExamFromPlan(ancode: Int!, unknown: Boolean!): Boolean! + addZpaExamToPlan(ancode: Int!): Boolean! + rmZpaExamFromPlan(ancode: Int!): Boolean! # Additional Exams addAdditionalExam(exam: AdditionalExamInput!): Boolean! # Primuss @@ -3874,15 +3874,6 @@ func (ec *executionContext) field_Mutation_addZpaExamToPlan_args(ctx context.Con } } args["ancode"] = arg0 - var arg1 bool - if tmp, ok := rawArgs["unknown"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("unknown")) - arg1, err = ec.unmarshalNBoolean2bool(ctx, tmp) - if err != nil { - return nil, err - } - } - args["unknown"] = arg1 return args, nil } @@ -4066,15 +4057,6 @@ func (ec *executionContext) field_Mutation_rmZpaExamFromPlan_args(ctx context.Co } } args["ancode"] = arg0 - var arg1 bool - if tmp, ok := rawArgs["unknown"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("unknown")) - arg1, err = ec.unmarshalNBoolean2bool(ctx, tmp) - if err != nil { - return nil, err - } - } - args["unknown"] = arg1 return args, nil } @@ -9895,7 +9877,7 @@ func (ec *executionContext) _Mutation_addZpaExamToPlan(ctx context.Context, fiel }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().AddZpaExamToPlan(rctx, fc.Args["ancode"].(int), fc.Args["unknown"].(bool)) + return ec.resolvers.Mutation().AddZpaExamToPlan(rctx, fc.Args["ancode"].(int)) }) if err != nil { ec.Error(ctx, err) @@ -9950,7 +9932,7 @@ func (ec *executionContext) _Mutation_rmZpaExamFromPlan(ctx context.Context, fie }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().RmZpaExamFromPlan(rctx, fc.Args["ancode"].(int), fc.Args["unknown"].(bool)) + return ec.resolvers.Mutation().RmZpaExamFromPlan(rctx, fc.Args["ancode"].(int)) }) if err != nil { ec.Error(ctx, err) diff --git a/graph/mutation.graphqls b/graph/mutation.graphqls index ab186ea..a43d4df 100644 --- a/graph/mutation.graphqls +++ b/graph/mutation.graphqls @@ -2,8 +2,8 @@ type Mutation { setSemester(input: String!): Semester! # Prepare ZPA-Exams zpaExamsToPlan(input: [Int!]!): [ZPAExam!]! - addZpaExamToPlan(ancode: Int!, unknown: Boolean!): Boolean! - rmZpaExamFromPlan(ancode: Int!, unknown: Boolean!): Boolean! + addZpaExamToPlan(ancode: Int!): Boolean! + rmZpaExamFromPlan(ancode: Int!): Boolean! # Additional Exams addAdditionalExam(exam: AdditionalExamInput!): Boolean! # Primuss diff --git a/graph/mutation.resolvers.go b/graph/mutation.resolvers.go index 322ed03..bcb4308 100644 --- a/graph/mutation.resolvers.go +++ b/graph/mutation.resolvers.go @@ -2,7 +2,7 @@ package graph // This file will be automatically regenerated based on the schema, any resolver implementations // will be copied through when generating and any unknown code will be moved to the end. -// Code generated by github.com/99designs/gqlgen version v0.17.33 +// Code generated by github.com/99designs/gqlgen version v0.17.34 import ( "context" @@ -22,13 +22,13 @@ func (r *mutationResolver) ZpaExamsToPlan(ctx context.Context, input []int) ([]* } // AddZPAExamToPlan is the resolver for the addZPAExamToPlan field. -func (r *mutationResolver) AddZpaExamToPlan(ctx context.Context, ancode int, unknown bool) (bool, error) { - return r.plexams.AddZpaExamToPlan(ctx, ancode, unknown) +func (r *mutationResolver) AddZpaExamToPlan(ctx context.Context, ancode int) (bool, error) { + return r.plexams.AddZpaExamToPlan(ctx, ancode) } // RmZPAExamFromPlan is the resolver for the rmZPAExamFromPlan field. -func (r *mutationResolver) RmZpaExamFromPlan(ctx context.Context, ancode int, unknown bool) (bool, error) { - return r.plexams.RmZpaExamFromPlan(ctx, ancode, unknown) +func (r *mutationResolver) RmZpaExamFromPlan(ctx context.Context, ancode int) (bool, error) { + return r.plexams.RmZpaExamFromPlan(ctx, ancode) } // AddAdditionalExam is the resolver for the addAdditionalExam field. diff --git a/graph/primuss.resolvers.go b/graph/primuss.resolvers.go index a8b1b99..c80de9f 100644 --- a/graph/primuss.resolvers.go +++ b/graph/primuss.resolvers.go @@ -2,7 +2,7 @@ package graph // This file will be automatically regenerated based on the schema, any resolver implementations // will be copied through when generating and any unknown code will be moved to the end. -// Code generated by github.com/99designs/gqlgen version v0.17.33 +// Code generated by github.com/99designs/gqlgen version v0.17.34 import ( "context" diff --git a/graph/query.resolvers.go b/graph/query.resolvers.go index 336c039..802e25d 100644 --- a/graph/query.resolvers.go +++ b/graph/query.resolvers.go @@ -2,7 +2,7 @@ package graph // This file will be automatically regenerated based on the schema, any resolver implementations // will be copied through when generating and any unknown code will be moved to the end. -// Code generated by github.com/99designs/gqlgen version v0.17.33 +// Code generated by github.com/99designs/gqlgen version v0.17.34 import ( "context" diff --git a/graph/room.resolvers.go b/graph/room.resolvers.go index bad1ea1..37803e4 100644 --- a/graph/room.resolvers.go +++ b/graph/room.resolvers.go @@ -2,7 +2,7 @@ package graph // This file will be automatically regenerated based on the schema, any resolver implementations // will be copied through when generating and any unknown code will be moved to the end. -// Code generated by github.com/99designs/gqlgen version v0.17.33 +// Code generated by github.com/99designs/gqlgen version v0.17.34 import ( "context" diff --git a/plexams/plexams.go b/plexams/plexams.go index 60f818a..65d2e37 100644 --- a/plexams/plexams.go +++ b/plexams/plexams.go @@ -53,7 +53,15 @@ func NewPlexams(semester, dbUri, zpaBaseurl, zpaUsername, zpaPassword string, fk if dbUri == "" { log.Info().Msg("starting without DB!") } else { - client, err = db.NewDB(dbUri, semester) + dbName := viper.GetString("db.database") + var databaseName *string + if dbName == "" { + databaseName = nil + } else { + databaseName = &dbName + } + + client, err = db.NewDB(dbUri, semester, databaseName) if err != nil { panic(fmt.Errorf("fatal cannot create mongo client: %w", err)) diff --git a/plexams/prepare.go b/plexams/prepare.go index 10bed3f..3d15f44 100644 --- a/plexams/prepare.go +++ b/plexams/prepare.go @@ -23,16 +23,16 @@ func (p *Plexams) PrepareStudentRegs() error { } studentRegsPerAncodePlanned := make(map[int]map[string][]*model.StudentReg) - for _, ancode := range ancodes { - studentRegsPerAncodePlanned[ancode.Ancode] = studentRegsPerAncode[ancode.Ancode] + for _, ancode := range (*ancodes).ToSlice() { + studentRegsPerAncodePlanned[ancode] = studentRegsPerAncode[ancode] } studentRegsPerStudentPlanned := make(map[string][]*model.StudentReg, 0) for mtknr, studentRegs := range studentRegsPerStudent { studentRegsPlanned := make([]*model.StudentReg, 0) for _, studentReg := range studentRegs { - for _, ancode := range ancodes { - if ancode.Ancode == studentReg.AnCode { + for _, ancode := range (*ancodes).ToSlice() { + if ancode == studentReg.AnCode { studentRegsPlanned = append(studentRegsPlanned, studentReg) break } diff --git a/plexams/zpa_get.go b/plexams/zpa_get.go index 1b081b9..f3c26a0 100644 --- a/plexams/zpa_get.go +++ b/plexams/zpa_get.go @@ -180,18 +180,12 @@ func (p *Plexams) ZpaExamsToPlan(ctx context.Context, input []int) ([]*model.ZPA } } - err = p.dbClient.SetZPAExamsToPlan(ctx, examsToPlan) + err = p.dbClient.SetZPAExamsToPlan(ctx, examsToPlan, examsNotToPlan) if err != nil { log.Error().Err(err).Msg("cannot set zpa exams to plan") return nil, err } - err = p.dbClient.SetZPAExamsNotToPlan(ctx, examsNotToPlan) - if err != nil { - log.Error().Err(err).Msg("cannot set zpa exams not to plan") - return nil, err - } - return examsToPlan, nil } @@ -253,12 +247,12 @@ func (p *Plexams) ZpaExamsPlaningStatusUnknown(ctx context.Context) ([]*model.ZP return statusUnknown, nil } -func (p *Plexams) AddZpaExamToPlan(ctx context.Context, ancode int, unknown bool) (bool, error) { - return p.dbClient.AddZpaExamToPlan(ctx, ancode, unknown) +func (p *Plexams) AddZpaExamToPlan(ctx context.Context, ancode int) (bool, error) { + return p.dbClient.AddZpaExamToPlan(ctx, ancode) } -func (p *Plexams) RmZpaExamFromPlan(ctx context.Context, ancode int, unknown bool) (bool, error) { - return p.dbClient.RmZpaExamFromPlan(ctx, ancode, unknown) +func (p *Plexams) RmZpaExamFromPlan(ctx context.Context, ancode int) (bool, error) { + return p.dbClient.RmZpaExamFromPlan(ctx, ancode) } func (p *Plexams) GetSupervisorRequirements(ctx context.Context) ([]*zpa.SupervisorRequirements, error) { From 6d0e0f0e4e8ec98a8da96334fbb6e0be7adadeba Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Wed, 12 Jul 2023 15:23:55 +0200 Subject: [PATCH 02/78] constraints --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3fc05a9..8282f8f 100644 --- a/README.md +++ b/README.md @@ -15,5 +15,6 @@ erDiagram int ancode bool toPlan } - zpaexams ||--|| zpaexamsToPlan: references + zpaexams ||--|| zpaexamsToPlan: planOrNot + constraints |o--|| zpaexams: hasConstraint ``` From ef0276303d7347f8477e2bb5462f6108f9b928f7 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Thu, 13 Jul 2023 11:18:30 +0200 Subject: [PATCH 03/78] =?UTF-8?q?=F0=9F=9A=A7=20Primuss/Connected?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++++ db/exam.go | 66 ++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 55 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 8282f8f..ff38d1f 100644 --- a/README.md +++ b/README.md @@ -17,4 +17,10 @@ erDiagram } zpaexams ||--|| zpaexamsToPlan: planOrNot constraints |o--|| zpaexams: hasConstraint + zpaexams |o--o{ exams_XY: connectedExam ``` + + conflicts_XY + count_XY + exams_XY + studentregs_XY diff --git a/db/exam.go b/db/exam.go index 24a716d..1bc77b8 100644 --- a/db/exam.go +++ b/db/exam.go @@ -102,6 +102,18 @@ func (db *DB) SaveConnectedExam(ctx context.Context, exam *model.ConnectedExam) return nil } +type PrimussExam struct { + Ancode int `bson:"ancode"` + Program string `bson:"program"` +} + +type ConnectedExam struct { + ZpaExam int `bson:"zpaExamAncode"` + PrimussExams []*PrimussExam `bson:"primussExamsAncodes"` + OtherPrimussExams []*PrimussExam `bson:"otherPrimussExamsAncodes"` + Errors []string `bson:"errors"` +} + func (db *DB) SaveConnectedExams(ctx context.Context, exams []*model.ConnectedExam) error { collection := db.Client.Database(db.databaseName).Collection(collectionNameConnectedExams) @@ -115,7 +127,34 @@ func (db *DB) SaveConnectedExams(ctx context.Context, exams []*model.ConnectedEx examsToInsert := make([]interface{}, 0, len(exams)) for _, exam := range exams { - examsToInsert = append(examsToInsert, exam) + var primussExamsAncodes []*PrimussExam + if exam.PrimussExams != nil && len(exam.PrimussExams) > 0 { + primussExamsAncodes = make([]*PrimussExam, 0, len(exam.PrimussExams)) + for _, primussExam := range exam.PrimussExams { + primussExamsAncodes = append(primussExamsAncodes, &PrimussExam{ + Ancode: primussExam.AnCode, + Program: primussExam.Program, + }) + } + } + + var otherPrimussExamsAncodes []*PrimussExam + if exam.OtherPrimussExams != nil && len(exam.OtherPrimussExams) > 0 { + otherPrimussExamsAncodes = make([]*PrimussExam, 0, len(exam.OtherPrimussExams)) + for _, otherPrimussExam := range exam.OtherPrimussExams { + otherPrimussExamsAncodes = append(otherPrimussExamsAncodes, &PrimussExam{ + Ancode: otherPrimussExam.AnCode, + Program: otherPrimussExam.Program, + }) + } + } + + examsToInsert = append(examsToInsert, &ConnectedExam{ + ZpaExam: exam.ZpaExam.AnCode, + PrimussExams: primussExamsAncodes, + OtherPrimussExams: otherPrimussExamsAncodes, + Errors: exam.Errors, + }) } _, err = collection.InsertMany(ctx, examsToInsert) @@ -158,39 +197,32 @@ func (db *DB) GetConnectedExam(ctx context.Context, ancode int) (*model.Connecte func (db *DB) GetConnectedExams(ctx context.Context) ([]*model.ConnectedExam, error) { collection := db.Client.Database(db.databaseName).Collection(collectionNameConnectedExams) - exams := make([]*model.ConnectedExam, 0) + exams := make([]*ConnectedExam, 0) findOptions := options.Find() - findOptions.SetSort(bson.D{{Key: "zpaexam.ancode", Value: 1}}) + findOptions.SetSort(bson.D{{Key: "zpaExamAncode", Value: 1}}) cur, err := collection.Find(ctx, bson.M{}, findOptions) if err != nil { log.Error().Err(err).Str("semester", db.semester).Str("collection", collectionNameConnectedExams).Msg("MongoDB Find") - return exams, err + return nil, err } defer cur.Close(ctx) - for cur.Next(ctx) { - var exam model.ConnectedExam - - err := cur.Decode(&exam) - if err != nil { - log.Error().Err(err).Str("semester", db.semester).Str("collection", collectionNameConnectedExams).Interface("cur", cur). - Msg("Cannot decode to additional exam") - return exams, err - } - - exams = append(exams, &exam) - } + err = cur.All(ctx, &exams) if err := cur.Err(); err != nil { log.Error().Err(err).Str("semester", db.semester).Str("collection", collectionNameConnectedExams).Msg("Cursor returned error") - return exams, err + return nil, err } return exams, nil } +func (db *DB) connectedExamToModelConnectedExam(ctx context.Context, exam *ConnectedExam) *model.ConnectedExam { + +} + func (db *DB) SaveExamsWithRegs(ctx context.Context, exams []*model.ExamWithRegs) error { collection := db.Client.Database(db.databaseName).Collection(collectionNameExamsWithRegs) From b775a197b9e0902914a27d73d6a59b58555a2e1c Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Thu, 13 Jul 2023 14:37:34 +0200 Subject: [PATCH 04/78] GetConnectedExams --- db/exam.go | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/db/exam.go b/db/exam.go index 1bc77b8..67bc4f4 100644 --- a/db/exam.go +++ b/db/exam.go @@ -211,16 +211,60 @@ func (db *DB) GetConnectedExams(ctx context.Context) ([]*model.ConnectedExam, er err = cur.All(ctx, &exams) - if err := cur.Err(); err != nil { + if err != nil { log.Error().Err(err).Str("semester", db.semester).Str("collection", collectionNameConnectedExams).Msg("Cursor returned error") return nil, err } - return exams, nil + if exams == nil { + return nil, nil + } + + connectedExams := make([]*model.ConnectedExam, 0, len(exams)) + for _, exam := range exams { + connectedExam, err := db.connectedExamToModelConnectedExam(ctx, exam) + if err != nil { + log.Error().Err(err).Int("ancode", exam.ZpaExam).Msg("cannot get connected exam") + } + connectedExams = append(connectedExams, connectedExam) + } + + return connectedExams, nil } -func (db *DB) connectedExamToModelConnectedExam(ctx context.Context, exam *ConnectedExam) *model.ConnectedExam { +func (db *DB) connectedExamToModelConnectedExam(ctx context.Context, exam *ConnectedExam) (*model.ConnectedExam, error) { + zpaExam, err := db.GetZpaExamByAncode(ctx, exam.ZpaExam) + if err != nil { + log.Error().Err(err).Int("ancode", exam.ZpaExam).Msg("cannot get zpa exam") + return nil, err + } + + var primussExams []*model.PrimussExam + for _, exam := range exam.PrimussExams { + primussExam, err := db.GetPrimussExam(ctx, exam.Program, exam.Ancode) + if err != nil { + log.Error().Err(err).Int("ancode", exam.Ancode).Str("program", exam.Program).Msg("cannot get primuss exam") + return nil, err + } + primussExams = append(primussExams, primussExam) + } + + var otherPrimussExams []*model.PrimussExam + for _, exam := range exam.OtherPrimussExams { + primussExam, err := db.GetPrimussExam(ctx, exam.Program, exam.Ancode) + if err != nil { + log.Error().Err(err).Int("ancode", exam.Ancode).Str("program", exam.Program).Msg("cannot get primuss exam") + return nil, err + } + otherPrimussExams = append(otherPrimussExams, primussExam) + } + return &model.ConnectedExam{ + ZpaExam: zpaExam, + PrimussExams: primussExams, + OtherPrimussExams: otherPrimussExams, + Errors: exam.Errors, + }, nil } func (db *DB) SaveExamsWithRegs(ctx context.Context, exams []*model.ExamWithRegs) error { From d50e26e9539f4d3e19f8306559ddd4724d85f0e5 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Tue, 18 Jul 2023 10:10:54 +0200 Subject: [PATCH 05/78] =?UTF-8?q?=F0=9F=9A=A7=20connected=20exams?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +- db/exam.go | 179 -------------------------------------- db/exam_connected.go | 199 +++++++++++++++++++++++++++++++++++++++++++ db/primuss_exam.go | 15 +--- 4 files changed, 203 insertions(+), 193 deletions(-) create mode 100644 db/exam_connected.go diff --git a/README.md b/README.md index ff38d1f..c47e000 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,8 @@ erDiagram } zpaexams ||--|| zpaexamsToPlan: planOrNot constraints |o--|| zpaexams: hasConstraint - zpaexams |o--o{ exams_XY: connectedExam + zpaexams |o--o{ exams_primuss: connectedExam + additionalExam |o--o{ exams_primuss: connectedAdditionalExam ``` conflicts_XY diff --git a/db/exam.go b/db/exam.go index 67bc4f4..ba3ab42 100644 --- a/db/exam.go +++ b/db/exam.go @@ -88,185 +88,6 @@ func (db *DB) AddExam(ctx context.Context, exam *model.Exam) error { return result.Err() } -func (db *DB) SaveConnectedExam(ctx context.Context, exam *model.ConnectedExam) error { - collection := db.Client.Database(db.databaseName).Collection(collectionNameConnectedExams) - - _, err := collection.InsertOne(ctx, exam) - if err != nil { - log.Error().Err(err). - Str("collectionName", collectionNameConnectedExams). - Msg("cannot insert exams") - return err - } - - return nil -} - -type PrimussExam struct { - Ancode int `bson:"ancode"` - Program string `bson:"program"` -} - -type ConnectedExam struct { - ZpaExam int `bson:"zpaExamAncode"` - PrimussExams []*PrimussExam `bson:"primussExamsAncodes"` - OtherPrimussExams []*PrimussExam `bson:"otherPrimussExamsAncodes"` - Errors []string `bson:"errors"` -} - -func (db *DB) SaveConnectedExams(ctx context.Context, exams []*model.ConnectedExam) error { - collection := db.Client.Database(db.databaseName).Collection(collectionNameConnectedExams) - - err := collection.Drop(ctx) - if err != nil { - log.Error().Err(err). - Str("collectionName", collectionNameConnectedExams). - Msg("cannot drop collection") - return err - } - - examsToInsert := make([]interface{}, 0, len(exams)) - for _, exam := range exams { - var primussExamsAncodes []*PrimussExam - if exam.PrimussExams != nil && len(exam.PrimussExams) > 0 { - primussExamsAncodes = make([]*PrimussExam, 0, len(exam.PrimussExams)) - for _, primussExam := range exam.PrimussExams { - primussExamsAncodes = append(primussExamsAncodes, &PrimussExam{ - Ancode: primussExam.AnCode, - Program: primussExam.Program, - }) - } - } - - var otherPrimussExamsAncodes []*PrimussExam - if exam.OtherPrimussExams != nil && len(exam.OtherPrimussExams) > 0 { - otherPrimussExamsAncodes = make([]*PrimussExam, 0, len(exam.OtherPrimussExams)) - for _, otherPrimussExam := range exam.OtherPrimussExams { - otherPrimussExamsAncodes = append(otherPrimussExamsAncodes, &PrimussExam{ - Ancode: otherPrimussExam.AnCode, - Program: otherPrimussExam.Program, - }) - } - } - - examsToInsert = append(examsToInsert, &ConnectedExam{ - ZpaExam: exam.ZpaExam.AnCode, - PrimussExams: primussExamsAncodes, - OtherPrimussExams: otherPrimussExamsAncodes, - Errors: exam.Errors, - }) - } - - _, err = collection.InsertMany(ctx, examsToInsert) - if err != nil { - log.Error().Err(err). - Str("collectionName", collectionNameConnectedExams). - Msg("cannot insert exams") - return err - } - - return nil -} - -func (db *DB) ReplaceConnectedExam(ctx context.Context, exam *model.ConnectedExam) error { - collection := db.Client.Database(db.databaseName).Collection(collectionNameConnectedExams) - - _, err := collection.ReplaceOne(ctx, bson.D{{Key: "zpaexam.ancode", Value: exam.ZpaExam.AnCode}}, exam) - if err != nil { - log.Error().Err(err).Int("zpaexam.ancode", exam.ZpaExam.AnCode).Msg("cannot replace connected exam") - return err - } - - return nil -} - -func (db *DB) GetConnectedExam(ctx context.Context, ancode int) (*model.ConnectedExam, error) { - collection := db.Client.Database(db.databaseName).Collection(collectionNameConnectedExams) - - var result model.ConnectedExam - err := collection.FindOne(ctx, bson.D{{Key: "zpaexam.ancode", Value: ancode}}).Decode(&result) - if err != nil { - log.Error().Err(err).Str("semester", db.semester). - Int("ancode", ancode).Msg("cannot find Connected exam") - return nil, err - } - - return &result, nil -} - -func (db *DB) GetConnectedExams(ctx context.Context) ([]*model.ConnectedExam, error) { - collection := db.Client.Database(db.databaseName).Collection(collectionNameConnectedExams) - - exams := make([]*ConnectedExam, 0) - - findOptions := options.Find() - findOptions.SetSort(bson.D{{Key: "zpaExamAncode", Value: 1}}) - - cur, err := collection.Find(ctx, bson.M{}, findOptions) - if err != nil { - log.Error().Err(err).Str("semester", db.semester).Str("collection", collectionNameConnectedExams).Msg("MongoDB Find") - return nil, err - } - defer cur.Close(ctx) - - err = cur.All(ctx, &exams) - - if err != nil { - log.Error().Err(err).Str("semester", db.semester).Str("collection", collectionNameConnectedExams).Msg("Cursor returned error") - return nil, err - } - - if exams == nil { - return nil, nil - } - - connectedExams := make([]*model.ConnectedExam, 0, len(exams)) - for _, exam := range exams { - connectedExam, err := db.connectedExamToModelConnectedExam(ctx, exam) - if err != nil { - log.Error().Err(err).Int("ancode", exam.ZpaExam).Msg("cannot get connected exam") - } - connectedExams = append(connectedExams, connectedExam) - } - - return connectedExams, nil -} - -func (db *DB) connectedExamToModelConnectedExam(ctx context.Context, exam *ConnectedExam) (*model.ConnectedExam, error) { - zpaExam, err := db.GetZpaExamByAncode(ctx, exam.ZpaExam) - if err != nil { - log.Error().Err(err).Int("ancode", exam.ZpaExam).Msg("cannot get zpa exam") - return nil, err - } - - var primussExams []*model.PrimussExam - for _, exam := range exam.PrimussExams { - primussExam, err := db.GetPrimussExam(ctx, exam.Program, exam.Ancode) - if err != nil { - log.Error().Err(err).Int("ancode", exam.Ancode).Str("program", exam.Program).Msg("cannot get primuss exam") - return nil, err - } - primussExams = append(primussExams, primussExam) - } - - var otherPrimussExams []*model.PrimussExam - for _, exam := range exam.OtherPrimussExams { - primussExam, err := db.GetPrimussExam(ctx, exam.Program, exam.Ancode) - if err != nil { - log.Error().Err(err).Int("ancode", exam.Ancode).Str("program", exam.Program).Msg("cannot get primuss exam") - return nil, err - } - otherPrimussExams = append(otherPrimussExams, primussExam) - } - - return &model.ConnectedExam{ - ZpaExam: zpaExam, - PrimussExams: primussExams, - OtherPrimussExams: otherPrimussExams, - Errors: exam.Errors, - }, nil -} - func (db *DB) SaveExamsWithRegs(ctx context.Context, exams []*model.ExamWithRegs) error { collection := db.Client.Database(db.databaseName).Collection(collectionNameExamsWithRegs) diff --git a/db/exam_connected.go b/db/exam_connected.go new file mode 100644 index 0000000..bdeb28d --- /dev/null +++ b/db/exam_connected.go @@ -0,0 +1,199 @@ +package db + +import ( + "context" + + "github.com/obcode/plexams.go/graph/model" + "github.com/rs/zerolog/log" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo/options" +) + +type PrimussExam struct { + Ancode int `bson:"ancode"` + Program string `bson:"program"` +} + +type ConnectedExam struct { + ZpaExam int `bson:"zpaExamAncode"` + PrimussExams []*PrimussExam `bson:"primussExamsAncodes"` + OtherPrimussExams []*PrimussExam `bson:"otherPrimussExamsAncodes"` + Errors []string `bson:"errors"` +} + +func (db *DB) SaveConnectedExam(ctx context.Context, exam *model.ConnectedExam) error { + collection := db.Client.Database(db.databaseName).Collection(collectionNameConnectedExams) + + _, err := collection.InsertOne(ctx, exam) + if err != nil { + log.Error().Err(err). + Str("collectionName", collectionNameConnectedExams). + Msg("cannot insert exams") + return err + } + + return nil +} + +func (db *DB) SaveConnectedExams(ctx context.Context, exams []*model.ConnectedExam) error { + collection := db.Client.Database(db.databaseName).Collection(collectionNameConnectedExams) + + err := collection.Drop(ctx) + if err != nil { + log.Error().Err(err). + Str("collectionName", collectionNameConnectedExams). + Msg("cannot drop collection") + return err + } + + examsToInsert := make([]interface{}, 0, len(exams)) + for _, exam := range exams { + examsToInsert = append(examsToInsert, db.modelConnectedExamToConnectedExam(exam)) + } + + _, err = collection.InsertMany(ctx, examsToInsert) + if err != nil { + log.Error().Err(err). + Str("collectionName", collectionNameConnectedExams). + Msg("cannot insert exams") + return err + } + + return nil +} + +func (db *DB) ReplaceConnectedExam(ctx context.Context, exam *model.ConnectedExam) error { + collection := db.Client.Database(db.databaseName).Collection(collectionNameConnectedExams) + + connectedExam := db.modelConnectedExamToConnectedExam(exam) + _, err := collection.ReplaceOne(ctx, bson.D{{Key: "zpaExamAncode", Value: exam.ZpaExam.AnCode}}, connectedExam) + if err != nil { + log.Error().Err(err).Int("zpaexam.ancode", exam.ZpaExam.AnCode).Msg("cannot replace connected exam") + return err + } + + return nil +} + +func (db *DB) GetConnectedExam(ctx context.Context, ancode int) (*model.ConnectedExam, error) { + collection := db.Client.Database(db.databaseName).Collection(collectionNameConnectedExams) + + var result ConnectedExam + err := collection.FindOne(ctx, bson.D{{Key: "zpaExamAncode", Value: ancode}}).Decode(&result) + if err != nil { + log.Error().Err(err).Str("semester", db.semester). + Int("ancode", ancode).Msg("cannot find Connected exam") + return nil, err + } + + connectedExam, err := db.connectedExamToModelConnectedExam(ctx, &result) + if err != nil { + log.Error().Err(err).Int("ancode", result.ZpaExam).Msg("cannot get connected exam") + } + + return connectedExam, nil +} + +func (db *DB) GetConnectedExams(ctx context.Context) ([]*model.ConnectedExam, error) { + collection := db.Client.Database(db.databaseName).Collection(collectionNameConnectedExams) + + exams := make([]*ConnectedExam, 0) + + findOptions := options.Find() + findOptions.SetSort(bson.D{{Key: "zpaExamAncode", Value: 1}}) + + cur, err := collection.Find(ctx, bson.M{}, findOptions) + if err != nil { + log.Error().Err(err).Str("semester", db.semester).Str("collection", collectionNameConnectedExams).Msg("MongoDB Find") + return nil, err + } + defer cur.Close(ctx) + + err = cur.All(ctx, &exams) + + if err != nil { + log.Error().Err(err).Str("semester", db.semester).Str("collection", collectionNameConnectedExams).Msg("Cursor returned error") + return nil, err + } + + if exams == nil { + return nil, nil + } + + connectedExams := make([]*model.ConnectedExam, 0, len(exams)) + for _, exam := range exams { + connectedExam, err := db.connectedExamToModelConnectedExam(ctx, exam) + if err != nil { + log.Error().Err(err).Int("ancode", exam.ZpaExam).Msg("cannot get connected exam") + } + connectedExams = append(connectedExams, connectedExam) + } + + return connectedExams, nil +} + +func (db *DB) modelConnectedExamToConnectedExam(exam *model.ConnectedExam) *ConnectedExam { + var primussExamsAncodes []*PrimussExam + if exam.PrimussExams != nil && len(exam.PrimussExams) > 0 { + primussExamsAncodes = make([]*PrimussExam, 0, len(exam.PrimussExams)) + for _, primussExam := range exam.PrimussExams { + primussExamsAncodes = append(primussExamsAncodes, &PrimussExam{ + Ancode: primussExam.AnCode, + Program: primussExam.Program, + }) + } + } + + var otherPrimussExamsAncodes []*PrimussExam + if exam.OtherPrimussExams != nil && len(exam.OtherPrimussExams) > 0 { + otherPrimussExamsAncodes = make([]*PrimussExam, 0, len(exam.OtherPrimussExams)) + for _, otherPrimussExam := range exam.OtherPrimussExams { + otherPrimussExamsAncodes = append(otherPrimussExamsAncodes, &PrimussExam{ + Ancode: otherPrimussExam.AnCode, + Program: otherPrimussExam.Program, + }) + } + } + + return &ConnectedExam{ + ZpaExam: exam.ZpaExam.AnCode, + PrimussExams: primussExamsAncodes, + OtherPrimussExams: otherPrimussExamsAncodes, + Errors: exam.Errors, + } +} + +func (db *DB) connectedExamToModelConnectedExam(ctx context.Context, exam *ConnectedExam) (*model.ConnectedExam, error) { + zpaExam, err := db.GetZpaExamByAncode(ctx, exam.ZpaExam) + if err != nil { + log.Error().Err(err).Int("ancode", exam.ZpaExam).Msg("cannot get zpa exam") + return nil, err + } + + var primussExams []*model.PrimussExam + for _, exam := range exam.PrimussExams { + primussExam, err := db.GetPrimussExam(ctx, exam.Program, exam.Ancode) + if err != nil { + log.Error().Err(err).Int("ancode", exam.Ancode).Str("program", exam.Program).Msg("cannot get primuss exam") + return nil, err + } + primussExams = append(primussExams, primussExam) + } + + var otherPrimussExams []*model.PrimussExam + for _, exam := range exam.OtherPrimussExams { + primussExam, err := db.GetPrimussExam(ctx, exam.Program, exam.Ancode) + if err != nil { + log.Error().Err(err).Int("ancode", exam.Ancode).Str("program", exam.Program).Msg("cannot get primuss exam") + return nil, err + } + otherPrimussExams = append(otherPrimussExams, primussExam) + } + + return &model.ConnectedExam{ + ZpaExam: zpaExam, + PrimussExams: primussExams, + OtherPrimussExams: otherPrimussExams, + Errors: exam.Errors, + }, nil +} diff --git a/db/primuss_exam.go b/db/primuss_exam.go index 94fac60..3aa0479 100644 --- a/db/primuss_exam.go +++ b/db/primuss_exam.go @@ -116,20 +116,9 @@ func (db *DB) getPrimussExams(ctx context.Context, program string) ([]*model.Pri } defer cur.Close(ctx) - for cur.Next(ctx) { - var exam model.PrimussExam + err = cur.All(ctx, &exams) - err := cur.Decode(&exam) - if err != nil { - log.Error().Err(err).Str("semester", db.semester).Str("program", program).Interface("cur", cur). - Msg("Cannot decode to exam") - return exams, err - } - - exams = append(exams, &exam) - } - - if err := cur.Err(); err != nil { + if err != nil { log.Error().Err(err).Str("semester", db.semester).Str("program", program).Msg("Cursor returned error") return exams, err } From dbcf116681b543db601c5750c935741ab253783a Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Thu, 27 Jul 2023 11:48:32 +0200 Subject: [PATCH 06/78] add Exam --- README.md | 11 +- db/exam.go | 40 +- graph/exam.graphqls | 26 + graph/generated/generated.go | 1285 +++++++++++++++++++++++++----- graph/model/exam.go | 28 +- graph/model/models_gen.go | 19 + graph/mutation.graphqls | 2 +- graph/mutation.resolvers.go | 5 - graph/zpa.graphqls | 1 + plexams/exam.go | 226 +++--- plexams/prepare.go | 4 +- plexams/validate_invigilation.go | 1 + 12 files changed, 1277 insertions(+), 371 deletions(-) diff --git a/README.md b/README.md index c47e000..b0a14b5 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ - teachers - zpaexams +## Datenmodell + ```mermaid erDiagram teachers @@ -18,10 +20,17 @@ erDiagram zpaexams ||--|| zpaexamsToPlan: planOrNot constraints |o--|| zpaexams: hasConstraint zpaexams |o--o{ exams_primuss: connectedExam - additionalExam |o--o{ exams_primuss: connectedAdditionalExam + externalExams { + int ancode + string program + } ``` + additionalExam |o--o{ exams_primuss: connectedAdditionalExam + conflicts_XY count_XY exams_XY studentregs_XY + +## Ablauf diff --git a/db/exam.go b/db/exam.go index ba3ab42..c12da40 100644 --- a/db/exam.go +++ b/db/exam.go @@ -2,12 +2,10 @@ package db import ( "context" - "fmt" "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) @@ -68,25 +66,25 @@ func (db *DB) ExamsAlreadyPrepared(ctx context.Context) bool { return docsCount != 0 } -func (db *DB) AddExam(ctx context.Context, exam *model.Exam) error { - collection := db.Client.Database(db.databaseName).Collection("exams") - - result := collection.FindOne(ctx, bson.D{{Key: "ancode", Value: exam.AnCode}}) - if result.Err() == nil { - log.Error().Int("ancode", exam.AnCode).Msg("cannot add exam, exam with ancode already in db") - return fmt.Errorf("cannot add exam, exam with ancode %d already in db", exam.AnCode) - } - - if result.Err() == mongo.ErrNoDocuments { - _, err := collection.InsertOne(ctx, exam) - if err != nil { - return err - } - return nil - } - - return result.Err() -} +// func (db *DB) AddExam(ctx context.Context, exam *model.Exam) error { +// collection := db.Client.Database(db.databaseName).Collection("exams") + +// result := collection.FindOne(ctx, bson.D{{Key: "ancode", Value: exam.AnCode}}) +// if result.Err() == nil { +// log.Error().Int("ancode", exam.AnCode).Msg("cannot add exam, exam with ancode already in db") +// return fmt.Errorf("cannot add exam, exam with ancode %d already in db", exam.AnCode) +// } + +// if result.Err() == mongo.ErrNoDocuments { +// _, err := collection.InsertOne(ctx, exam) +// if err != nil { +// return err +// } +// return nil +// } + +// return result.Err() +// } func (db *DB) SaveExamsWithRegs(ctx context.Context, exams []*model.ExamWithRegs) error { collection := db.Client.Database(db.databaseName).Collection(collectionNameExamsWithRegs) diff --git a/graph/exam.graphqls b/graph/exam.graphqls index 54d4c22..107a8dd 100644 --- a/graph/exam.graphqls +++ b/graph/exam.graphqls @@ -1,3 +1,4 @@ +# TODO: remove me input AdditionalExamInput { ancode: Int! module: String! @@ -7,6 +8,7 @@ input AdditionalExamInput { groups: [String!]! } +# TODO: remove me type AdditionalExam { ancode: Int! module: String! @@ -17,6 +19,7 @@ type AdditionalExam { groups: [String!]! } +# TODO: remove me type ExamWithRegs { ancode: Int! zpaExam: ZPAExam! @@ -45,17 +48,20 @@ type RoomConstraints { seb: Boolean! } +# TODO: remove me type ExamToPlan { exam: ExamWithRegs! constraints: Constraints } +# TODO: remove me type PlannedExamWithNTA { exam: ExamWithRegs! constraints: Constraints nta: [NTAWithRegs!] } +# TODO: remove me type ExamInPlan { exam: ExamWithRegs! constraints: Constraints @@ -63,9 +69,29 @@ type ExamInPlan { slot: Slot } +# TODO: remove me type ExamWithRegsAndRooms { exam: ExamInPlan! normalRegs: [StudentReg!]! ntaRegs: [NTAWithRegs!]! rooms: [RoomForExam!]! } + +type ExternalExam { + ancode: Int! + program: String! +} + +type Exam { + ancode: Int! + zpaExam: ZPAExam + externalExam: ExternalExam + primussExams: [PrimussExam!]! + studentRegs: [StudentRegsPerAncodeAndProgram!]! + conflicts: [ConflictPerProgram!]! + connectErrors: [String!]! + constraints: Constraints + nta: [NTAWithRegs!] + slot: Slot + rooms: [RoomForExam!] +} diff --git a/graph/generated/generated.go b/graph/generated/generated.go index bdb1254..daf9c84 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -97,6 +97,20 @@ type ComplexityRoot struct { SameSlot func(childComplexity int) int } + Exam struct { + Ancode func(childComplexity int) int + Conflicts func(childComplexity int) int + ConnectErrors func(childComplexity int) int + Constraints func(childComplexity int) int + ExternalExam func(childComplexity int) int + Nta func(childComplexity int) int + PrimussExams func(childComplexity int) int + Rooms func(childComplexity int) int + Slot func(childComplexity int) int + StudentRegs func(childComplexity int) int + ZpaExam func(childComplexity int) int + } + ExamDay struct { Date func(childComplexity int) int Number func(childComplexity int) int @@ -160,6 +174,11 @@ type ComplexityRoot struct { MainExamerID func(childComplexity int) int } + ExternalExam struct { + Ancode func(childComplexity int) int + Program func(childComplexity int) int + } + FK07Program struct { Name func(childComplexity int) int } @@ -238,7 +257,6 @@ type ComplexityRoot struct { Online func(childComplexity int, ancode int) int PlacesWithSockets func(childComplexity int, ancode int) int PossibleDays func(childComplexity int, ancode int, days []string) int - PrepareExams func(childComplexity int, input []*model.PrimussExamInput) int RemovePrimussExam func(childComplexity int, input *model.PrimussExamInput) int RmExamGroupFromSlot func(childComplexity int, examGroupCode int) int RmZpaExamFromPlan func(childComplexity int, ancode int) int @@ -554,7 +572,6 @@ type MutationResolver interface { RmZpaExamFromPlan(ctx context.Context, ancode int) (bool, error) AddAdditionalExam(ctx context.Context, exam model.AdditionalExamInput) (bool, error) RemovePrimussExam(ctx context.Context, input *model.PrimussExamInput) (bool, error) - PrepareExams(ctx context.Context, input []*model.PrimussExamInput) (bool, error) AddNta(ctx context.Context, input model.NTAInput) (*model.NTA, error) NotPlannedByMe(ctx context.Context, ancode int) (bool, error) ExcludeDays(ctx context.Context, ancode int, days []string) (bool, error) @@ -853,6 +870,83 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Constraints.SameSlot(childComplexity), true + case "Exam.ancode": + if e.complexity.Exam.Ancode == nil { + break + } + + return e.complexity.Exam.Ancode(childComplexity), true + + case "Exam.conflicts": + if e.complexity.Exam.Conflicts == nil { + break + } + + return e.complexity.Exam.Conflicts(childComplexity), true + + case "Exam.connectErrors": + if e.complexity.Exam.ConnectErrors == nil { + break + } + + return e.complexity.Exam.ConnectErrors(childComplexity), true + + case "Exam.constraints": + if e.complexity.Exam.Constraints == nil { + break + } + + return e.complexity.Exam.Constraints(childComplexity), true + + case "Exam.externalExam": + if e.complexity.Exam.ExternalExam == nil { + break + } + + return e.complexity.Exam.ExternalExam(childComplexity), true + + case "Exam.nta": + if e.complexity.Exam.Nta == nil { + break + } + + return e.complexity.Exam.Nta(childComplexity), true + + case "Exam.primussExams": + if e.complexity.Exam.PrimussExams == nil { + break + } + + return e.complexity.Exam.PrimussExams(childComplexity), true + + case "Exam.rooms": + if e.complexity.Exam.Rooms == nil { + break + } + + return e.complexity.Exam.Rooms(childComplexity), true + + case "Exam.slot": + if e.complexity.Exam.Slot == nil { + break + } + + return e.complexity.Exam.Slot(childComplexity), true + + case "Exam.studentRegs": + if e.complexity.Exam.StudentRegs == nil { + break + } + + return e.complexity.Exam.StudentRegs(childComplexity), true + + case "Exam.zpaExam": + if e.complexity.Exam.ZpaExam == nil { + break + } + + return e.complexity.Exam.ZpaExam(childComplexity), true + case "ExamDay.date": if e.complexity.ExamDay.Date == nil { break @@ -1105,6 +1199,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.ExamerInPlan.MainExamerID(childComplexity), true + case "ExternalExam.ancode": + if e.complexity.ExternalExam.Ancode == nil { + break + } + + return e.complexity.ExternalExam.Ancode(childComplexity), true + + case "ExternalExam.program": + if e.complexity.ExternalExam.Program == nil { + break + } + + return e.complexity.ExternalExam.Program(childComplexity), true + case "FK07Program.name": if e.complexity.FK07Program.Name == nil { break @@ -1536,18 +1644,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.PossibleDays(childComplexity, args["ancode"].(int), args["days"].([]string)), true - case "Mutation.prepareExams": - if e.complexity.Mutation.PrepareExams == nil { - break - } - - args, err := ec.field_Mutation_prepareExams_args(context.TODO(), rawArgs) - if err != nil { - return 0, false - } - - return e.complexity.Mutation.PrepareExams(childComplexity, args["input"].([]*model.PrimussExamInput)), true - case "Mutation.removePrimussExam": if e.complexity.Mutation.RemovePrimussExam == nil { break @@ -3217,7 +3313,8 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er } var sources = []*ast.Source{ - {Name: "../exam.graphqls", Input: `input AdditionalExamInput { + {Name: "../exam.graphqls", Input: `# TODO: remove me +input AdditionalExamInput { ancode: Int! module: String! mainExamerID: Int! @@ -3226,6 +3323,7 @@ var sources = []*ast.Source{ groups: [String!]! } +# TODO: remove me type AdditionalExam { ancode: Int! module: String! @@ -3236,6 +3334,7 @@ type AdditionalExam { groups: [String!]! } +# TODO: remove me type ExamWithRegs { ancode: Int! zpaExam: ZPAExam! @@ -3264,17 +3363,20 @@ type RoomConstraints { seb: Boolean! } +# TODO: remove me type ExamToPlan { exam: ExamWithRegs! constraints: Constraints } +# TODO: remove me type PlannedExamWithNTA { exam: ExamWithRegs! constraints: Constraints nta: [NTAWithRegs!] } +# TODO: remove me type ExamInPlan { exam: ExamWithRegs! constraints: Constraints @@ -3282,12 +3384,32 @@ type ExamInPlan { slot: Slot } +# TODO: remove me type ExamWithRegsAndRooms { exam: ExamInPlan! normalRegs: [StudentReg!]! ntaRegs: [NTAWithRegs!]! rooms: [RoomForExam!]! } + +type ExternalExam { + ancode: Int! + program: String! +} + +type Exam { + ancode: Int! + zpaExam: ZPAExam + externalExam: ExternalExam + primussExams: [PrimussExam!]! + studentRegs: [StudentRegsPerAncodeAndProgram!]! + conflicts: [ConflictPerProgram!]! + connectErrors: [String!]! + constraints: Constraints + nta: [NTAWithRegs!] + slot: Slot + rooms: [RoomForExam!] +} `, BuiltIn: false}, {Name: "../invigilation.graphqls", Input: `type Invigilation { roomName: String @@ -3373,7 +3495,7 @@ type RoomWithInvigilator { addAdditionalExam(exam: AdditionalExamInput!): Boolean! # Primuss removePrimussExam(input: PrimussExamInput): Boolean! - prepareExams(input: [PrimussExamInput!]!): Boolean! + # prepareExams(input: [PrimussExamInput!]!): Boolean! addNTA(input: NTAInput!): NTA! # Contraints notPlannedByMe(ancode: Int!): Boolean! @@ -3759,6 +3881,7 @@ type FK07Program { name: String! } +# TODO: remove me type ZPAExamWithConstraints { zpaExam: ZPAExam! constraints: Constraints # == nil if no constraint @@ -4000,21 +4123,6 @@ func (ec *executionContext) field_Mutation_possibleDays_args(ctx context.Context return args, nil } -func (ec *executionContext) field_Mutation_prepareExams_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { - var err error - args := map[string]interface{}{} - var arg0 []*model.PrimussExamInput - if tmp, ok := rawArgs["input"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - arg0, err = ec.unmarshalNPrimussExamInput2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamInputᚄ(ctx, tmp) - if err != nil { - return nil, err - } - } - args["input"] = arg0 - return args, nil -} - func (ec *executionContext) field_Mutation_removePrimussExam_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -6005,8 +6113,8 @@ func (ec *executionContext) fieldContext_Constraints_roomConstraints(ctx context return fc, nil } -func (ec *executionContext) _ExamDay_number(ctx context.Context, field graphql.CollectedField, obj *model.ExamDay) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_ExamDay_number(ctx, field) +func (ec *executionContext) _Exam_ancode(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Exam_ancode(ctx, field) if err != nil { return graphql.Null } @@ -6019,7 +6127,7 @@ func (ec *executionContext) _ExamDay_number(ctx context.Context, field graphql.C }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Number, nil + return obj.Ancode, nil }) if err != nil { ec.Error(ctx, err) @@ -6036,9 +6144,9 @@ func (ec *executionContext) _ExamDay_number(ctx context.Context, field graphql.C return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ExamDay_number(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Exam_ancode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "ExamDay", + Object: "Exam", Field: field, IsMethod: false, IsResolver: false, @@ -6049,8 +6157,8 @@ func (ec *executionContext) fieldContext_ExamDay_number(ctx context.Context, fie return fc, nil } -func (ec *executionContext) _ExamDay_date(ctx context.Context, field graphql.CollectedField, obj *model.ExamDay) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_ExamDay_date(ctx, field) +func (ec *executionContext) _Exam_zpaExam(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Exam_zpaExam(ctx, field) if err != nil { return graphql.Null } @@ -6063,38 +6171,59 @@ func (ec *executionContext) _ExamDay_date(ctx context.Context, field graphql.Col }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Date, nil + return obj.ZpaExam, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(time.Time) + res := resTmp.(*model.ZPAExam) fc.Result = res - return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) + return ec.marshalOZPAExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExam(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ExamDay_date(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Exam_zpaExam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "ExamDay", + Object: "Exam", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Time does not have child fields") + switch field.Name { + case "zpaID": + return ec.fieldContext_ZPAExam_zpaID(ctx, field) + case "semester": + return ec.fieldContext_ZPAExam_semester(ctx, field) + case "ancode": + return ec.fieldContext_ZPAExam_ancode(ctx, field) + case "module": + return ec.fieldContext_ZPAExam_module(ctx, field) + case "mainExamer": + return ec.fieldContext_ZPAExam_mainExamer(ctx, field) + case "mainExamerID": + return ec.fieldContext_ZPAExam_mainExamerID(ctx, field) + case "examType": + return ec.fieldContext_ZPAExam_examType(ctx, field) + case "examTypeFull": + return ec.fieldContext_ZPAExam_examTypeFull(ctx, field) + case "duration": + return ec.fieldContext_ZPAExam_duration(ctx, field) + case "isRepeaterExam": + return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) + case "groups": + return ec.fieldContext_ZPAExam_groups(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) }, } return fc, nil } -func (ec *executionContext) _ExamGroup_examGroupCode(ctx context.Context, field graphql.CollectedField, obj *model.ExamGroup) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_ExamGroup_examGroupCode(ctx, field) +func (ec *executionContext) _Exam_externalExam(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Exam_externalExam(ctx, field) if err != nil { return graphql.Null } @@ -6107,38 +6236,41 @@ func (ec *executionContext) _ExamGroup_examGroupCode(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.ExamGroupCode, nil + return obj.ExternalExam, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(int) + res := resTmp.(*model.ExternalExam) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalOExternalExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExternalExam(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ExamGroup_examGroupCode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Exam_externalExam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "ExamGroup", + Object: "Exam", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") + switch field.Name { + case "ancode": + return ec.fieldContext_ExternalExam_ancode(ctx, field) + case "program": + return ec.fieldContext_ExternalExam_program(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ExternalExam", field.Name) }, } return fc, nil } -func (ec *executionContext) _ExamGroup_exams(ctx context.Context, field graphql.CollectedField, obj *model.ExamGroup) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_ExamGroup_exams(ctx, field) +func (ec *executionContext) _Exam_primussExams(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Exam_primussExams(ctx, field) if err != nil { return graphql.Null } @@ -6151,7 +6283,7 @@ func (ec *executionContext) _ExamGroup_exams(ctx context.Context, field graphql. }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Exams, nil + return obj.PrimussExams, nil }) if err != nil { ec.Error(ctx, err) @@ -6163,32 +6295,44 @@ func (ec *executionContext) _ExamGroup_exams(ctx context.Context, field graphql. } return graphql.Null } - res := resTmp.([]*model.ExamToPlan) + res := resTmp.([]*model.PrimussExam) fc.Result = res - return ec.marshalNExamToPlan2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamToPlanᚄ(ctx, field.Selections, res) + return ec.marshalNPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ExamGroup_exams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Exam_primussExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "ExamGroup", + Object: "Exam", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "exam": - return ec.fieldContext_ExamToPlan_exam(ctx, field) - case "constraints": - return ec.fieldContext_ExamToPlan_constraints(ctx, field) + case "ancode": + return ec.fieldContext_PrimussExam_ancode(ctx, field) + case "module": + return ec.fieldContext_PrimussExam_module(ctx, field) + case "mainExamer": + return ec.fieldContext_PrimussExam_mainExamer(ctx, field) + case "program": + return ec.fieldContext_PrimussExam_program(ctx, field) + case "examType": + return ec.fieldContext_PrimussExam_examType(ctx, field) + case "presence": + return ec.fieldContext_PrimussExam_presence(ctx, field) + case "studentRegs": + return ec.fieldContext_PrimussExam_studentRegs(ctx, field) + case "conflicts": + return ec.fieldContext_PrimussExam_conflicts(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ExamToPlan", field.Name) + return nil, fmt.Errorf("no field named %q was found under type PrimussExam", field.Name) }, } return fc, nil } -func (ec *executionContext) _ExamGroup_examGroupInfo(ctx context.Context, field graphql.CollectedField, obj *model.ExamGroup) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_ExamGroup_examGroupInfo(ctx, field) +func (ec *executionContext) _Exam_studentRegs(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Exam_studentRegs(ctx, field) if err != nil { return graphql.Null } @@ -6201,59 +6345,44 @@ func (ec *executionContext) _ExamGroup_examGroupInfo(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.ExamGroupInfo, nil + return obj.StudentRegs, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*model.ExamGroupInfo) + res := resTmp.([]*model.StudentRegsPerAncodeAndProgram) fc.Result = res - return ec.marshalOExamGroupInfo2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupInfo(ctx, field.Selections, res) + return ec.marshalNStudentRegsPerAncodeAndProgram2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentRegsPerAncodeAndProgramᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ExamGroup_examGroupInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Exam_studentRegs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "ExamGroup", + Object: "Exam", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "notPlannedByMe": - return ec.fieldContext_ExamGroupInfo_notPlannedByMe(ctx, field) - case "excludeDays": - return ec.fieldContext_ExamGroupInfo_excludeDays(ctx, field) - case "possibleDays": - return ec.fieldContext_ExamGroupInfo_possibleDays(ctx, field) - case "fixedDay": - return ec.fieldContext_ExamGroupInfo_fixedDay(ctx, field) - case "fixedSlot": - return ec.fieldContext_ExamGroupInfo_fixedSlot(ctx, field) - case "possibleSlots": - return ec.fieldContext_ExamGroupInfo_possibleSlots(ctx, field) - case "conflicts": - return ec.fieldContext_ExamGroupInfo_conflicts(ctx, field) + case "program": + return ec.fieldContext_StudentRegsPerAncodeAndProgram_program(ctx, field) case "studentRegs": - return ec.fieldContext_ExamGroupInfo_studentRegs(ctx, field) - case "programs": - return ec.fieldContext_ExamGroupInfo_programs(ctx, field) - case "maxDuration": - return ec.fieldContext_ExamGroupInfo_maxDuration(ctx, field) - case "maxDurationNTA": - return ec.fieldContext_ExamGroupInfo_maxDurationNTA(ctx, field) + return ec.fieldContext_StudentRegsPerAncodeAndProgram_studentRegs(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ExamGroupInfo", field.Name) + return nil, fmt.Errorf("no field named %q was found under type StudentRegsPerAncodeAndProgram", field.Name) }, } return fc, nil } -func (ec *executionContext) _ExamGroupConflict_examGroupCode(ctx context.Context, field graphql.CollectedField, obj *model.ExamGroupConflict) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_ExamGroupConflict_examGroupCode(ctx, field) +func (ec *executionContext) _Exam_conflicts(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Exam_conflicts(ctx, field) if err != nil { return graphql.Null } @@ -6266,7 +6395,7 @@ func (ec *executionContext) _ExamGroupConflict_examGroupCode(ctx context.Context }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.ExamGroupCode, nil + return obj.Conflicts, nil }) if err != nil { ec.Error(ctx, err) @@ -6278,26 +6407,32 @@ func (ec *executionContext) _ExamGroupConflict_examGroupCode(ctx context.Context } return graphql.Null } - res := resTmp.(int) + res := resTmp.([]*model.ConflictPerProgram) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNConflictPerProgram2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictPerProgramᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ExamGroupConflict_examGroupCode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Exam_conflicts(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "ExamGroupConflict", + Object: "Exam", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") + switch field.Name { + case "program": + return ec.fieldContext_ConflictPerProgram_program(ctx, field) + case "conflicts": + return ec.fieldContext_ConflictPerProgram_conflicts(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ConflictPerProgram", field.Name) }, } return fc, nil } -func (ec *executionContext) _ExamGroupConflict_count(ctx context.Context, field graphql.CollectedField, obj *model.ExamGroupConflict) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_ExamGroupConflict_count(ctx, field) +func (ec *executionContext) _Exam_connectErrors(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Exam_connectErrors(ctx, field) if err != nil { return graphql.Null } @@ -6310,7 +6445,7 @@ func (ec *executionContext) _ExamGroupConflict_count(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Count, nil + return obj.ConnectErrors, nil }) if err != nil { ec.Error(ctx, err) @@ -6322,14 +6457,563 @@ func (ec *executionContext) _ExamGroupConflict_count(ctx context.Context, field } return graphql.Null } - res := resTmp.(int) + res := resTmp.([]string) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNString2ᚕstringᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ExamGroupConflict_count(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Exam_connectErrors(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "ExamGroupConflict", + Object: "Exam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Exam_constraints(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Exam_constraints(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Constraints, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.Constraints) + fc.Result = res + return ec.marshalOConstraints2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConstraints(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Exam_constraints(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Exam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "ancode": + return ec.fieldContext_Constraints_ancode(ctx, field) + case "notPlannedByMe": + return ec.fieldContext_Constraints_notPlannedByMe(ctx, field) + case "excludeDays": + return ec.fieldContext_Constraints_excludeDays(ctx, field) + case "possibleDays": + return ec.fieldContext_Constraints_possibleDays(ctx, field) + case "fixedDay": + return ec.fieldContext_Constraints_fixedDay(ctx, field) + case "fixedTime": + return ec.fieldContext_Constraints_fixedTime(ctx, field) + case "sameSlot": + return ec.fieldContext_Constraints_sameSlot(ctx, field) + case "online": + return ec.fieldContext_Constraints_online(ctx, field) + case "roomConstraints": + return ec.fieldContext_Constraints_roomConstraints(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Constraints", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Exam_nta(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Exam_nta(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Nta, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.NTAWithRegs) + fc.Result = res + return ec.marshalONTAWithRegs2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Exam_nta(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Exam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "nta": + return ec.fieldContext_NTAWithRegs_nta(ctx, field) + case "regs": + return ec.fieldContext_NTAWithRegs_regs(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type NTAWithRegs", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Exam_slot(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Exam_slot(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Slot, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.Slot) + fc.Result = res + return ec.marshalOSlot2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSlot(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Exam_slot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Exam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "dayNumber": + return ec.fieldContext_Slot_dayNumber(ctx, field) + case "slotNumber": + return ec.fieldContext_Slot_slotNumber(ctx, field) + case "starttime": + return ec.fieldContext_Slot_starttime(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Slot", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Exam_rooms(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Exam_rooms(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Rooms, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.RoomForExam) + fc.Result = res + return ec.marshalORoomForExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomForExamᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Exam_rooms(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Exam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "ancode": + return ec.fieldContext_RoomForExam_ancode(ctx, field) + case "room": + return ec.fieldContext_RoomForExam_room(ctx, field) + case "seatsPlanned": + return ec.fieldContext_RoomForExam_seatsPlanned(ctx, field) + case "duration": + return ec.fieldContext_RoomForExam_duration(ctx, field) + case "handicap": + return ec.fieldContext_RoomForExam_handicap(ctx, field) + case "reserve": + return ec.fieldContext_RoomForExam_reserve(ctx, field) + case "students": + return ec.fieldContext_RoomForExam_students(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type RoomForExam", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _ExamDay_number(ctx context.Context, field graphql.CollectedField, obj *model.ExamDay) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ExamDay_number(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Number, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ExamDay_number(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ExamDay", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _ExamDay_date(ctx context.Context, field graphql.CollectedField, obj *model.ExamDay) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ExamDay_date(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Date, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(time.Time) + fc.Result = res + return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ExamDay_date(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ExamDay", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Time does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _ExamGroup_examGroupCode(ctx context.Context, field graphql.CollectedField, obj *model.ExamGroup) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ExamGroup_examGroupCode(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ExamGroupCode, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ExamGroup_examGroupCode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ExamGroup", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _ExamGroup_exams(ctx context.Context, field graphql.CollectedField, obj *model.ExamGroup) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ExamGroup_exams(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Exams, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.ExamToPlan) + fc.Result = res + return ec.marshalNExamToPlan2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamToPlanᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ExamGroup_exams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ExamGroup", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "exam": + return ec.fieldContext_ExamToPlan_exam(ctx, field) + case "constraints": + return ec.fieldContext_ExamToPlan_constraints(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ExamToPlan", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _ExamGroup_examGroupInfo(ctx context.Context, field graphql.CollectedField, obj *model.ExamGroup) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ExamGroup_examGroupInfo(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ExamGroupInfo, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.ExamGroupInfo) + fc.Result = res + return ec.marshalOExamGroupInfo2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupInfo(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ExamGroup_examGroupInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ExamGroup", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "notPlannedByMe": + return ec.fieldContext_ExamGroupInfo_notPlannedByMe(ctx, field) + case "excludeDays": + return ec.fieldContext_ExamGroupInfo_excludeDays(ctx, field) + case "possibleDays": + return ec.fieldContext_ExamGroupInfo_possibleDays(ctx, field) + case "fixedDay": + return ec.fieldContext_ExamGroupInfo_fixedDay(ctx, field) + case "fixedSlot": + return ec.fieldContext_ExamGroupInfo_fixedSlot(ctx, field) + case "possibleSlots": + return ec.fieldContext_ExamGroupInfo_possibleSlots(ctx, field) + case "conflicts": + return ec.fieldContext_ExamGroupInfo_conflicts(ctx, field) + case "studentRegs": + return ec.fieldContext_ExamGroupInfo_studentRegs(ctx, field) + case "programs": + return ec.fieldContext_ExamGroupInfo_programs(ctx, field) + case "maxDuration": + return ec.fieldContext_ExamGroupInfo_maxDuration(ctx, field) + case "maxDurationNTA": + return ec.fieldContext_ExamGroupInfo_maxDurationNTA(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ExamGroupInfo", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _ExamGroupConflict_examGroupCode(ctx context.Context, field graphql.CollectedField, obj *model.ExamGroupConflict) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ExamGroupConflict_examGroupCode(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ExamGroupCode, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ExamGroupConflict_examGroupCode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ExamGroupConflict", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _ExamGroupConflict_count(ctx context.Context, field graphql.CollectedField, obj *model.ExamGroupConflict) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ExamGroupConflict_count(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Count, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ExamGroupConflict_count(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ExamGroupConflict", Field: field, IsMethod: false, IsResolver: false, @@ -7699,8 +8383,96 @@ func (ec *executionContext) fieldContext_ExamWithRegsAndRooms_rooms(ctx context. return fc, nil } -func (ec *executionContext) _ExamerInPlan_mainExamer(ctx context.Context, field graphql.CollectedField, obj *model.ExamerInPlan) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_ExamerInPlan_mainExamer(ctx, field) +func (ec *executionContext) _ExamerInPlan_mainExamer(ctx context.Context, field graphql.CollectedField, obj *model.ExamerInPlan) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ExamerInPlan_mainExamer(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.MainExamer, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ExamerInPlan_mainExamer(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ExamerInPlan", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _ExamerInPlan_mainExamerID(ctx context.Context, field graphql.CollectedField, obj *model.ExamerInPlan) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ExamerInPlan_mainExamerID(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.MainExamerID, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ExamerInPlan_mainExamerID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ExamerInPlan", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _ExternalExam_ancode(ctx context.Context, field graphql.CollectedField, obj *model.ExternalExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ExternalExam_ancode(ctx, field) if err != nil { return graphql.Null } @@ -7713,7 +8485,7 @@ func (ec *executionContext) _ExamerInPlan_mainExamer(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.MainExamer, nil + return obj.Ancode, nil }) if err != nil { ec.Error(ctx, err) @@ -7725,26 +8497,26 @@ func (ec *executionContext) _ExamerInPlan_mainExamer(ctx context.Context, field } return graphql.Null } - res := resTmp.(string) + res := resTmp.(int) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ExamerInPlan_mainExamer(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ExternalExam_ancode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "ExamerInPlan", + Object: "ExternalExam", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + return nil, errors.New("field of type Int does not have child fields") }, } return fc, nil } -func (ec *executionContext) _ExamerInPlan_mainExamerID(ctx context.Context, field graphql.CollectedField, obj *model.ExamerInPlan) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_ExamerInPlan_mainExamerID(ctx, field) +func (ec *executionContext) _ExternalExam_program(ctx context.Context, field graphql.CollectedField, obj *model.ExternalExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ExternalExam_program(ctx, field) if err != nil { return graphql.Null } @@ -7757,7 +8529,7 @@ func (ec *executionContext) _ExamerInPlan_mainExamerID(ctx context.Context, fiel }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.MainExamerID, nil + return obj.Program, nil }) if err != nil { ec.Error(ctx, err) @@ -7769,19 +8541,19 @@ func (ec *executionContext) _ExamerInPlan_mainExamerID(ctx context.Context, fiel } return graphql.Null } - res := resTmp.(int) + res := resTmp.(string) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ExamerInPlan_mainExamerID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ExternalExam_program(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "ExamerInPlan", + Object: "ExternalExam", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil @@ -10083,61 +10855,6 @@ func (ec *executionContext) fieldContext_Mutation_removePrimussExam(ctx context. return fc, nil } -func (ec *executionContext) _Mutation_prepareExams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Mutation_prepareExams(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().PrepareExams(rctx, fc.Args["input"].([]*model.PrimussExamInput)) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(bool) - fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Mutation_prepareExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Mutation", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Boolean does not have child fields") - }, - } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Mutation_prepareExams_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } - return fc, nil -} - func (ec *executionContext) _Mutation_addNTA(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Mutation_addNTA(ctx, field) if err != nil { @@ -23205,6 +23922,77 @@ func (ec *executionContext) _Constraints(ctx context.Context, sel ast.SelectionS return out } +var examImplementors = []string{"Exam"} + +func (ec *executionContext) _Exam(ctx context.Context, sel ast.SelectionSet, obj *model.Exam) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, examImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Exam") + case "ancode": + out.Values[i] = ec._Exam_ancode(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "zpaExam": + out.Values[i] = ec._Exam_zpaExam(ctx, field, obj) + case "externalExam": + out.Values[i] = ec._Exam_externalExam(ctx, field, obj) + case "primussExams": + out.Values[i] = ec._Exam_primussExams(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "studentRegs": + out.Values[i] = ec._Exam_studentRegs(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "conflicts": + out.Values[i] = ec._Exam_conflicts(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "connectErrors": + out.Values[i] = ec._Exam_connectErrors(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "constraints": + out.Values[i] = ec._Exam_constraints(ctx, field, obj) + case "nta": + out.Values[i] = ec._Exam_nta(ctx, field, obj) + case "slot": + out.Values[i] = ec._Exam_slot(ctx, field, obj) + case "rooms": + out.Values[i] = ec._Exam_rooms(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var examDayImplementors = []string{"ExamDay"} func (ec *executionContext) _ExamDay(ctx context.Context, sel ast.SelectionSet, obj *model.ExamDay) graphql.Marshaler { @@ -23655,6 +24443,50 @@ func (ec *executionContext) _ExamerInPlan(ctx context.Context, sel ast.Selection return out } +var externalExamImplementors = []string{"ExternalExam"} + +func (ec *executionContext) _ExternalExam(ctx context.Context, sel ast.SelectionSet, obj *model.ExternalExam) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, externalExamImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("ExternalExam") + case "ancode": + out.Values[i] = ec._ExternalExam_ancode(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "program": + out.Values[i] = ec._ExternalExam_program(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var fK07ProgramImplementors = []string{"FK07Program"} func (ec *executionContext) _FK07Program(ctx context.Context, sel ast.SelectionSet, obj *model.FK07Program) graphql.Marshaler { @@ -24175,13 +25007,6 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) if out.Values[i] == graphql.Null { out.Invalids++ } - case "prepareExams": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_prepareExams(ctx, field) - }) - if out.Values[i] == graphql.Null { - out.Invalids++ - } case "addNTA": out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { return ec._Mutation_addNTA(ctx, field) @@ -28551,28 +29376,6 @@ func (ec *executionContext) marshalNPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexa return ec._PrimussExam(ctx, sel, v) } -func (ec *executionContext) unmarshalNPrimussExamInput2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamInputᚄ(ctx context.Context, v interface{}) ([]*model.PrimussExamInput, error) { - var vSlice []interface{} - if v != nil { - vSlice = graphql.CoerceList(v) - } - var err error - res := make([]*model.PrimussExamInput, len(vSlice)) - for i := range vSlice { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNPrimussExamInput2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamInput(ctx, vSlice[i]) - if err != nil { - return nil, err - } - } - return res, nil -} - -func (ec *executionContext) unmarshalNPrimussExamInput2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamInput(ctx context.Context, v interface{}) (*model.PrimussExamInput, error) { - res, err := ec.unmarshalInputPrimussExamInput(ctx, v) - return &res, graphql.ErrorOnPath(ctx, err) -} - func (ec *executionContext) marshalNRegWithError2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRegWithErrorᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.RegWithError) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup @@ -30338,6 +31141,13 @@ func (ec *executionContext) marshalOExamerInPlan2ᚕᚖgithubᚗcomᚋobcodeᚋp return ret } +func (ec *executionContext) marshalOExternalExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExternalExam(ctx context.Context, sel ast.SelectionSet, v *model.ExternalExam) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._ExternalExam(ctx, sel, v) +} + func (ec *executionContext) unmarshalOInt2ᚕintᚄ(ctx context.Context, v interface{}) ([]int, error) { if v == nil { return nil, nil @@ -30871,6 +31681,53 @@ func (ec *executionContext) marshalORoomConstraints2ᚖgithubᚗcomᚋobcodeᚋp return ec._RoomConstraints(ctx, sel, v) } +func (ec *executionContext) marshalORoomForExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomForExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.RoomForExam) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNRoomForExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomForExam(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + func (ec *executionContext) marshalOSemesterConfig2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSemesterConfig(ctx context.Context, sel ast.SelectionSet, v *model.SemesterConfig) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/graph/model/exam.go b/graph/model/exam.go index 23437dd..36f1cc2 100644 --- a/graph/model/exam.go +++ b/graph/model/exam.go @@ -5,20 +5,20 @@ type RemovedPrimussExam struct { Program string `bson:"Stg"` } -type Exam struct { - Semester string `json:"semester"` - AnCode int `json:"ancode"` - Module string `json:"module"` - MainExamer *Teacher `json:"main_examer"` - MainExamerName string `json:"main_examer_name"` - MainExamerID int `json:"main_examer_id"` - ExamType string `json:"exam_type"` - Duration int `json:"duration"` - IsRepeaterExam bool `json:"is_repeater_exam"` - ZpaGroups []string `json:"groups"` - RemovedPrimussExams []RemovedPrimussExam `json:"removedPrimussExams"` - RegisteredExams []*RegisteredExam `json:"registeredExams"` -} +// type Exam struct { +// Semester string `json:"semester"` +// AnCode int `json:"ancode"` +// Module string `json:"module"` +// MainExamer *Teacher `json:"main_examer"` +// MainExamerName string `json:"main_examer_name"` +// MainExamerID int `json:"main_examer_id"` +// ExamType string `json:"exam_type"` +// Duration int `json:"duration"` +// IsRepeaterExam bool `json:"is_repeater_exam"` +// ZpaGroups []string `json:"groups"` +// RemovedPrimussExams []RemovedPrimussExam `json:"removedPrimussExams"` +// RegisteredExams []*RegisteredExam `json:"registeredExams"` +// } func (exam *ExamToPlan) IsGO() bool { for _, primussExam := range exam.Exam.PrimussExams { diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index 56db2b1..a4ac6ba 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -53,6 +53,20 @@ type Constraints struct { RoomConstraints *RoomConstraints `json:"roomConstraints,omitempty"` } +type Exam struct { + Ancode int `json:"ancode"` + ZpaExam *ZPAExam `json:"zpaExam,omitempty"` + ExternalExam *ExternalExam `json:"externalExam,omitempty"` + PrimussExams []*PrimussExam `json:"primussExams"` + StudentRegs []*StudentRegsPerAncodeAndProgram `json:"studentRegs"` + Conflicts []*ConflictPerProgram `json:"conflicts"` + ConnectErrors []string `json:"connectErrors"` + Constraints *Constraints `json:"constraints,omitempty"` + Nta []*NTAWithRegs `json:"nta,omitempty"` + Slot *Slot `json:"slot,omitempty"` + Rooms []*RoomForExam `json:"rooms,omitempty"` +} + type ExamDay struct { Number int `json:"number"` Date time.Time `json:"date"` @@ -116,6 +130,11 @@ type ExamerInPlan struct { MainExamerID int `json:"mainExamerID"` } +type ExternalExam struct { + Ancode int `json:"ancode"` + Program string `json:"program"` +} + type FK07Program struct { Name string `json:"name"` } diff --git a/graph/mutation.graphqls b/graph/mutation.graphqls index a43d4df..b6971d5 100644 --- a/graph/mutation.graphqls +++ b/graph/mutation.graphqls @@ -8,7 +8,7 @@ type Mutation { addAdditionalExam(exam: AdditionalExamInput!): Boolean! # Primuss removePrimussExam(input: PrimussExamInput): Boolean! - prepareExams(input: [PrimussExamInput!]!): Boolean! + # prepareExams(input: [PrimussExamInput!]!): Boolean! addNTA(input: NTAInput!): NTA! # Contraints notPlannedByMe(ancode: Int!): Boolean! diff --git a/graph/mutation.resolvers.go b/graph/mutation.resolvers.go index bcb4308..8254895 100644 --- a/graph/mutation.resolvers.go +++ b/graph/mutation.resolvers.go @@ -41,11 +41,6 @@ func (r *mutationResolver) RemovePrimussExam(ctx context.Context, input *model.P return r.plexams.RemovePrimussExam(ctx, input) } -// PrepareExams is the resolver for the prepareExams field. -func (r *mutationResolver) PrepareExams(ctx context.Context, input []*model.PrimussExamInput) (bool, error) { - return r.plexams.PrepareExams(ctx, input) -} - // AddNta is the resolver for the addNTA field. func (r *mutationResolver) AddNta(ctx context.Context, input model.NTAInput) (*model.NTA, error) { return r.plexams.AddNta(ctx, input) diff --git a/graph/zpa.graphqls b/graph/zpa.graphqls index 1612eef..905007b 100644 --- a/graph/zpa.graphqls +++ b/graph/zpa.graphqls @@ -40,6 +40,7 @@ type FK07Program { name: String! } +# TODO: remove me type ZPAExamWithConstraints { zpaExam: ZPAExam! constraints: Constraints # == nil if no constraint diff --git a/plexams/exam.go b/plexams/exam.go index 8cfb3c1..98c4e96 100644 --- a/plexams/exam.go +++ b/plexams/exam.go @@ -149,86 +149,86 @@ func (p *Plexams) PrepareConnectedExam(ancode int) error { return nil } -func (p *Plexams) PrepareExams(ctx context.Context, inputs []*model.PrimussExamInput) (bool, error) { - if p.dbClient.ExamsAlreadyPrepared(ctx) { - oks := true - for _, input := range inputs { - ok, err := p.RemovePrimussExam(ctx, input) - if err != nil { - return false, err - } - oks = oks && ok - } - return oks, nil - } else { - connectedExams, err := p.GetConnectedExams(ctx) - if err != nil { - return false, err - } - - oks := true - for _, connectedExam := range connectedExams { - // generate Exam and add Teacher - exam, err := p.zpaExamToExam(ctx, connectedExam.ZpaExam) - if err != nil { - // FIXME: Maybe not a good idea? - return false, err - } - - for _, primussExam := range connectedExam.PrimussExams { - - if isConnected(primussExam, inputs) { - studentRegs, err := p.GetStudentRegs(ctx, primussExam) - if err != nil { - err := p.Log(ctx, fmt.Sprintf("no studentRegs for primuss exam %s/%d", - primussExam.Program, primussExam.AnCode), "") - if err != nil { - log.Error().Err(err).Msg("cannot log") - } - } - conflicts, err := p.GetConflicts(ctx, primussExam) - if err != nil { - err := p.Log(ctx, fmt.Sprintf("no studentRegs for primuss exam %s/%d", - primussExam.Program, primussExam.AnCode), "") - if err != nil { - log.Error().Err(err).Msg("cannot log") - } - } - exam.RegisteredExams = append(exam.RegisteredExams, &model.RegisteredExam{ - Exam: primussExam, - StudentRegs: studentRegs, - Conflicts: conflicts.Conflicts, - }) - } else { // should not be connected - if exam.RemovedPrimussExams == nil { - exam.RemovedPrimussExams = make([]model.RemovedPrimussExam, 0) - } - exam.RemovedPrimussExams = append(exam.RemovedPrimussExams, - model.RemovedPrimussExam{ - AnCode: primussExam.AnCode, - Program: primussExam.Program, - }) - // log to MongoDb - err := p.Log(ctx, fmt.Sprintf("removed primuss exam %s/%d from exam %d", - primussExam.Program, primussExam.AnCode, exam.AnCode), "") - if err != nil { - log.Error().Err(err).Str("program", primussExam.Program). - Int("ancode", primussExam.AnCode). - Msg("cannot log removed primuss exam") - } - } - } - - // add exam to db - err = p.dbClient.AddExam(ctx, exam) - if err != nil { - log.Error().Err(err).Int("ancode", exam.AnCode).Msg("cannot insert exam to db") - } - } - - return oks, nil - } -} +// func (p *Plexams) PrepareExams(ctx context.Context, inputs []*model.PrimussExamInput) (bool, error) { +// if p.dbClient.ExamsAlreadyPrepared(ctx) { +// oks := true +// for _, input := range inputs { +// ok, err := p.RemovePrimussExam(ctx, input) +// if err != nil { +// return false, err +// } +// oks = oks && ok +// } +// return oks, nil +// } else { +// connectedExams, err := p.GetConnectedExams(ctx) +// if err != nil { +// return false, err +// } + +// oks := true +// for _, connectedExam := range connectedExams { +// // generate Exam and add Teacher +// exam, err := p.zpaExamToExam(ctx, connectedExam.ZpaExam) +// if err != nil { +// // FIXME: Maybe not a good idea? +// return false, err +// } + +// for _, primussExam := range connectedExam.PrimussExams { + +// if isConnected(primussExam, inputs) { +// studentRegs, err := p.GetStudentRegs(ctx, primussExam) +// if err != nil { +// err := p.Log(ctx, fmt.Sprintf("no studentRegs for primuss exam %s/%d", +// primussExam.Program, primussExam.AnCode), "") +// if err != nil { +// log.Error().Err(err).Msg("cannot log") +// } +// } +// conflicts, err := p.GetConflicts(ctx, primussExam) +// if err != nil { +// err := p.Log(ctx, fmt.Sprintf("no studentRegs for primuss exam %s/%d", +// primussExam.Program, primussExam.AnCode), "") +// if err != nil { +// log.Error().Err(err).Msg("cannot log") +// } +// } +// exam.RegisteredExams = append(exam.RegisteredExams, &model.RegisteredExam{ +// Exam: primussExam, +// StudentRegs: studentRegs, +// Conflicts: conflicts.Conflicts, +// }) +// } else { // should not be connected +// if exam.RemovedPrimussExams == nil { +// exam.RemovedPrimussExams = make([]model.RemovedPrimussExam, 0) +// } +// exam.RemovedPrimussExams = append(exam.RemovedPrimussExams, +// model.RemovedPrimussExam{ +// AnCode: primussExam.AnCode, +// Program: primussExam.Program, +// }) +// // log to MongoDb +// err := p.Log(ctx, fmt.Sprintf("removed primuss exam %s/%d from exam %d", +// primussExam.Program, primussExam.AnCode, exam.AnCode), "") +// if err != nil { +// log.Error().Err(err).Str("program", primussExam.Program). +// Int("ancode", primussExam.AnCode). +// Msg("cannot log removed primuss exam") +// } +// } +// } + +// // add exam to db +// err = p.dbClient.AddExam(ctx, exam) +// if err != nil { +// log.Error().Err(err).Int("ancode", exam.AnCode).Msg("cannot insert exam to db") +// } +// } + +// return oks, nil +// } +// } func (p *Plexams) ConnectExam(ancode int, program string) error { ctx := context.Background() @@ -290,39 +290,39 @@ func (p *Plexams) RemovePrimussExam(ctx context.Context, input *model.PrimussExa return true, nil } -func isConnected(primussExam *model.PrimussExam, notConnectedExams []*model.PrimussExamInput) bool { - for _, notConnectedExam := range notConnectedExams { - if primussExam.AnCode == notConnectedExam.Ancode && primussExam.Program == notConnectedExam.Program { - return false - } - } - - return true -} - -func (p *Plexams) zpaExamToExam(ctx context.Context, zpaExam *model.ZPAExam) (*model.Exam, error) { - mainExamer, err := p.dbClient.GetTeacher(ctx, zpaExam.MainExamerID) - if err != nil { - log.Error().Err(err).Int("AnCode", zpaExam.AnCode).Int("MainExamerID", zpaExam.MainExamerID). - Str("MainExamerName", zpaExam.MainExamer).Msg("cannot find main examer") - return nil, err - } - - return &model.Exam{ - Semester: zpaExam.Semester, - AnCode: zpaExam.AnCode, - Module: zpaExam.Module, - MainExamer: mainExamer, - MainExamerName: zpaExam.MainExamer, - MainExamerID: zpaExam.MainExamerID, - ExamType: zpaExam.ExamType, - Duration: zpaExam.Duration, - IsRepeaterExam: zpaExam.IsRepeaterExam, - ZpaGroups: zpaExam.Groups, - RemovedPrimussExams: nil, - RegisteredExams: []*model.RegisteredExam{}, - }, nil -} +// func isConnected(primussExam *model.PrimussExam, notConnectedExams []*model.PrimussExamInput) bool { +// for _, notConnectedExam := range notConnectedExams { +// if primussExam.AnCode == notConnectedExam.Ancode && primussExam.Program == notConnectedExam.Program { +// return false +// } +// } + +// return true +// } + +// func (p *Plexams) zpaExamToExam(ctx context.Context, zpaExam *model.ZPAExam) (*model.Exam, error) { +// mainExamer, err := p.dbClient.GetTeacher(ctx, zpaExam.MainExamerID) +// if err != nil { +// log.Error().Err(err).Int("AnCode", zpaExam.AnCode).Int("MainExamerID", zpaExam.MainExamerID). +// Str("MainExamerName", zpaExam.MainExamer).Msg("cannot find main examer") +// return nil, err +// } + +// return &model.Exam{ +// Semester: zpaExam.Semester, +// AnCode: zpaExam.AnCode, +// Module: zpaExam.Module, +// MainExamer: mainExamer, +// MainExamerName: zpaExam.MainExamer, +// MainExamerID: zpaExam.MainExamerID, +// ExamType: zpaExam.ExamType, +// Duration: zpaExam.Duration, +// IsRepeaterExam: zpaExam.IsRepeaterExam, +// ZpaGroups: zpaExam.Groups, +// RemovedPrimussExams: nil, +// RegisteredExams: []*model.RegisteredExam{}, +// }, nil +// } func (p *Plexams) ExamWithRegs(ctx context.Context, ancode int) (*model.ExamWithRegs, error) { return p.dbClient.ExamWithRegs(ctx, ancode) diff --git a/plexams/prepare.go b/plexams/prepare.go index 3d15f44..2135670 100644 --- a/plexams/prepare.go +++ b/plexams/prepare.go @@ -149,8 +149,8 @@ func (p *Plexams) PrepareExamsWithRegs() error { } connectedExams := make(map[int]*model.ConnectedExam) - for _, connecconnectedExam := range connectedExamsSlice { - connectedExams[connecconnectedExam.ZpaExam.AnCode] = connecconnectedExam + for _, connectedExam := range connectedExamsSlice { + connectedExams[connectedExam.ZpaExam.AnCode] = connectedExam } studentRegsSlice, err := p.GetStudentRegsPerAncodePlanned(ctx) diff --git a/plexams/validate_invigilation.go b/plexams/validate_invigilation.go index 291c644..5382bf2 100644 --- a/plexams/validate_invigilation.go +++ b/plexams/validate_invigilation.go @@ -100,6 +100,7 @@ func (p *Plexams) ValidateInvigilatorRequirements() error { return nil } +// TODO: NTA- und Reserve-Aufsicht (wenn NTA) nicht im folgenden Slot einteilen! func (p *Plexams) ValidateInvigilatorSlots() error { color.Style{color.FgRed, color.BgGreen, color.OpBold}. Printf(" --- validating invigilator for all slots --- \n") From cc39f485e004848325b319238d087b57fea35954 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Tue, 1 Aug 2023 11:21:29 +0200 Subject: [PATCH 07/78] just todo and readme --- README.md | 60 +++++++++++++++++++++++++++++++++++++++++++++ cmd/zpa.go | 3 +++ plexams/zpa_post.go | 2 +- 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b0a14b5..8b2aa14 100644 --- a/README.md +++ b/README.md @@ -34,3 +34,63 @@ erDiagram studentregs_XY ## Ablauf + +1. Prüfungen aus dem ZPA importieren (bei Änderungen erneut): + + ``` + plexams.go zpa exams + ``` + +2. Dozierende aus dem ZPA importieren (bei Änderungen erneut): + + ``` + plexams.go zpa teacher + ``` + +3. Prüfungen in `plexams.gui` auswählen, die geplant werden müssen. +4. (optional) zusätzliche Prüfungen einfügen, die beachtet werden müssen. +5. Besonderheiten (`constraints`) bei Prüfungen einpflegen. +6. Primuss-Daten per `Makefile` importieren. +7. Zuordnung ZPA <-> Primuss: + + ``` + plexams.go prepare connected-exams + ``` + + Kontrollieren in `plexams.gui`. + +8. Evtl. Primuss-Anmeldungen korrigieren + + ``` + plexams.go primuss fix-ancode + ``` + + und erneut zuordnen lassen (siehe 7.) oder zusätzlich zuordnen (siehe 9.) + +9. Evtl. mit + + ``` + plexams.go prepare connect-exam + ``` + + ein zusätzliches connecten + +10. Primuss-Anmeldungen ins ZPA importieren + + ``` + plexams.go zpa studentregs + ``` + +11. Zuordnung ZPA-Prüfungen zu Primuss-Anmeldungen fixieren. +12. Nachteilsausgleiche bei Prüfer:innen per E-Mail melden/nachfragen + + ``` + plexams.go email nta -r + ``` + +bis hier + +13. MUC.DAI-Planung an Prüfungsplaner FK03 (DE), FK08 (GS), FK12 (ID) +14. Vorläufigen Plan ins ZPA und an Fachschaft +15. Plan im ZPA veröffentlichen +16. E-Mail Anforderungen an die Aufsichtenplanung diff --git a/cmd/zpa.go b/cmd/zpa.go index 22d97ba..68b5a50 100644 --- a/cmd/zpa.go +++ b/cmd/zpa.go @@ -24,6 +24,7 @@ var ( Run: func(cmd *cobra.Command, args []string) { plexams := initPlexamsConfig() switch args[0] { + // TODO: wenn schon in der DB vorhanden, Änderungen anzeigen case "teacher": t := true teachers, err := plexams.GetTeachers(context.Background(), &t) @@ -34,6 +35,7 @@ var ( fmt.Printf("%3d. %s\n", i+1, teacher.Fullname) } + // TODO: wenn schon in der DB vorhanden, Änderungen anzeigen case "exams": t := true exams, err := plexams.GetZPAExams(context.Background(), &t) @@ -44,6 +46,7 @@ var ( fmt.Printf("%3d. %s (%s)\n", exam.AnCode, exam.Module, exam.MainExamer) } + // TODO: wenn schon in der DB vorhanden, Änderungen anzeigen case "invigs": invigs, err := plexams.GetSupervisorRequirements(context.Background()) if err != nil { diff --git a/plexams/zpa_post.go b/plexams/zpa_post.go index 4b68b9e..887bf6f 100644 --- a/plexams/zpa_post.go +++ b/plexams/zpa_post.go @@ -72,7 +72,7 @@ func (p *Plexams) PostStudentRegsToZPA(ctx context.Context) (int, []*model.RegWi zpaStudentRegErrors := make([]*model.ZPAStudentRegError, 0) err = json.Unmarshal(body, &zpaStudentRegErrors) if err != nil { - log.Error().Err(err).Msg("error while unmarshalling errors from ZPA") + log.Error().Err(err).Interface("zpa-errors", zpaStudentRegErrors).Msg("error while unmarshalling errors from ZPA") return 0, nil, err } From 550e8940941d15f255e3a93de7c7a169fc92466a Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Tue, 1 Aug 2023 17:35:14 +0200 Subject: [PATCH 08/78] just change todo tags --- graph/exam.graphqls | 19 +- graph/exam.resolvers.go | 22 + graph/generated/generated.go | 2725 +++++++++++++++++++--------------- graph/query.graphqls | 13 +- graph/query.resolvers.go | 60 - graph/zpa.graphqls | 17 +- graph/zpa.resolvers.go | 71 + plexams/exam.go | 5 + 8 files changed, 1636 insertions(+), 1296 deletions(-) create mode 100644 graph/exam.resolvers.go create mode 100644 graph/zpa.resolvers.go diff --git a/graph/exam.graphqls b/graph/exam.graphqls index 107a8dd..967ba20 100644 --- a/graph/exam.graphqls +++ b/graph/exam.graphqls @@ -1,4 +1,9 @@ -# TODO: remove me +extend type Query { + exams: [Exam!]! + exam(ancode: Int!): Exam +} + +# Deprecated: remove me input AdditionalExamInput { ancode: Int! module: String! @@ -8,7 +13,7 @@ input AdditionalExamInput { groups: [String!]! } -# TODO: remove me +# Deprecated: remove me type AdditionalExam { ancode: Int! module: String! @@ -19,7 +24,7 @@ type AdditionalExam { groups: [String!]! } -# TODO: remove me +# Deprecated: remove me type ExamWithRegs { ancode: Int! zpaExam: ZPAExam! @@ -48,20 +53,20 @@ type RoomConstraints { seb: Boolean! } -# TODO: remove me +# Deprecated: remove me type ExamToPlan { exam: ExamWithRegs! constraints: Constraints } -# TODO: remove me +# Deprecated: remove me type PlannedExamWithNTA { exam: ExamWithRegs! constraints: Constraints nta: [NTAWithRegs!] } -# TODO: remove me +# Deprecated: remove me type ExamInPlan { exam: ExamWithRegs! constraints: Constraints @@ -69,7 +74,7 @@ type ExamInPlan { slot: Slot } -# TODO: remove me +# Deprecated: remove me type ExamWithRegsAndRooms { exam: ExamInPlan! normalRegs: [StudentReg!]! diff --git a/graph/exam.resolvers.go b/graph/exam.resolvers.go new file mode 100644 index 0000000..961461f --- /dev/null +++ b/graph/exam.resolvers.go @@ -0,0 +1,22 @@ +package graph + +// This file will be automatically regenerated based on the schema, any resolver implementations +// will be copied through when generating and any unknown code will be moved to the end. +// Code generated by github.com/99designs/gqlgen version v0.17.34 + +import ( + "context" + "fmt" + + "github.com/obcode/plexams.go/graph/model" +) + +// Exams is the resolver for the exams field. +func (r *queryResolver) Exams(ctx context.Context) ([]*model.Exam, error) { + panic(fmt.Errorf("not implemented: Exams - exams")) +} + +// Exam is the resolver for the exam field. +func (r *queryResolver) Exam(ctx context.Context, ancode int) (*model.Exam, error) { + panic(fmt.Errorf("not implemented: Exam - exam")) +} diff --git a/graph/generated/generated.go b/graph/generated/generated.go index daf9c84..61125d6 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -340,12 +340,14 @@ type ComplexityRoot struct { ConnectedExams func(childComplexity int) int ConstraintForAncode func(childComplexity int, ancode int) int DayOkForInvigilator func(childComplexity int, day int, invigilatorID int) int + Exam func(childComplexity int, ancode int) int ExamGroup func(childComplexity int, examGroupCode int) int ExamGroups func(childComplexity int) int ExamGroupsInSlot func(childComplexity int, day int, time int) int ExamGroupsWithoutSlot func(childComplexity int) int ExamWithRegs func(childComplexity int, ancode int) int ExamerInPlan func(childComplexity int) int + Exams func(childComplexity int) int ExamsInPlan func(childComplexity int) int ExamsInSlot func(childComplexity int, day int, time int) int ExamsInSlotWithRooms func(childComplexity int, day int, time int) int @@ -596,18 +598,6 @@ type QueryResolver interface { AllSemesterNames(ctx context.Context) ([]*model.Semester, error) Semester(ctx context.Context) (*model.Semester, error) SemesterConfig(ctx context.Context) (*model.SemesterConfig, error) - Teacher(ctx context.Context, id int) (*model.Teacher, error) - Teachers(ctx context.Context, fromZpa *bool) ([]*model.Teacher, error) - Invigilators(ctx context.Context) ([]*model.ZPAInvigilator, error) - Fk07programs(ctx context.Context) ([]*model.FK07Program, error) - ZpaExams(ctx context.Context, fromZpa *bool) ([]*model.ZPAExam, error) - ZpaExamsByType(ctx context.Context) ([]*model.ZPAExamsForType, error) - ZpaExamsToPlan(ctx context.Context) ([]*model.ZPAExam, error) - ZpaExamsNotToPlan(ctx context.Context) ([]*model.ZPAExam, error) - ZpaExamsPlaningStatusUnknown(ctx context.Context) ([]*model.ZPAExam, error) - ZpaExam(ctx context.Context, ancode int) (*model.ZPAExam, error) - ZpaAnCodes(ctx context.Context) ([]*model.AnCode, error) - StudentRegsImportErrors(ctx context.Context) ([]*model.RegWithError, error) AdditionalExams(ctx context.Context) ([]*model.AdditionalExam, error) PrimussExams(ctx context.Context) ([]*model.PrimussExamByProgram, error) PrimussExam(ctx context.Context, program string, ancode int) (*model.PrimussExam, error) @@ -647,6 +637,20 @@ type QueryResolver interface { RoomsWithInvigilationsForSlot(ctx context.Context, day int, time int) (*model.InvigilationSlot, error) InvigilatorsForDay(ctx context.Context, day int) (*model.InvigilatorsForDay, error) DayOkForInvigilator(ctx context.Context, day int, invigilatorID int) (*bool, error) + Exams(ctx context.Context) ([]*model.Exam, error) + Exam(ctx context.Context, ancode int) (*model.Exam, error) + Teacher(ctx context.Context, id int) (*model.Teacher, error) + Teachers(ctx context.Context, fromZpa *bool) ([]*model.Teacher, error) + Invigilators(ctx context.Context) ([]*model.ZPAInvigilator, error) + Fk07programs(ctx context.Context) ([]*model.FK07Program, error) + ZpaExams(ctx context.Context, fromZpa *bool) ([]*model.ZPAExam, error) + ZpaExamsByType(ctx context.Context) ([]*model.ZPAExamsForType, error) + ZpaExamsToPlan(ctx context.Context) ([]*model.ZPAExam, error) + ZpaExamsNotToPlan(ctx context.Context) ([]*model.ZPAExam, error) + ZpaExamsPlaningStatusUnknown(ctx context.Context) ([]*model.ZPAExam, error) + ZpaExam(ctx context.Context, ancode int) (*model.ZPAExam, error) + ZpaAnCodes(ctx context.Context) ([]*model.AnCode, error) + StudentRegsImportErrors(ctx context.Context) ([]*model.RegWithError, error) } type RoomForExamResolver interface { Room(ctx context.Context, obj *model.RoomForExam) (*model.Room, error) @@ -2080,6 +2084,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.DayOkForInvigilator(childComplexity, args["day"].(int), args["invigilatorID"].(int)), true + case "Query.exam": + if e.complexity.Query.Exam == nil { + break + } + + args, err := ec.field_Query_exam_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Exam(childComplexity, args["ancode"].(int)), true + case "Query.examGroup": if e.complexity.Query.ExamGroup == nil { break @@ -2137,6 +2153,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.ExamerInPlan(childComplexity), true + case "Query.exams": + if e.complexity.Query.Exams == nil { + break + } + + return e.complexity.Query.Exams(childComplexity), true + case "Query.examsInPlan": if e.complexity.Query.ExamsInPlan == nil { break @@ -3313,7 +3336,12 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er } var sources = []*ast.Source{ - {Name: "../exam.graphqls", Input: `# TODO: remove me + {Name: "../exam.graphqls", Input: `extend type Query { + exams: [Exam!]! + exam(ancode: Int!): Exam +} + +# Deprecated: remove me input AdditionalExamInput { ancode: Int! module: String! @@ -3323,7 +3351,7 @@ input AdditionalExamInput { groups: [String!]! } -# TODO: remove me +# Deprecated: remove me type AdditionalExam { ancode: Int! module: String! @@ -3334,7 +3362,7 @@ type AdditionalExam { groups: [String!]! } -# TODO: remove me +# Deprecated: remove me type ExamWithRegs { ancode: Int! zpaExam: ZPAExam! @@ -3363,20 +3391,20 @@ type RoomConstraints { seb: Boolean! } -# TODO: remove me +# Deprecated: remove me type ExamToPlan { exam: ExamWithRegs! constraints: Constraints } -# TODO: remove me +# Deprecated: remove me type PlannedExamWithNTA { exam: ExamWithRegs! constraints: Constraints nta: [NTAWithRegs!] } -# TODO: remove me +# Deprecated: remove me type ExamInPlan { exam: ExamWithRegs! constraints: Constraints @@ -3384,7 +3412,7 @@ type ExamInPlan { slot: Slot } -# TODO: remove me +# Deprecated: remove me type ExamWithRegsAndRooms { exam: ExamInPlan! normalRegs: [StudentReg!]! @@ -3685,18 +3713,7 @@ type ConnectedExam { semester: Semester! semesterConfig: SemesterConfig! # ZPA - teacher(id: Int!): Teacher - teachers(fromZPA: Boolean): [Teacher!]! - invigilators: [ZPAInvigilator!]! - fk07programs: [FK07Program!]! - zpaExams(fromZPA: Boolean): [ZPAExam!]! - zpaExamsByType: [ZPAExamsForType!]! - zpaExamsToPlan: [ZPAExam!]! - zpaExamsNotToPlan: [ZPAExam!]! - zpaExamsPlaningStatusUnknown: [ZPAExam!]! - zpaExam(ancode: Int!): ZPAExam - zpaAnCodes: [AnCode] - studentRegsImportErrors: [RegWithError!]! + # Additional Exams additionalExams: [AdditionalExam!]! # Primuss @@ -3839,7 +3856,22 @@ type Step { deadline: Time } `, BuiltIn: false}, - {Name: "../zpa.graphqls", Input: `type ZPAExam { + {Name: "../zpa.graphqls", Input: `extend type Query { + teacher(id: Int!): Teacher + teachers(fromZPA: Boolean): [Teacher!]! + invigilators: [ZPAInvigilator!]! + fk07programs: [FK07Program!]! + zpaExams(fromZPA: Boolean): [ZPAExam!]! + zpaExamsByType: [ZPAExamsForType!]! + zpaExamsToPlan: [ZPAExam!]! + zpaExamsNotToPlan: [ZPAExam!]! + zpaExamsPlaningStatusUnknown: [ZPAExam!]! + zpaExam(ancode: Int!): ZPAExam + zpaAnCodes: [AnCode] + studentRegsImportErrors: [RegWithError!]! +} + +type ZPAExam { zpaID: Int! semester: String! ancode: Int! @@ -3881,7 +3913,7 @@ type FK07Program { name: String! } -# TODO: remove me +# Deprecated: remove me type ZPAExamWithConstraints { zpaExam: ZPAExam! constraints: Constraints # == nil if no constraint @@ -4405,6 +4437,21 @@ func (ec *executionContext) field_Query_examWithRegs_args(ctx context.Context, r return args, nil } +func (ec *executionContext) field_Query_exam_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 int + if tmp, ok := rawArgs["ancode"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("ancode")) + arg0, err = ec.unmarshalNInt2int(ctx, tmp) + if err != nil { + return nil, err + } + } + args["ancode"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query_examsInSlotWithRooms_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -13559,8 +13606,8 @@ func (ec *executionContext) fieldContext_Query_semesterConfig(ctx context.Contex return fc, nil } -func (ec *executionContext) _Query_teacher(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_teacher(ctx, field) +func (ec *executionContext) _Query_additionalExams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_additionalExams(ctx, field) if err != nil { return graphql.Null } @@ -13573,21 +13620,24 @@ func (ec *executionContext) _Query_teacher(ctx context.Context, field graphql.Co }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Teacher(rctx, fc.Args["id"].(int)) + return ec.resolvers.Query().AdditionalExams(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*model.Teacher) + res := resTmp.([]*model.AdditionalExam) fc.Result = res - return ec.marshalOTeacher2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐTeacher(ctx, field.Selections, res) + return ec.marshalNAdditionalExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAdditionalExamᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_teacher(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_additionalExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -13595,46 +13645,29 @@ func (ec *executionContext) fieldContext_Query_teacher(ctx context.Context, fiel IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "shortname": - return ec.fieldContext_Teacher_shortname(ctx, field) - case "fullname": - return ec.fieldContext_Teacher_fullname(ctx, field) - case "isProf": - return ec.fieldContext_Teacher_isProf(ctx, field) - case "isLBA": - return ec.fieldContext_Teacher_isLBA(ctx, field) - case "isProfHC": - return ec.fieldContext_Teacher_isProfHC(ctx, field) - case "isStaff": - return ec.fieldContext_Teacher_isStaff(ctx, field) - case "lastSemester": - return ec.fieldContext_Teacher_lastSemester(ctx, field) - case "fk": - return ec.fieldContext_Teacher_fk(ctx, field) - case "id": - return ec.fieldContext_Teacher_id(ctx, field) - case "email": - return ec.fieldContext_Teacher_email(ctx, field) + case "ancode": + return ec.fieldContext_AdditionalExam_ancode(ctx, field) + case "module": + return ec.fieldContext_AdditionalExam_module(ctx, field) + case "mainExamer": + return ec.fieldContext_AdditionalExam_mainExamer(ctx, field) + case "mainExamerID": + return ec.fieldContext_AdditionalExam_mainExamerID(ctx, field) + case "duration": + return ec.fieldContext_AdditionalExam_duration(ctx, field) + case "isRepeaterExam": + return ec.fieldContext_AdditionalExam_isRepeaterExam(ctx, field) + case "groups": + return ec.fieldContext_AdditionalExam_groups(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type Teacher", field.Name) + return nil, fmt.Errorf("no field named %q was found under type AdditionalExam", field.Name) }, } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_teacher_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } return fc, nil } -func (ec *executionContext) _Query_teachers(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_teachers(ctx, field) +func (ec *executionContext) _Query_primussExams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_primussExams(ctx, field) if err != nil { return graphql.Null } @@ -13647,24 +13680,21 @@ func (ec *executionContext) _Query_teachers(ctx context.Context, field graphql.C }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Teachers(rctx, fc.Args["fromZPA"].(*bool)) + return ec.resolvers.Query().PrimussExams(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.([]*model.Teacher) + res := resTmp.([]*model.PrimussExamByProgram) fc.Result = res - return ec.marshalNTeacher2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐTeacherᚄ(ctx, field.Selections, res) + return ec.marshalOPrimussExamByProgram2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamByProgram(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_teachers(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_primussExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -13672,46 +13702,19 @@ func (ec *executionContext) fieldContext_Query_teachers(ctx context.Context, fie IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "shortname": - return ec.fieldContext_Teacher_shortname(ctx, field) - case "fullname": - return ec.fieldContext_Teacher_fullname(ctx, field) - case "isProf": - return ec.fieldContext_Teacher_isProf(ctx, field) - case "isLBA": - return ec.fieldContext_Teacher_isLBA(ctx, field) - case "isProfHC": - return ec.fieldContext_Teacher_isProfHC(ctx, field) - case "isStaff": - return ec.fieldContext_Teacher_isStaff(ctx, field) - case "lastSemester": - return ec.fieldContext_Teacher_lastSemester(ctx, field) - case "fk": - return ec.fieldContext_Teacher_fk(ctx, field) - case "id": - return ec.fieldContext_Teacher_id(ctx, field) - case "email": - return ec.fieldContext_Teacher_email(ctx, field) + case "program": + return ec.fieldContext_PrimussExamByProgram_program(ctx, field) + case "exams": + return ec.fieldContext_PrimussExamByProgram_exams(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type Teacher", field.Name) + return nil, fmt.Errorf("no field named %q was found under type PrimussExamByProgram", field.Name) }, } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_teachers_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } return fc, nil } -func (ec *executionContext) _Query_invigilators(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_invigilators(ctx, field) +func (ec *executionContext) _Query_primussExam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_primussExam(ctx, field) if err != nil { return graphql.Null } @@ -13724,7 +13727,7 @@ func (ec *executionContext) _Query_invigilators(ctx context.Context, field graph }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Invigilators(rctx) + return ec.resolvers.Query().PrimussExam(rctx, fc.Args["program"].(string), fc.Args["ancode"].(int)) }) if err != nil { ec.Error(ctx, err) @@ -13736,12 +13739,12 @@ func (ec *executionContext) _Query_invigilators(ctx context.Context, field graph } return graphql.Null } - res := resTmp.([]*model.ZPAInvigilator) + res := resTmp.(*model.PrimussExam) fc.Result = res - return ec.marshalNZPAInvigilator2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAInvigilatorᚄ(ctx, field.Selections, res) + return ec.marshalNPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_invigilators(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_primussExam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -13749,19 +13752,42 @@ func (ec *executionContext) fieldContext_Query_invigilators(ctx context.Context, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "teacher": - return ec.fieldContext_ZPAInvigilator_teacher(ctx, field) - case "hasSubmittedRequirements": - return ec.fieldContext_ZPAInvigilator_hasSubmittedRequirements(ctx, field) + case "ancode": + return ec.fieldContext_PrimussExam_ancode(ctx, field) + case "module": + return ec.fieldContext_PrimussExam_module(ctx, field) + case "mainExamer": + return ec.fieldContext_PrimussExam_mainExamer(ctx, field) + case "program": + return ec.fieldContext_PrimussExam_program(ctx, field) + case "examType": + return ec.fieldContext_PrimussExam_examType(ctx, field) + case "presence": + return ec.fieldContext_PrimussExam_presence(ctx, field) + case "studentRegs": + return ec.fieldContext_PrimussExam_studentRegs(ctx, field) + case "conflicts": + return ec.fieldContext_PrimussExam_conflicts(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ZPAInvigilator", field.Name) + return nil, fmt.Errorf("no field named %q was found under type PrimussExam", field.Name) }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_primussExam_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } -func (ec *executionContext) _Query_fk07programs(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_fk07programs(ctx, field) +func (ec *executionContext) _Query_primussExamsForAnCode(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_primussExamsForAnCode(ctx, field) if err != nil { return graphql.Null } @@ -13774,24 +13800,21 @@ func (ec *executionContext) _Query_fk07programs(ctx context.Context, field graph }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Fk07programs(rctx) + return ec.resolvers.Query().PrimussExamsForAnCode(rctx, fc.Args["ancode"].(int)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.([]*model.FK07Program) + res := resTmp.([]*model.PrimussExam) fc.Result = res - return ec.marshalNFK07Program2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐFK07Programᚄ(ctx, field.Selections, res) + return ec.marshalOPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_fk07programs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_primussExamsForAnCode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -13799,17 +13822,42 @@ func (ec *executionContext) fieldContext_Query_fk07programs(ctx context.Context, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "name": - return ec.fieldContext_FK07Program_name(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type FK07Program", field.Name) + case "ancode": + return ec.fieldContext_PrimussExam_ancode(ctx, field) + case "module": + return ec.fieldContext_PrimussExam_module(ctx, field) + case "mainExamer": + return ec.fieldContext_PrimussExam_mainExamer(ctx, field) + case "program": + return ec.fieldContext_PrimussExam_program(ctx, field) + case "examType": + return ec.fieldContext_PrimussExam_examType(ctx, field) + case "presence": + return ec.fieldContext_PrimussExam_presence(ctx, field) + case "studentRegs": + return ec.fieldContext_PrimussExam_studentRegs(ctx, field) + case "conflicts": + return ec.fieldContext_PrimussExam_conflicts(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type PrimussExam", field.Name) }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_primussExamsForAnCode_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } -func (ec *executionContext) _Query_zpaExams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_zpaExams(ctx, field) +func (ec *executionContext) _Query_studentRegsForProgram(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_studentRegsForProgram(ctx, field) if err != nil { return graphql.Null } @@ -13822,24 +13870,21 @@ func (ec *executionContext) _Query_zpaExams(ctx context.Context, field graphql.C }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ZpaExams(rctx, fc.Args["fromZPA"].(*bool)) + return ec.resolvers.Query().StudentRegsForProgram(rctx, fc.Args["program"].(string)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.([]*model.ZPAExam) + res := resTmp.([]*model.StudentReg) fc.Result = res - return ec.marshalNZPAExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamᚄ(ctx, field.Selections, res) + return ec.marshalOStudentReg2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentRegᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_zpaExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_studentRegsForProgram(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -13847,30 +13892,20 @@ func (ec *executionContext) fieldContext_Query_zpaExams(ctx context.Context, fie IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "zpaID": - return ec.fieldContext_ZPAExam_zpaID(ctx, field) - case "semester": - return ec.fieldContext_ZPAExam_semester(ctx, field) + case "mtknr": + return ec.fieldContext_StudentReg_mtknr(ctx, field) case "ancode": - return ec.fieldContext_ZPAExam_ancode(ctx, field) - case "module": - return ec.fieldContext_ZPAExam_module(ctx, field) - case "mainExamer": - return ec.fieldContext_ZPAExam_mainExamer(ctx, field) - case "mainExamerID": - return ec.fieldContext_ZPAExam_mainExamerID(ctx, field) - case "examType": - return ec.fieldContext_ZPAExam_examType(ctx, field) - case "examTypeFull": - return ec.fieldContext_ZPAExam_examTypeFull(ctx, field) - case "duration": - return ec.fieldContext_ZPAExam_duration(ctx, field) - case "isRepeaterExam": - return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) - case "groups": - return ec.fieldContext_ZPAExam_groups(ctx, field) + return ec.fieldContext_StudentReg_ancode(ctx, field) + case "program": + return ec.fieldContext_StudentReg_program(ctx, field) + case "group": + return ec.fieldContext_StudentReg_group(ctx, field) + case "name": + return ec.fieldContext_StudentReg_name(ctx, field) + case "presence": + return ec.fieldContext_StudentReg_presence(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) + return nil, fmt.Errorf("no field named %q was found under type StudentReg", field.Name) }, } defer func() { @@ -13880,15 +13915,15 @@ func (ec *executionContext) fieldContext_Query_zpaExams(ctx context.Context, fie } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_zpaExams_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_Query_studentRegsForProgram_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } return fc, nil } -func (ec *executionContext) _Query_zpaExamsByType(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_zpaExamsByType(ctx, field) +func (ec *executionContext) _Query_connectedExam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_connectedExam(ctx, field) if err != nil { return graphql.Null } @@ -13901,24 +13936,21 @@ func (ec *executionContext) _Query_zpaExamsByType(ctx context.Context, field gra }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ZpaExamsByType(rctx) + return ec.resolvers.Query().ConnectedExam(rctx, fc.Args["ancode"].(int)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.([]*model.ZPAExamsForType) + res := resTmp.(*model.ConnectedExam) fc.Result = res - return ec.marshalNZPAExamsForType2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamsForTypeᚄ(ctx, field.Selections, res) + return ec.marshalOConnectedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExam(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_zpaExamsByType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_connectedExam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -13926,19 +13958,34 @@ func (ec *executionContext) fieldContext_Query_zpaExamsByType(ctx context.Contex IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "type": - return ec.fieldContext_ZPAExamsForType_type(ctx, field) - case "exams": - return ec.fieldContext_ZPAExamsForType_exams(ctx, field) + case "zpaExam": + return ec.fieldContext_ConnectedExam_zpaExam(ctx, field) + case "primussExams": + return ec.fieldContext_ConnectedExam_primussExams(ctx, field) + case "otherPrimussExams": + return ec.fieldContext_ConnectedExam_otherPrimussExams(ctx, field) + case "errors": + return ec.fieldContext_ConnectedExam_errors(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ZPAExamsForType", field.Name) + return nil, fmt.Errorf("no field named %q was found under type ConnectedExam", field.Name) }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_connectedExam_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } -func (ec *executionContext) _Query_zpaExamsToPlan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_zpaExamsToPlan(ctx, field) +func (ec *executionContext) _Query_connectedExams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_connectedExams(ctx, field) if err != nil { return graphql.Null } @@ -13951,7 +13998,7 @@ func (ec *executionContext) _Query_zpaExamsToPlan(ctx context.Context, field gra }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ZpaExamsToPlan(rctx) + return ec.resolvers.Query().ConnectedExams(rctx) }) if err != nil { ec.Error(ctx, err) @@ -13963,12 +14010,63 @@ func (ec *executionContext) _Query_zpaExamsToPlan(ctx context.Context, field gra } return graphql.Null } - res := resTmp.([]*model.ZPAExam) + res := resTmp.([]*model.ConnectedExam) fc.Result = res - return ec.marshalNZPAExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamᚄ(ctx, field.Selections, res) + return ec.marshalNConnectedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExamᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_zpaExamsToPlan(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_connectedExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "zpaExam": + return ec.fieldContext_ConnectedExam_zpaExam(ctx, field) + case "primussExams": + return ec.fieldContext_ConnectedExam_primussExams(ctx, field) + case "otherPrimussExams": + return ec.fieldContext_ConnectedExam_otherPrimussExams(ctx, field) + case "errors": + return ec.fieldContext_ConnectedExam_errors(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ConnectedExam", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Query_examWithRegs(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_examWithRegs(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().ExamWithRegs(rctx, fc.Args["ancode"].(int)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.ExamWithRegs) + fc.Result = res + return ec.marshalOExamWithRegs2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegs(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_examWithRegs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -13976,37 +14074,38 @@ func (ec *executionContext) fieldContext_Query_zpaExamsToPlan(ctx context.Contex IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "zpaID": - return ec.fieldContext_ZPAExam_zpaID(ctx, field) - case "semester": - return ec.fieldContext_ZPAExam_semester(ctx, field) case "ancode": - return ec.fieldContext_ZPAExam_ancode(ctx, field) - case "module": - return ec.fieldContext_ZPAExam_module(ctx, field) - case "mainExamer": - return ec.fieldContext_ZPAExam_mainExamer(ctx, field) - case "mainExamerID": - return ec.fieldContext_ZPAExam_mainExamerID(ctx, field) - case "examType": - return ec.fieldContext_ZPAExam_examType(ctx, field) - case "examTypeFull": - return ec.fieldContext_ZPAExam_examTypeFull(ctx, field) - case "duration": - return ec.fieldContext_ZPAExam_duration(ctx, field) - case "isRepeaterExam": - return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) - case "groups": - return ec.fieldContext_ZPAExam_groups(ctx, field) + return ec.fieldContext_ExamWithRegs_ancode(ctx, field) + case "zpaExam": + return ec.fieldContext_ExamWithRegs_zpaExam(ctx, field) + case "primussExams": + return ec.fieldContext_ExamWithRegs_primussExams(ctx, field) + case "studentRegs": + return ec.fieldContext_ExamWithRegs_studentRegs(ctx, field) + case "conflicts": + return ec.fieldContext_ExamWithRegs_conflicts(ctx, field) + case "connectErrors": + return ec.fieldContext_ExamWithRegs_connectErrors(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) + return nil, fmt.Errorf("no field named %q was found under type ExamWithRegs", field.Name) }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_examWithRegs_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } -func (ec *executionContext) _Query_zpaExamsNotToPlan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_zpaExamsNotToPlan(ctx, field) +func (ec *executionContext) _Query_examsWithRegs(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_examsWithRegs(ctx, field) if err != nil { return graphql.Null } @@ -14019,24 +14118,76 @@ func (ec *executionContext) _Query_zpaExamsNotToPlan(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ZpaExamsNotToPlan(rctx) + return ec.resolvers.Query().ExamsWithRegs(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") + return graphql.Null + } + res := resTmp.([]*model.ExamWithRegs) + fc.Result = res + return ec.marshalOExamWithRegs2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegsᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_examsWithRegs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "ancode": + return ec.fieldContext_ExamWithRegs_ancode(ctx, field) + case "zpaExam": + return ec.fieldContext_ExamWithRegs_zpaExam(ctx, field) + case "primussExams": + return ec.fieldContext_ExamWithRegs_primussExams(ctx, field) + case "studentRegs": + return ec.fieldContext_ExamWithRegs_studentRegs(ctx, field) + case "conflicts": + return ec.fieldContext_ExamWithRegs_conflicts(ctx, field) + case "connectErrors": + return ec.fieldContext_ExamWithRegs_connectErrors(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ExamWithRegs", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Query_constraintForAncode(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_constraintForAncode(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().ConstraintForAncode(rctx, fc.Args["ancode"].(int)) + }) + if err != nil { + ec.Error(ctx, err) return graphql.Null } - res := resTmp.([]*model.ZPAExam) + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.Constraints) fc.Result = res - return ec.marshalNZPAExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamᚄ(ctx, field.Selections, res) + return ec.marshalOConstraints2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConstraints(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_zpaExamsNotToPlan(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_constraintForAncode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -14044,37 +14195,44 @@ func (ec *executionContext) fieldContext_Query_zpaExamsNotToPlan(ctx context.Con IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "zpaID": - return ec.fieldContext_ZPAExam_zpaID(ctx, field) - case "semester": - return ec.fieldContext_ZPAExam_semester(ctx, field) case "ancode": - return ec.fieldContext_ZPAExam_ancode(ctx, field) - case "module": - return ec.fieldContext_ZPAExam_module(ctx, field) - case "mainExamer": - return ec.fieldContext_ZPAExam_mainExamer(ctx, field) - case "mainExamerID": - return ec.fieldContext_ZPAExam_mainExamerID(ctx, field) - case "examType": - return ec.fieldContext_ZPAExam_examType(ctx, field) - case "examTypeFull": - return ec.fieldContext_ZPAExam_examTypeFull(ctx, field) - case "duration": - return ec.fieldContext_ZPAExam_duration(ctx, field) - case "isRepeaterExam": - return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) - case "groups": - return ec.fieldContext_ZPAExam_groups(ctx, field) + return ec.fieldContext_Constraints_ancode(ctx, field) + case "notPlannedByMe": + return ec.fieldContext_Constraints_notPlannedByMe(ctx, field) + case "excludeDays": + return ec.fieldContext_Constraints_excludeDays(ctx, field) + case "possibleDays": + return ec.fieldContext_Constraints_possibleDays(ctx, field) + case "fixedDay": + return ec.fieldContext_Constraints_fixedDay(ctx, field) + case "fixedTime": + return ec.fieldContext_Constraints_fixedTime(ctx, field) + case "sameSlot": + return ec.fieldContext_Constraints_sameSlot(ctx, field) + case "online": + return ec.fieldContext_Constraints_online(ctx, field) + case "roomConstraints": + return ec.fieldContext_Constraints_roomConstraints(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) + return nil, fmt.Errorf("no field named %q was found under type Constraints", field.Name) }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_constraintForAncode_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } -func (ec *executionContext) _Query_zpaExamsPlaningStatusUnknown(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_zpaExamsPlaningStatusUnknown(ctx, field) +func (ec *executionContext) _Query_zpaExamsToPlanWithConstraints(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_zpaExamsToPlanWithConstraints(ctx, field) if err != nil { return graphql.Null } @@ -14087,7 +14245,7 @@ func (ec *executionContext) _Query_zpaExamsPlaningStatusUnknown(ctx context.Cont }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ZpaExamsPlaningStatusUnknown(rctx) + return ec.resolvers.Query().ZpaExamsToPlanWithConstraints(rctx) }) if err != nil { ec.Error(ctx, err) @@ -14099,12 +14257,12 @@ func (ec *executionContext) _Query_zpaExamsPlaningStatusUnknown(ctx context.Cont } return graphql.Null } - res := resTmp.([]*model.ZPAExam) + res := resTmp.([]*model.ZPAExamWithConstraints) fc.Result = res - return ec.marshalNZPAExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamᚄ(ctx, field.Selections, res) + return ec.marshalNZPAExamWithConstraints2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamWithConstraintsᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_zpaExamsPlaningStatusUnknown(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_zpaExamsToPlanWithConstraints(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -14112,37 +14270,19 @@ func (ec *executionContext) fieldContext_Query_zpaExamsPlaningStatusUnknown(ctx IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "zpaID": - return ec.fieldContext_ZPAExam_zpaID(ctx, field) - case "semester": - return ec.fieldContext_ZPAExam_semester(ctx, field) - case "ancode": - return ec.fieldContext_ZPAExam_ancode(ctx, field) - case "module": - return ec.fieldContext_ZPAExam_module(ctx, field) - case "mainExamer": - return ec.fieldContext_ZPAExam_mainExamer(ctx, field) - case "mainExamerID": - return ec.fieldContext_ZPAExam_mainExamerID(ctx, field) - case "examType": - return ec.fieldContext_ZPAExam_examType(ctx, field) - case "examTypeFull": - return ec.fieldContext_ZPAExam_examTypeFull(ctx, field) - case "duration": - return ec.fieldContext_ZPAExam_duration(ctx, field) - case "isRepeaterExam": - return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) - case "groups": - return ec.fieldContext_ZPAExam_groups(ctx, field) + case "zpaExam": + return ec.fieldContext_ZPAExamWithConstraints_zpaExam(ctx, field) + case "constraints": + return ec.fieldContext_ZPAExamWithConstraints_constraints(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) + return nil, fmt.Errorf("no field named %q was found under type ZPAExamWithConstraints", field.Name) }, } return fc, nil } -func (ec *executionContext) _Query_zpaExam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_zpaExam(ctx, field) +func (ec *executionContext) _Query_examGroups(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_examGroups(ctx, field) if err != nil { return graphql.Null } @@ -14155,21 +14295,24 @@ func (ec *executionContext) _Query_zpaExam(ctx context.Context, field graphql.Co }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ZpaExam(rctx, fc.Args["ancode"].(int)) + return ec.resolvers.Query().ExamGroups(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*model.ZPAExam) + res := resTmp.([]*model.ExamGroup) fc.Result = res - return ec.marshalOZPAExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExam(ctx, field.Selections, res) + return ec.marshalNExamGroup2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_zpaExam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_examGroups(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -14177,48 +14320,21 @@ func (ec *executionContext) fieldContext_Query_zpaExam(ctx context.Context, fiel IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "zpaID": - return ec.fieldContext_ZPAExam_zpaID(ctx, field) - case "semester": - return ec.fieldContext_ZPAExam_semester(ctx, field) - case "ancode": - return ec.fieldContext_ZPAExam_ancode(ctx, field) - case "module": - return ec.fieldContext_ZPAExam_module(ctx, field) - case "mainExamer": - return ec.fieldContext_ZPAExam_mainExamer(ctx, field) - case "mainExamerID": - return ec.fieldContext_ZPAExam_mainExamerID(ctx, field) - case "examType": - return ec.fieldContext_ZPAExam_examType(ctx, field) - case "examTypeFull": - return ec.fieldContext_ZPAExam_examTypeFull(ctx, field) - case "duration": - return ec.fieldContext_ZPAExam_duration(ctx, field) - case "isRepeaterExam": - return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) - case "groups": - return ec.fieldContext_ZPAExam_groups(ctx, field) + case "examGroupCode": + return ec.fieldContext_ExamGroup_examGroupCode(ctx, field) + case "exams": + return ec.fieldContext_ExamGroup_exams(ctx, field) + case "examGroupInfo": + return ec.fieldContext_ExamGroup_examGroupInfo(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) + return nil, fmt.Errorf("no field named %q was found under type ExamGroup", field.Name) }, } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_zpaExam_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } return fc, nil } -func (ec *executionContext) _Query_zpaAnCodes(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_zpaAnCodes(ctx, field) +func (ec *executionContext) _Query_examGroup(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_examGroup(ctx, field) if err != nil { return graphql.Null } @@ -14231,7 +14347,7 @@ func (ec *executionContext) _Query_zpaAnCodes(ctx context.Context, field graphql }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ZpaAnCodes(rctx) + return ec.resolvers.Query().ExamGroup(rctx, fc.Args["examGroupCode"].(int)) }) if err != nil { ec.Error(ctx, err) @@ -14240,12 +14356,12 @@ func (ec *executionContext) _Query_zpaAnCodes(ctx context.Context, field graphql if resTmp == nil { return graphql.Null } - res := resTmp.([]*model.AnCode) + res := resTmp.(*model.ExamGroup) fc.Result = res - return ec.marshalOAnCode2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAnCode(ctx, field.Selections, res) + return ec.marshalOExamGroup2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroup(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_zpaAnCodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_examGroup(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -14253,17 +14369,32 @@ func (ec *executionContext) fieldContext_Query_zpaAnCodes(ctx context.Context, f IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "ancode": - return ec.fieldContext_AnCode_ancode(ctx, field) + case "examGroupCode": + return ec.fieldContext_ExamGroup_examGroupCode(ctx, field) + case "exams": + return ec.fieldContext_ExamGroup_exams(ctx, field) + case "examGroupInfo": + return ec.fieldContext_ExamGroup_examGroupInfo(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type AnCode", field.Name) + return nil, fmt.Errorf("no field named %q was found under type ExamGroup", field.Name) }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_examGroup_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } -func (ec *executionContext) _Query_studentRegsImportErrors(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_studentRegsImportErrors(ctx, field) +func (ec *executionContext) _Query_conflictingGroupCodes(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_conflictingGroupCodes(ctx, field) if err != nil { return graphql.Null } @@ -14276,24 +14407,21 @@ func (ec *executionContext) _Query_studentRegsImportErrors(ctx context.Context, }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().StudentRegsImportErrors(rctx) + return ec.resolvers.Query().ConflictingGroupCodes(rctx, fc.Args["examGroupCode"].(int)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.([]*model.RegWithError) + res := resTmp.([]*model.ExamGroupConflict) fc.Result = res - return ec.marshalNRegWithError2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRegWithErrorᚄ(ctx, field.Selections, res) + return ec.marshalOExamGroupConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupConflictᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_studentRegsImportErrors(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_conflictingGroupCodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -14301,19 +14429,30 @@ func (ec *executionContext) fieldContext_Query_studentRegsImportErrors(ctx conte IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "registration": - return ec.fieldContext_RegWithError_registration(ctx, field) - case "error": - return ec.fieldContext_RegWithError_error(ctx, field) + case "examGroupCode": + return ec.fieldContext_ExamGroupConflict_examGroupCode(ctx, field) + case "count": + return ec.fieldContext_ExamGroupConflict_count(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type RegWithError", field.Name) + return nil, fmt.Errorf("no field named %q was found under type ExamGroupConflict", field.Name) }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_conflictingGroupCodes_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } -func (ec *executionContext) _Query_additionalExams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_additionalExams(ctx, field) +func (ec *executionContext) _Query_ntas(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_ntas(ctx, field) if err != nil { return graphql.Null } @@ -14326,24 +14465,21 @@ func (ec *executionContext) _Query_additionalExams(ctx context.Context, field gr }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().AdditionalExams(rctx) + return ec.resolvers.Query().Ntas(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.([]*model.AdditionalExam) + res := resTmp.([]*model.NTA) fc.Result = res - return ec.marshalNAdditionalExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAdditionalExamᚄ(ctx, field.Selections, res) + return ec.marshalONTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_additionalExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_ntas(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -14351,29 +14487,35 @@ func (ec *executionContext) fieldContext_Query_additionalExams(ctx context.Conte IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "ancode": - return ec.fieldContext_AdditionalExam_ancode(ctx, field) - case "module": - return ec.fieldContext_AdditionalExam_module(ctx, field) - case "mainExamer": - return ec.fieldContext_AdditionalExam_mainExamer(ctx, field) - case "mainExamerID": - return ec.fieldContext_AdditionalExam_mainExamerID(ctx, field) - case "duration": - return ec.fieldContext_AdditionalExam_duration(ctx, field) - case "isRepeaterExam": - return ec.fieldContext_AdditionalExam_isRepeaterExam(ctx, field) - case "groups": - return ec.fieldContext_AdditionalExam_groups(ctx, field) + case "name": + return ec.fieldContext_NTA_name(ctx, field) + case "mtknr": + return ec.fieldContext_NTA_mtknr(ctx, field) + case "compensation": + return ec.fieldContext_NTA_compensation(ctx, field) + case "deltaDurationPercent": + return ec.fieldContext_NTA_deltaDurationPercent(ctx, field) + case "needsRoomAlone": + return ec.fieldContext_NTA_needsRoomAlone(ctx, field) + case "program": + return ec.fieldContext_NTA_program(ctx, field) + case "from": + return ec.fieldContext_NTA_from(ctx, field) + case "until": + return ec.fieldContext_NTA_until(ctx, field) + case "lastSemester": + return ec.fieldContext_NTA_lastSemester(ctx, field) + case "exams": + return ec.fieldContext_NTA_exams(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type AdditionalExam", field.Name) + return nil, fmt.Errorf("no field named %q was found under type NTA", field.Name) }, } return fc, nil } -func (ec *executionContext) _Query_primussExams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_primussExams(ctx, field) +func (ec *executionContext) _Query_ntasWithRegs(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_ntasWithRegs(ctx, field) if err != nil { return graphql.Null } @@ -14386,7 +14528,7 @@ func (ec *executionContext) _Query_primussExams(ctx context.Context, field graph }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().PrimussExams(rctx) + return ec.resolvers.Query().NtasWithRegs(rctx) }) if err != nil { ec.Error(ctx, err) @@ -14395,12 +14537,12 @@ func (ec *executionContext) _Query_primussExams(ctx context.Context, field graph if resTmp == nil { return graphql.Null } - res := resTmp.([]*model.PrimussExamByProgram) + res := resTmp.([]*model.NTAWithRegs) fc.Result = res - return ec.marshalOPrimussExamByProgram2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamByProgram(ctx, field.Selections, res) + return ec.marshalONTAWithRegs2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_primussExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_ntasWithRegs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -14408,19 +14550,19 @@ func (ec *executionContext) fieldContext_Query_primussExams(ctx context.Context, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "program": - return ec.fieldContext_PrimussExamByProgram_program(ctx, field) - case "exams": - return ec.fieldContext_PrimussExamByProgram_exams(ctx, field) + case "nta": + return ec.fieldContext_NTAWithRegs_nta(ctx, field) + case "regs": + return ec.fieldContext_NTAWithRegs_regs(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type PrimussExamByProgram", field.Name) + return nil, fmt.Errorf("no field named %q was found under type NTAWithRegs", field.Name) }, } return fc, nil } -func (ec *executionContext) _Query_primussExam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_primussExam(ctx, field) +func (ec *executionContext) _Query_ntasWithRegsByTeacher(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_ntasWithRegsByTeacher(ctx, field) if err != nil { return graphql.Null } @@ -14433,24 +14575,21 @@ func (ec *executionContext) _Query_primussExam(ctx context.Context, field graphq }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().PrimussExam(rctx, fc.Args["program"].(string), fc.Args["ancode"].(int)) + return ec.resolvers.Query().NtasWithRegsByTeacher(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(*model.PrimussExam) + res := resTmp.([]*model.NTAWithRegsByExamAndTeacher) fc.Result = res - return ec.marshalNPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx, field.Selections, res) + return ec.marshalONTAWithRegsByExamAndTeacher2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsByExamAndTeacherᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_primussExam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_ntasWithRegsByTeacher(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -14458,42 +14597,19 @@ func (ec *executionContext) fieldContext_Query_primussExam(ctx context.Context, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "ancode": - return ec.fieldContext_PrimussExam_ancode(ctx, field) - case "module": - return ec.fieldContext_PrimussExam_module(ctx, field) - case "mainExamer": - return ec.fieldContext_PrimussExam_mainExamer(ctx, field) - case "program": - return ec.fieldContext_PrimussExam_program(ctx, field) - case "examType": - return ec.fieldContext_PrimussExam_examType(ctx, field) - case "presence": - return ec.fieldContext_PrimussExam_presence(ctx, field) - case "studentRegs": - return ec.fieldContext_PrimussExam_studentRegs(ctx, field) - case "conflicts": - return ec.fieldContext_PrimussExam_conflicts(ctx, field) + case "teacher": + return ec.fieldContext_NTAWithRegsByExamAndTeacher_teacher(ctx, field) + case "exams": + return ec.fieldContext_NTAWithRegsByExamAndTeacher_exams(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type PrimussExam", field.Name) + return nil, fmt.Errorf("no field named %q was found under type NTAWithRegsByExamAndTeacher", field.Name) }, } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_primussExam_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } return fc, nil } -func (ec *executionContext) _Query_primussExamsForAnCode(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_primussExamsForAnCode(ctx, field) +func (ec *executionContext) _Query_nta(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_nta(ctx, field) if err != nil { return graphql.Null } @@ -14506,7 +14622,7 @@ func (ec *executionContext) _Query_primussExamsForAnCode(ctx context.Context, fi }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().PrimussExamsForAnCode(rctx, fc.Args["ancode"].(int)) + return ec.resolvers.Query().Nta(rctx, fc.Args["mtknr"].(string)) }) if err != nil { ec.Error(ctx, err) @@ -14515,12 +14631,12 @@ func (ec *executionContext) _Query_primussExamsForAnCode(ctx context.Context, fi if resTmp == nil { return graphql.Null } - res := resTmp.([]*model.PrimussExam) + res := resTmp.(*model.NTAWithRegs) fc.Result = res - return ec.marshalOPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamᚄ(ctx, field.Selections, res) + return ec.marshalONTAWithRegs2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegs(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_primussExamsForAnCode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_nta(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -14528,24 +14644,12 @@ func (ec *executionContext) fieldContext_Query_primussExamsForAnCode(ctx context IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "ancode": - return ec.fieldContext_PrimussExam_ancode(ctx, field) - case "module": - return ec.fieldContext_PrimussExam_module(ctx, field) - case "mainExamer": - return ec.fieldContext_PrimussExam_mainExamer(ctx, field) - case "program": - return ec.fieldContext_PrimussExam_program(ctx, field) - case "examType": - return ec.fieldContext_PrimussExam_examType(ctx, field) - case "presence": - return ec.fieldContext_PrimussExam_presence(ctx, field) - case "studentRegs": - return ec.fieldContext_PrimussExam_studentRegs(ctx, field) - case "conflicts": - return ec.fieldContext_PrimussExam_conflicts(ctx, field) + case "nta": + return ec.fieldContext_NTAWithRegs_nta(ctx, field) + case "regs": + return ec.fieldContext_NTAWithRegs_regs(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type PrimussExam", field.Name) + return nil, fmt.Errorf("no field named %q was found under type NTAWithRegs", field.Name) }, } defer func() { @@ -14555,15 +14659,15 @@ func (ec *executionContext) fieldContext_Query_primussExamsForAnCode(ctx context } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_primussExamsForAnCode_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_Query_nta_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } return fc, nil } -func (ec *executionContext) _Query_studentRegsForProgram(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_studentRegsForProgram(ctx, field) +func (ec *executionContext) _Query_allowedSlots(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_allowedSlots(ctx, field) if err != nil { return graphql.Null } @@ -14576,7 +14680,7 @@ func (ec *executionContext) _Query_studentRegsForProgram(ctx context.Context, fi }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().StudentRegsForProgram(rctx, fc.Args["program"].(string)) + return ec.resolvers.Query().AllowedSlots(rctx, fc.Args["examGroupCode"].(int)) }) if err != nil { ec.Error(ctx, err) @@ -14585,12 +14689,12 @@ func (ec *executionContext) _Query_studentRegsForProgram(ctx context.Context, fi if resTmp == nil { return graphql.Null } - res := resTmp.([]*model.StudentReg) + res := resTmp.([]*model.Slot) fc.Result = res - return ec.marshalOStudentReg2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentRegᚄ(ctx, field.Selections, res) + return ec.marshalOSlot2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSlotᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_studentRegsForProgram(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_allowedSlots(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -14598,20 +14702,14 @@ func (ec *executionContext) fieldContext_Query_studentRegsForProgram(ctx context IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "mtknr": - return ec.fieldContext_StudentReg_mtknr(ctx, field) - case "ancode": - return ec.fieldContext_StudentReg_ancode(ctx, field) - case "program": - return ec.fieldContext_StudentReg_program(ctx, field) - case "group": - return ec.fieldContext_StudentReg_group(ctx, field) - case "name": - return ec.fieldContext_StudentReg_name(ctx, field) - case "presence": - return ec.fieldContext_StudentReg_presence(ctx, field) + case "dayNumber": + return ec.fieldContext_Slot_dayNumber(ctx, field) + case "slotNumber": + return ec.fieldContext_Slot_slotNumber(ctx, field) + case "starttime": + return ec.fieldContext_Slot_starttime(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type StudentReg", field.Name) + return nil, fmt.Errorf("no field named %q was found under type Slot", field.Name) }, } defer func() { @@ -14621,15 +14719,15 @@ func (ec *executionContext) fieldContext_Query_studentRegsForProgram(ctx context } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_studentRegsForProgram_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_Query_allowedSlots_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } return fc, nil } -func (ec *executionContext) _Query_connectedExam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_connectedExam(ctx, field) +func (ec *executionContext) _Query_awkwardSlots(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_awkwardSlots(ctx, field) if err != nil { return graphql.Null } @@ -14642,21 +14740,24 @@ func (ec *executionContext) _Query_connectedExam(ctx context.Context, field grap }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ConnectedExam(rctx, fc.Args["ancode"].(int)) + return ec.resolvers.Query().AwkwardSlots(rctx, fc.Args["examGroupCode"].(int)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*model.ConnectedExam) + res := resTmp.([]*model.Slot) fc.Result = res - return ec.marshalOConnectedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExam(ctx, field.Selections, res) + return ec.marshalNSlot2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSlotᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_connectedExam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_awkwardSlots(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -14664,16 +14765,14 @@ func (ec *executionContext) fieldContext_Query_connectedExam(ctx context.Context IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "zpaExam": - return ec.fieldContext_ConnectedExam_zpaExam(ctx, field) - case "primussExams": - return ec.fieldContext_ConnectedExam_primussExams(ctx, field) - case "otherPrimussExams": - return ec.fieldContext_ConnectedExam_otherPrimussExams(ctx, field) - case "errors": - return ec.fieldContext_ConnectedExam_errors(ctx, field) + case "dayNumber": + return ec.fieldContext_Slot_dayNumber(ctx, field) + case "slotNumber": + return ec.fieldContext_Slot_slotNumber(ctx, field) + case "starttime": + return ec.fieldContext_Slot_starttime(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ConnectedExam", field.Name) + return nil, fmt.Errorf("no field named %q was found under type Slot", field.Name) }, } defer func() { @@ -14683,15 +14782,15 @@ func (ec *executionContext) fieldContext_Query_connectedExam(ctx context.Context } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_connectedExam_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_Query_awkwardSlots_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } return fc, nil } -func (ec *executionContext) _Query_connectedExams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_connectedExams(ctx, field) +func (ec *executionContext) _Query_examGroupsInSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_examGroupsInSlot(ctx, field) if err != nil { return graphql.Null } @@ -14704,24 +14803,21 @@ func (ec *executionContext) _Query_connectedExams(ctx context.Context, field gra }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ConnectedExams(rctx) + return ec.resolvers.Query().ExamGroupsInSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.([]*model.ConnectedExam) + res := resTmp.([]*model.ExamGroup) fc.Result = res - return ec.marshalNConnectedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExamᚄ(ctx, field.Selections, res) + return ec.marshalOExamGroup2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_connectedExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_examGroupsInSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -14729,23 +14825,32 @@ func (ec *executionContext) fieldContext_Query_connectedExams(ctx context.Contex IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "zpaExam": - return ec.fieldContext_ConnectedExam_zpaExam(ctx, field) - case "primussExams": - return ec.fieldContext_ConnectedExam_primussExams(ctx, field) - case "otherPrimussExams": - return ec.fieldContext_ConnectedExam_otherPrimussExams(ctx, field) - case "errors": - return ec.fieldContext_ConnectedExam_errors(ctx, field) + case "examGroupCode": + return ec.fieldContext_ExamGroup_examGroupCode(ctx, field) + case "exams": + return ec.fieldContext_ExamGroup_exams(ctx, field) + case "examGroupInfo": + return ec.fieldContext_ExamGroup_examGroupInfo(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ConnectedExam", field.Name) + return nil, fmt.Errorf("no field named %q was found under type ExamGroup", field.Name) }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_examGroupsInSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } -func (ec *executionContext) _Query_examWithRegs(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_examWithRegs(ctx, field) +func (ec *executionContext) _Query_examGroupsWithoutSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_examGroupsWithoutSlot(ctx, field) if err != nil { return graphql.Null } @@ -14758,7 +14863,7 @@ func (ec *executionContext) _Query_examWithRegs(ctx context.Context, field graph }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ExamWithRegs(rctx, fc.Args["ancode"].(int)) + return ec.resolvers.Query().ExamGroupsWithoutSlot(rctx) }) if err != nil { ec.Error(ctx, err) @@ -14767,12 +14872,12 @@ func (ec *executionContext) _Query_examWithRegs(ctx context.Context, field graph if resTmp == nil { return graphql.Null } - res := resTmp.(*model.ExamWithRegs) + res := resTmp.([]*model.ExamGroup) fc.Result = res - return ec.marshalOExamWithRegs2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegs(ctx, field.Selections, res) + return ec.marshalOExamGroup2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_examWithRegs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_examGroupsWithoutSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -14780,38 +14885,21 @@ func (ec *executionContext) fieldContext_Query_examWithRegs(ctx context.Context, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "ancode": - return ec.fieldContext_ExamWithRegs_ancode(ctx, field) - case "zpaExam": - return ec.fieldContext_ExamWithRegs_zpaExam(ctx, field) - case "primussExams": - return ec.fieldContext_ExamWithRegs_primussExams(ctx, field) - case "studentRegs": - return ec.fieldContext_ExamWithRegs_studentRegs(ctx, field) - case "conflicts": - return ec.fieldContext_ExamWithRegs_conflicts(ctx, field) - case "connectErrors": - return ec.fieldContext_ExamWithRegs_connectErrors(ctx, field) + case "examGroupCode": + return ec.fieldContext_ExamGroup_examGroupCode(ctx, field) + case "exams": + return ec.fieldContext_ExamGroup_exams(ctx, field) + case "examGroupInfo": + return ec.fieldContext_ExamGroup_examGroupInfo(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ExamWithRegs", field.Name) + return nil, fmt.Errorf("no field named %q was found under type ExamGroup", field.Name) }, } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_examWithRegs_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } return fc, nil } -func (ec *executionContext) _Query_examsWithRegs(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_examsWithRegs(ctx, field) +func (ec *executionContext) _Query_allProgramsInPlan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_allProgramsInPlan(ctx, field) if err != nil { return graphql.Null } @@ -14824,7 +14912,7 @@ func (ec *executionContext) _Query_examsWithRegs(ctx context.Context, field grap }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ExamsWithRegs(rctx) + return ec.resolvers.Query().AllProgramsInPlan(rctx) }) if err != nil { ec.Error(ctx, err) @@ -14833,40 +14921,26 @@ func (ec *executionContext) _Query_examsWithRegs(ctx context.Context, field grap if resTmp == nil { return graphql.Null } - res := resTmp.([]*model.ExamWithRegs) + res := resTmp.([]string) fc.Result = res - return ec.marshalOExamWithRegs2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegsᚄ(ctx, field.Selections, res) + return ec.marshalOString2ᚕstringᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_examsWithRegs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_allProgramsInPlan(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "ancode": - return ec.fieldContext_ExamWithRegs_ancode(ctx, field) - case "zpaExam": - return ec.fieldContext_ExamWithRegs_zpaExam(ctx, field) - case "primussExams": - return ec.fieldContext_ExamWithRegs_primussExams(ctx, field) - case "studentRegs": - return ec.fieldContext_ExamWithRegs_studentRegs(ctx, field) - case "conflicts": - return ec.fieldContext_ExamWithRegs_conflicts(ctx, field) - case "connectErrors": - return ec.fieldContext_ExamWithRegs_connectErrors(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type ExamWithRegs", field.Name) + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil } -func (ec *executionContext) _Query_constraintForAncode(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_constraintForAncode(ctx, field) +func (ec *executionContext) _Query_ancodesInPlan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_ancodesInPlan(ctx, field) if err != nil { return graphql.Null } @@ -14879,7 +14953,7 @@ func (ec *executionContext) _Query_constraintForAncode(ctx context.Context, fiel }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ConstraintForAncode(rctx, fc.Args["ancode"].(int)) + return ec.resolvers.Query().AncodesInPlan(rctx) }) if err != nil { ec.Error(ctx, err) @@ -14888,57 +14962,26 @@ func (ec *executionContext) _Query_constraintForAncode(ctx context.Context, fiel if resTmp == nil { return graphql.Null } - res := resTmp.(*model.Constraints) + res := resTmp.([]int) fc.Result = res - return ec.marshalOConstraints2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConstraints(ctx, field.Selections, res) + return ec.marshalOInt2ᚕintᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_constraintForAncode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_ancodesInPlan(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, IsMethod: true, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "ancode": - return ec.fieldContext_Constraints_ancode(ctx, field) - case "notPlannedByMe": - return ec.fieldContext_Constraints_notPlannedByMe(ctx, field) - case "excludeDays": - return ec.fieldContext_Constraints_excludeDays(ctx, field) - case "possibleDays": - return ec.fieldContext_Constraints_possibleDays(ctx, field) - case "fixedDay": - return ec.fieldContext_Constraints_fixedDay(ctx, field) - case "fixedTime": - return ec.fieldContext_Constraints_fixedTime(ctx, field) - case "sameSlot": - return ec.fieldContext_Constraints_sameSlot(ctx, field) - case "online": - return ec.fieldContext_Constraints_online(ctx, field) - case "roomConstraints": - return ec.fieldContext_Constraints_roomConstraints(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type Constraints", field.Name) + return nil, errors.New("field of type Int does not have child fields") }, } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_constraintForAncode_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } return fc, nil } -func (ec *executionContext) _Query_zpaExamsToPlanWithConstraints(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_zpaExamsToPlanWithConstraints(ctx, field) +func (ec *executionContext) _Query_examerInPlan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_examerInPlan(ctx, field) if err != nil { return graphql.Null } @@ -14951,24 +14994,21 @@ func (ec *executionContext) _Query_zpaExamsToPlanWithConstraints(ctx context.Con }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ZpaExamsToPlanWithConstraints(rctx) + return ec.resolvers.Query().ExamerInPlan(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.([]*model.ZPAExamWithConstraints) + res := resTmp.([]*model.ExamerInPlan) fc.Result = res - return ec.marshalNZPAExamWithConstraints2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamWithConstraintsᚄ(ctx, field.Selections, res) + return ec.marshalOExamerInPlan2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamerInPlanᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_zpaExamsToPlanWithConstraints(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_examerInPlan(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -14976,19 +15016,19 @@ func (ec *executionContext) fieldContext_Query_zpaExamsToPlanWithConstraints(ctx IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "zpaExam": - return ec.fieldContext_ZPAExamWithConstraints_zpaExam(ctx, field) - case "constraints": - return ec.fieldContext_ZPAExamWithConstraints_constraints(ctx, field) + case "mainExamer": + return ec.fieldContext_ExamerInPlan_mainExamer(ctx, field) + case "mainExamerID": + return ec.fieldContext_ExamerInPlan_mainExamerID(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ZPAExamWithConstraints", field.Name) + return nil, fmt.Errorf("no field named %q was found under type ExamerInPlan", field.Name) }, } return fc, nil } -func (ec *executionContext) _Query_examGroups(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_examGroups(ctx, field) +func (ec *executionContext) _Query_plannedExamsInSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_plannedExamsInSlot(ctx, field) if err != nil { return graphql.Null } @@ -15001,24 +15041,21 @@ func (ec *executionContext) _Query_examGroups(ctx context.Context, field graphql }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ExamGroups(rctx) + return ec.resolvers.Query().PlannedExamsInSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.([]*model.ExamGroup) + res := resTmp.([]*model.PlannedExamWithNta) fc.Result = res - return ec.marshalNExamGroup2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupᚄ(ctx, field.Selections, res) + return ec.marshalOPlannedExamWithNTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExamWithNtaᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_examGroups(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_plannedExamsInSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -15026,21 +15063,32 @@ func (ec *executionContext) fieldContext_Query_examGroups(ctx context.Context, f IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "examGroupCode": - return ec.fieldContext_ExamGroup_examGroupCode(ctx, field) - case "exams": - return ec.fieldContext_ExamGroup_exams(ctx, field) - case "examGroupInfo": - return ec.fieldContext_ExamGroup_examGroupInfo(ctx, field) + case "exam": + return ec.fieldContext_PlannedExamWithNTA_exam(ctx, field) + case "constraints": + return ec.fieldContext_PlannedExamWithNTA_constraints(ctx, field) + case "nta": + return ec.fieldContext_PlannedExamWithNTA_nta(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ExamGroup", field.Name) + return nil, fmt.Errorf("no field named %q was found under type PlannedExamWithNTA", field.Name) }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_plannedExamsInSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } -func (ec *executionContext) _Query_examGroup(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_examGroup(ctx, field) +func (ec *executionContext) _Query_examsInPlan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_examsInPlan(ctx, field) if err != nil { return graphql.Null } @@ -15053,7 +15101,7 @@ func (ec *executionContext) _Query_examGroup(ctx context.Context, field graphql. }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ExamGroup(rctx, fc.Args["examGroupCode"].(int)) + return ec.resolvers.Query().ExamsInPlan(rctx) }) if err != nil { ec.Error(ctx, err) @@ -15062,12 +15110,12 @@ func (ec *executionContext) _Query_examGroup(ctx context.Context, field graphql. if resTmp == nil { return graphql.Null } - res := resTmp.(*model.ExamGroup) + res := resTmp.([]*model.ExamInPlan) fc.Result = res - return ec.marshalOExamGroup2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroup(ctx, field.Selections, res) + return ec.marshalOExamInPlan2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamInPlanᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_examGroup(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_examsInPlan(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -15075,32 +15123,23 @@ func (ec *executionContext) fieldContext_Query_examGroup(ctx context.Context, fi IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "examGroupCode": - return ec.fieldContext_ExamGroup_examGroupCode(ctx, field) - case "exams": - return ec.fieldContext_ExamGroup_exams(ctx, field) - case "examGroupInfo": - return ec.fieldContext_ExamGroup_examGroupInfo(ctx, field) + case "exam": + return ec.fieldContext_ExamInPlan_exam(ctx, field) + case "constraints": + return ec.fieldContext_ExamInPlan_constraints(ctx, field) + case "nta": + return ec.fieldContext_ExamInPlan_nta(ctx, field) + case "slot": + return ec.fieldContext_ExamInPlan_slot(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ExamGroup", field.Name) + return nil, fmt.Errorf("no field named %q was found under type ExamInPlan", field.Name) }, } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_examGroup_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } return fc, nil } -func (ec *executionContext) _Query_conflictingGroupCodes(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_conflictingGroupCodes(ctx, field) +func (ec *executionContext) _Query_examsInSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_examsInSlot(ctx, field) if err != nil { return graphql.Null } @@ -15113,7 +15152,7 @@ func (ec *executionContext) _Query_conflictingGroupCodes(ctx context.Context, fi }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ConflictingGroupCodes(rctx, fc.Args["examGroupCode"].(int)) + return ec.resolvers.Query().ExamsInSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) }) if err != nil { ec.Error(ctx, err) @@ -15122,12 +15161,12 @@ func (ec *executionContext) _Query_conflictingGroupCodes(ctx context.Context, fi if resTmp == nil { return graphql.Null } - res := resTmp.([]*model.ExamGroupConflict) + res := resTmp.([]*model.ExamInPlan) fc.Result = res - return ec.marshalOExamGroupConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupConflictᚄ(ctx, field.Selections, res) + return ec.marshalOExamInPlan2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamInPlanᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_conflictingGroupCodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_examsInSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -15135,12 +15174,16 @@ func (ec *executionContext) fieldContext_Query_conflictingGroupCodes(ctx context IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "examGroupCode": - return ec.fieldContext_ExamGroupConflict_examGroupCode(ctx, field) - case "count": - return ec.fieldContext_ExamGroupConflict_count(ctx, field) + case "exam": + return ec.fieldContext_ExamInPlan_exam(ctx, field) + case "constraints": + return ec.fieldContext_ExamInPlan_constraints(ctx, field) + case "nta": + return ec.fieldContext_ExamInPlan_nta(ctx, field) + case "slot": + return ec.fieldContext_ExamInPlan_slot(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ExamGroupConflict", field.Name) + return nil, fmt.Errorf("no field named %q was found under type ExamInPlan", field.Name) }, } defer func() { @@ -15150,15 +15193,15 @@ func (ec *executionContext) fieldContext_Query_conflictingGroupCodes(ctx context } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_conflictingGroupCodes_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_Query_examsInSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } return fc, nil } -func (ec *executionContext) _Query_ntas(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_ntas(ctx, field) +func (ec *executionContext) _Query_examsInSlotWithRooms(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_examsInSlotWithRooms(ctx, field) if err != nil { return graphql.Null } @@ -15171,7 +15214,7 @@ func (ec *executionContext) _Query_ntas(ctx context.Context, field graphql.Colle }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Ntas(rctx) + return ec.resolvers.Query().ExamsInSlotWithRooms(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) }) if err != nil { ec.Error(ctx, err) @@ -15180,12 +15223,12 @@ func (ec *executionContext) _Query_ntas(ctx context.Context, field graphql.Colle if resTmp == nil { return graphql.Null } - res := resTmp.([]*model.NTA) + res := resTmp.([]*model.ExamWithRegsAndRooms) fc.Result = res - return ec.marshalONTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAᚄ(ctx, field.Selections, res) + return ec.marshalOExamWithRegsAndRooms2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegsAndRoomsᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_ntas(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_examsInSlotWithRooms(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -15193,35 +15236,34 @@ func (ec *executionContext) fieldContext_Query_ntas(ctx context.Context, field g IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "name": - return ec.fieldContext_NTA_name(ctx, field) - case "mtknr": - return ec.fieldContext_NTA_mtknr(ctx, field) - case "compensation": - return ec.fieldContext_NTA_compensation(ctx, field) - case "deltaDurationPercent": - return ec.fieldContext_NTA_deltaDurationPercent(ctx, field) - case "needsRoomAlone": - return ec.fieldContext_NTA_needsRoomAlone(ctx, field) - case "program": - return ec.fieldContext_NTA_program(ctx, field) - case "from": - return ec.fieldContext_NTA_from(ctx, field) - case "until": - return ec.fieldContext_NTA_until(ctx, field) - case "lastSemester": - return ec.fieldContext_NTA_lastSemester(ctx, field) - case "exams": - return ec.fieldContext_NTA_exams(ctx, field) + case "exam": + return ec.fieldContext_ExamWithRegsAndRooms_exam(ctx, field) + case "normalRegs": + return ec.fieldContext_ExamWithRegsAndRooms_normalRegs(ctx, field) + case "ntaRegs": + return ec.fieldContext_ExamWithRegsAndRooms_ntaRegs(ctx, field) + case "rooms": + return ec.fieldContext_ExamWithRegsAndRooms_rooms(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type NTA", field.Name) + return nil, fmt.Errorf("no field named %q was found under type ExamWithRegsAndRooms", field.Name) }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_examsInSlotWithRooms_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } -func (ec *executionContext) _Query_ntasWithRegs(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_ntasWithRegs(ctx, field) +func (ec *executionContext) _Query_rooms(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_rooms(ctx, field) if err != nil { return graphql.Null } @@ -15234,41 +15276,56 @@ func (ec *executionContext) _Query_ntasWithRegs(ctx context.Context, field graph }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().NtasWithRegs(rctx) + return ec.resolvers.Query().Rooms(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.([]*model.NTAWithRegs) + res := resTmp.([]*model.Room) fc.Result = res - return ec.marshalONTAWithRegs2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsᚄ(ctx, field.Selections, res) + return ec.marshalNRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_ntasWithRegs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_rooms(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "nta": - return ec.fieldContext_NTAWithRegs_nta(ctx, field) - case "regs": - return ec.fieldContext_NTAWithRegs_regs(ctx, field) + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext_Room_name(ctx, field) + case "seats": + return ec.fieldContext_Room_seats(ctx, field) + case "handicap": + return ec.fieldContext_Room_handicap(ctx, field) + case "lab": + return ec.fieldContext_Room_lab(ctx, field) + case "placesWithSocket": + return ec.fieldContext_Room_placesWithSocket(ctx, field) + case "needsRequest": + return ec.fieldContext_Room_needsRequest(ctx, field) + case "exahm": + return ec.fieldContext_Room_exahm(ctx, field) + case "seb": + return ec.fieldContext_Room_seb(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type NTAWithRegs", field.Name) + return nil, fmt.Errorf("no field named %q was found under type Room", field.Name) }, } return fc, nil } -func (ec *executionContext) _Query_ntasWithRegsByTeacher(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_ntasWithRegsByTeacher(ctx, field) +func (ec *executionContext) _Query_roomsWithConstraints(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_roomsWithConstraints(ctx, field) if err != nil { return graphql.Null } @@ -15281,21 +15338,24 @@ func (ec *executionContext) _Query_ntasWithRegsByTeacher(ctx context.Context, fi }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().NtasWithRegsByTeacher(rctx) + return ec.resolvers.Query().RoomsWithConstraints(rctx, fc.Args["handicap"].(bool), fc.Args["lab"].(bool), fc.Args["placesWithSocket"].(bool), fc.Args["exahm"].(*bool)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.([]*model.NTAWithRegsByExamAndTeacher) + res := resTmp.([]*model.Room) fc.Result = res - return ec.marshalONTAWithRegsByExamAndTeacher2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsByExamAndTeacherᚄ(ctx, field.Selections, res) + return ec.marshalNRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_ntasWithRegsByTeacher(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_roomsWithConstraints(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -15303,19 +15363,42 @@ func (ec *executionContext) fieldContext_Query_ntasWithRegsByTeacher(ctx context IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "teacher": - return ec.fieldContext_NTAWithRegsByExamAndTeacher_teacher(ctx, field) - case "exams": - return ec.fieldContext_NTAWithRegsByExamAndTeacher_exams(ctx, field) + case "name": + return ec.fieldContext_Room_name(ctx, field) + case "seats": + return ec.fieldContext_Room_seats(ctx, field) + case "handicap": + return ec.fieldContext_Room_handicap(ctx, field) + case "lab": + return ec.fieldContext_Room_lab(ctx, field) + case "placesWithSocket": + return ec.fieldContext_Room_placesWithSocket(ctx, field) + case "needsRequest": + return ec.fieldContext_Room_needsRequest(ctx, field) + case "exahm": + return ec.fieldContext_Room_exahm(ctx, field) + case "seb": + return ec.fieldContext_Room_seb(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type NTAWithRegsByExamAndTeacher", field.Name) + return nil, fmt.Errorf("no field named %q was found under type Room", field.Name) }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_roomsWithConstraints_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } -func (ec *executionContext) _Query_nta(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_nta(ctx, field) +func (ec *executionContext) _Query_roomsForSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_roomsForSlot(ctx, field) if err != nil { return graphql.Null } @@ -15328,7 +15411,7 @@ func (ec *executionContext) _Query_nta(ctx context.Context, field graphql.Collec }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Nta(rctx, fc.Args["mtknr"].(string)) + return ec.resolvers.Query().RoomsForSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) }) if err != nil { ec.Error(ctx, err) @@ -15337,12 +15420,12 @@ func (ec *executionContext) _Query_nta(ctx context.Context, field graphql.Collec if resTmp == nil { return graphql.Null } - res := resTmp.(*model.NTAWithRegs) + res := resTmp.(*model.SlotWithRooms) fc.Result = res - return ec.marshalONTAWithRegs2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegs(ctx, field.Selections, res) + return ec.marshalOSlotWithRooms2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSlotWithRooms(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_nta(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_roomsForSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -15350,12 +15433,20 @@ func (ec *executionContext) fieldContext_Query_nta(ctx context.Context, field gr IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "nta": - return ec.fieldContext_NTAWithRegs_nta(ctx, field) - case "regs": - return ec.fieldContext_NTAWithRegs_regs(ctx, field) + case "dayNumber": + return ec.fieldContext_SlotWithRooms_dayNumber(ctx, field) + case "slotNumber": + return ec.fieldContext_SlotWithRooms_slotNumber(ctx, field) + case "normalRooms": + return ec.fieldContext_SlotWithRooms_normalRooms(ctx, field) + case "exahmRooms": + return ec.fieldContext_SlotWithRooms_exahmRooms(ctx, field) + case "labRooms": + return ec.fieldContext_SlotWithRooms_labRooms(ctx, field) + case "ntaRooms": + return ec.fieldContext_SlotWithRooms_ntaRooms(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type NTAWithRegs", field.Name) + return nil, fmt.Errorf("no field named %q was found under type SlotWithRooms", field.Name) }, } defer func() { @@ -15365,15 +15456,15 @@ func (ec *executionContext) fieldContext_Query_nta(ctx context.Context, field gr } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_nta_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_Query_roomsForSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } return fc, nil } -func (ec *executionContext) _Query_allowedSlots(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_allowedSlots(ctx, field) +func (ec *executionContext) _Query_plannedRoomNames(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_plannedRoomNames(ctx, field) if err != nil { return graphql.Null } @@ -15386,7 +15477,7 @@ func (ec *executionContext) _Query_allowedSlots(ctx context.Context, field graph }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().AllowedSlots(rctx, fc.Args["examGroupCode"].(int)) + return ec.resolvers.Query().PlannedRoomNames(rctx) }) if err != nil { ec.Error(ctx, err) @@ -15395,45 +15486,26 @@ func (ec *executionContext) _Query_allowedSlots(ctx context.Context, field graph if resTmp == nil { return graphql.Null } - res := resTmp.([]*model.Slot) + res := resTmp.([]string) fc.Result = res - return ec.marshalOSlot2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSlotᚄ(ctx, field.Selections, res) + return ec.marshalOString2ᚕstringᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_allowedSlots(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_plannedRoomNames(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, IsMethod: true, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "dayNumber": - return ec.fieldContext_Slot_dayNumber(ctx, field) - case "slotNumber": - return ec.fieldContext_Slot_slotNumber(ctx, field) - case "starttime": - return ec.fieldContext_Slot_starttime(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type Slot", field.Name) + return nil, errors.New("field of type String does not have child fields") }, } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_allowedSlots_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } return fc, nil } -func (ec *executionContext) _Query_awkwardSlots(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_awkwardSlots(ctx, field) +func (ec *executionContext) _Query_plannedRoomNamesInSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_plannedRoomNamesInSlot(ctx, field) if err != nil { return graphql.Null } @@ -15446,39 +15518,28 @@ func (ec *executionContext) _Query_awkwardSlots(ctx context.Context, field graph }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().AwkwardSlots(rctx, fc.Args["examGroupCode"].(int)) + return ec.resolvers.Query().PlannedRoomNamesInSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.([]*model.Slot) + res := resTmp.([]string) fc.Result = res - return ec.marshalNSlot2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSlotᚄ(ctx, field.Selections, res) + return ec.marshalOString2ᚕstringᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_awkwardSlots(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_plannedRoomNamesInSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, IsMethod: true, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "dayNumber": - return ec.fieldContext_Slot_dayNumber(ctx, field) - case "slotNumber": - return ec.fieldContext_Slot_slotNumber(ctx, field) - case "starttime": - return ec.fieldContext_Slot_starttime(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type Slot", field.Name) + return nil, errors.New("field of type String does not have child fields") }, } defer func() { @@ -15488,15 +15549,15 @@ func (ec *executionContext) fieldContext_Query_awkwardSlots(ctx context.Context, } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_awkwardSlots_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_Query_plannedRoomNamesInSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } return fc, nil } -func (ec *executionContext) _Query_examGroupsInSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_examGroupsInSlot(ctx, field) +func (ec *executionContext) _Query_invigilatorsWithReq(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_invigilatorsWithReq(ctx, field) if err != nil { return graphql.Null } @@ -15509,21 +15570,24 @@ func (ec *executionContext) _Query_examGroupsInSlot(ctx context.Context, field g }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ExamGroupsInSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) + return ec.resolvers.Query().InvigilatorsWithReq(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.([]*model.ExamGroup) + res := resTmp.([]*model.Invigilator) fc.Result = res - return ec.marshalOExamGroup2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupᚄ(ctx, field.Selections, res) + return ec.marshalNInvigilator2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilatorᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_examGroupsInSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_invigilatorsWithReq(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -15531,32 +15595,21 @@ func (ec *executionContext) fieldContext_Query_examGroupsInSlot(ctx context.Cont IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "examGroupCode": - return ec.fieldContext_ExamGroup_examGroupCode(ctx, field) - case "exams": - return ec.fieldContext_ExamGroup_exams(ctx, field) - case "examGroupInfo": - return ec.fieldContext_ExamGroup_examGroupInfo(ctx, field) + case "teacher": + return ec.fieldContext_Invigilator_teacher(ctx, field) + case "requirements": + return ec.fieldContext_Invigilator_requirements(ctx, field) + case "todos": + return ec.fieldContext_Invigilator_todos(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ExamGroup", field.Name) + return nil, fmt.Errorf("no field named %q was found under type Invigilator", field.Name) }, } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_examGroupsInSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } return fc, nil } -func (ec *executionContext) _Query_examGroupsWithoutSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_examGroupsWithoutSlot(ctx, field) +func (ec *executionContext) _Query_invigilatorTodos(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_invigilatorTodos(ctx, field) if err != nil { return graphql.Null } @@ -15569,7 +15622,7 @@ func (ec *executionContext) _Query_examGroupsWithoutSlot(ctx context.Context, fi }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ExamGroupsWithoutSlot(rctx) + return ec.resolvers.Query().InvigilatorTodos(rctx) }) if err != nil { ec.Error(ctx, err) @@ -15578,12 +15631,12 @@ func (ec *executionContext) _Query_examGroupsWithoutSlot(ctx context.Context, fi if resTmp == nil { return graphql.Null } - res := resTmp.([]*model.ExamGroup) + res := resTmp.(*model.InvigilationTodos) fc.Result = res - return ec.marshalOExamGroup2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupᚄ(ctx, field.Selections, res) + return ec.marshalOInvigilationTodos2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilationTodos(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_examGroupsWithoutSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_invigilatorTodos(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -15591,21 +15644,31 @@ func (ec *executionContext) fieldContext_Query_examGroupsWithoutSlot(ctx context IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "examGroupCode": - return ec.fieldContext_ExamGroup_examGroupCode(ctx, field) - case "exams": - return ec.fieldContext_ExamGroup_exams(ctx, field) - case "examGroupInfo": - return ec.fieldContext_ExamGroup_examGroupInfo(ctx, field) + case "sumExamRooms": + return ec.fieldContext_InvigilationTodos_sumExamRooms(ctx, field) + case "sumReserve": + return ec.fieldContext_InvigilationTodos_sumReserve(ctx, field) + case "sumOtherContributions": + return ec.fieldContext_InvigilationTodos_sumOtherContributions(ctx, field) + case "sumOtherContributionsOvertimeCutted": + return ec.fieldContext_InvigilationTodos_sumOtherContributionsOvertimeCutted(ctx, field) + case "invigilatorCount": + return ec.fieldContext_InvigilationTodos_invigilatorCount(ctx, field) + case "todoPerInvigilator": + return ec.fieldContext_InvigilationTodos_todoPerInvigilator(ctx, field) + case "todoPerInvigilatorOvertimeCutted": + return ec.fieldContext_InvigilationTodos_todoPerInvigilatorOvertimeCutted(ctx, field) + case "invigilators": + return ec.fieldContext_InvigilationTodos_invigilators(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ExamGroup", field.Name) + return nil, fmt.Errorf("no field named %q was found under type InvigilationTodos", field.Name) }, } return fc, nil } -func (ec *executionContext) _Query_allProgramsInPlan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_allProgramsInPlan(ctx, field) +func (ec *executionContext) _Query_roomsWithInvigilationsForSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_roomsWithInvigilationsForSlot(ctx, field) if err != nil { return graphql.Null } @@ -15618,7 +15681,7 @@ func (ec *executionContext) _Query_allProgramsInPlan(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().AllProgramsInPlan(rctx) + return ec.resolvers.Query().RoomsWithInvigilationsForSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) }) if err != nil { ec.Error(ctx, err) @@ -15627,26 +15690,43 @@ func (ec *executionContext) _Query_allProgramsInPlan(ctx context.Context, field if resTmp == nil { return graphql.Null } - res := resTmp.([]string) + res := resTmp.(*model.InvigilationSlot) fc.Result = res - return ec.marshalOString2ᚕstringᚄ(ctx, field.Selections, res) + return ec.marshalOInvigilationSlot2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilationSlot(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_allProgramsInPlan(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_roomsWithInvigilationsForSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, IsMethod: true, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + switch field.Name { + case "reserve": + return ec.fieldContext_InvigilationSlot_reserve(ctx, field) + case "roomsWithInvigilators": + return ec.fieldContext_InvigilationSlot_roomsWithInvigilators(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type InvigilationSlot", field.Name) }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_roomsWithInvigilationsForSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } -func (ec *executionContext) _Query_ancodesInPlan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_ancodesInPlan(ctx, field) +func (ec *executionContext) _Query_invigilatorsForDay(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_invigilatorsForDay(ctx, field) if err != nil { return graphql.Null } @@ -15659,7 +15739,7 @@ func (ec *executionContext) _Query_ancodesInPlan(ctx context.Context, field grap }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().AncodesInPlan(rctx) + return ec.resolvers.Query().InvigilatorsForDay(rctx, fc.Args["day"].(int)) }) if err != nil { ec.Error(ctx, err) @@ -15668,26 +15748,43 @@ func (ec *executionContext) _Query_ancodesInPlan(ctx context.Context, field grap if resTmp == nil { return graphql.Null } - res := resTmp.([]int) + res := resTmp.(*model.InvigilatorsForDay) fc.Result = res - return ec.marshalOInt2ᚕintᚄ(ctx, field.Selections, res) + return ec.marshalOInvigilatorsForDay2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilatorsForDay(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_ancodesInPlan(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_invigilatorsForDay(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, IsMethod: true, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") + switch field.Name { + case "want": + return ec.fieldContext_InvigilatorsForDay_want(ctx, field) + case "can": + return ec.fieldContext_InvigilatorsForDay_can(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type InvigilatorsForDay", field.Name) }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_invigilatorsForDay_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } -func (ec *executionContext) _Query_examerInPlan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_examerInPlan(ctx, field) +func (ec *executionContext) _Query_dayOkForInvigilator(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_dayOkForInvigilator(ctx, field) if err != nil { return graphql.Null } @@ -15700,7 +15797,7 @@ func (ec *executionContext) _Query_examerInPlan(ctx context.Context, field graph }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ExamerInPlan(rctx) + return ec.resolvers.Query().DayOkForInvigilator(rctx, fc.Args["day"].(int), fc.Args["invigilatorID"].(int)) }) if err != nil { ec.Error(ctx, err) @@ -15709,32 +15806,37 @@ func (ec *executionContext) _Query_examerInPlan(ctx context.Context, field graph if resTmp == nil { return graphql.Null } - res := resTmp.([]*model.ExamerInPlan) + res := resTmp.(*bool) fc.Result = res - return ec.marshalOExamerInPlan2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamerInPlanᚄ(ctx, field.Selections, res) + return ec.marshalOBoolean2ᚖbool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_examerInPlan(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_dayOkForInvigilator(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, IsMethod: true, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "mainExamer": - return ec.fieldContext_ExamerInPlan_mainExamer(ctx, field) - case "mainExamerID": - return ec.fieldContext_ExamerInPlan_mainExamerID(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type ExamerInPlan", field.Name) + return nil, errors.New("field of type Boolean does not have child fields") }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_dayOkForInvigilator_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } -func (ec *executionContext) _Query_plannedExamsInSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_plannedExamsInSlot(ctx, field) +func (ec *executionContext) _Query_exams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_exams(ctx, field) if err != nil { return graphql.Null } @@ -15747,21 +15849,24 @@ func (ec *executionContext) _Query_plannedExamsInSlot(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().PlannedExamsInSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) + return ec.resolvers.Query().Exams(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.([]*model.PlannedExamWithNta) + res := resTmp.([]*model.Exam) fc.Result = res - return ec.marshalOPlannedExamWithNTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExamWithNtaᚄ(ctx, field.Selections, res) + return ec.marshalNExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_plannedExamsInSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_exams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -15769,32 +15874,37 @@ func (ec *executionContext) fieldContext_Query_plannedExamsInSlot(ctx context.Co IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "exam": - return ec.fieldContext_PlannedExamWithNTA_exam(ctx, field) + case "ancode": + return ec.fieldContext_Exam_ancode(ctx, field) + case "zpaExam": + return ec.fieldContext_Exam_zpaExam(ctx, field) + case "externalExam": + return ec.fieldContext_Exam_externalExam(ctx, field) + case "primussExams": + return ec.fieldContext_Exam_primussExams(ctx, field) + case "studentRegs": + return ec.fieldContext_Exam_studentRegs(ctx, field) + case "conflicts": + return ec.fieldContext_Exam_conflicts(ctx, field) + case "connectErrors": + return ec.fieldContext_Exam_connectErrors(ctx, field) case "constraints": - return ec.fieldContext_PlannedExamWithNTA_constraints(ctx, field) + return ec.fieldContext_Exam_constraints(ctx, field) case "nta": - return ec.fieldContext_PlannedExamWithNTA_nta(ctx, field) + return ec.fieldContext_Exam_nta(ctx, field) + case "slot": + return ec.fieldContext_Exam_slot(ctx, field) + case "rooms": + return ec.fieldContext_Exam_rooms(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type PlannedExamWithNTA", field.Name) + return nil, fmt.Errorf("no field named %q was found under type Exam", field.Name) }, } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_plannedExamsInSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } return fc, nil } -func (ec *executionContext) _Query_examsInPlan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_examsInPlan(ctx, field) +func (ec *executionContext) _Query_exam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_exam(ctx, field) if err != nil { return graphql.Null } @@ -15807,7 +15917,7 @@ func (ec *executionContext) _Query_examsInPlan(ctx context.Context, field graphq }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ExamsInPlan(rctx) + return ec.resolvers.Query().Exam(rctx, fc.Args["ancode"].(int)) }) if err != nil { ec.Error(ctx, err) @@ -15816,12 +15926,12 @@ func (ec *executionContext) _Query_examsInPlan(ctx context.Context, field graphq if resTmp == nil { return graphql.Null } - res := resTmp.([]*model.ExamInPlan) + res := resTmp.(*model.Exam) fc.Result = res - return ec.marshalOExamInPlan2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamInPlanᚄ(ctx, field.Selections, res) + return ec.marshalOExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExam(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_examsInPlan(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_exam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -15829,23 +15939,48 @@ func (ec *executionContext) fieldContext_Query_examsInPlan(ctx context.Context, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "exam": - return ec.fieldContext_ExamInPlan_exam(ctx, field) + case "ancode": + return ec.fieldContext_Exam_ancode(ctx, field) + case "zpaExam": + return ec.fieldContext_Exam_zpaExam(ctx, field) + case "externalExam": + return ec.fieldContext_Exam_externalExam(ctx, field) + case "primussExams": + return ec.fieldContext_Exam_primussExams(ctx, field) + case "studentRegs": + return ec.fieldContext_Exam_studentRegs(ctx, field) + case "conflicts": + return ec.fieldContext_Exam_conflicts(ctx, field) + case "connectErrors": + return ec.fieldContext_Exam_connectErrors(ctx, field) case "constraints": - return ec.fieldContext_ExamInPlan_constraints(ctx, field) + return ec.fieldContext_Exam_constraints(ctx, field) case "nta": - return ec.fieldContext_ExamInPlan_nta(ctx, field) + return ec.fieldContext_Exam_nta(ctx, field) case "slot": - return ec.fieldContext_ExamInPlan_slot(ctx, field) + return ec.fieldContext_Exam_slot(ctx, field) + case "rooms": + return ec.fieldContext_Exam_rooms(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ExamInPlan", field.Name) + return nil, fmt.Errorf("no field named %q was found under type Exam", field.Name) }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_exam_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } -func (ec *executionContext) _Query_examsInSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_examsInSlot(ctx, field) +func (ec *executionContext) _Query_teacher(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_teacher(ctx, field) if err != nil { return graphql.Null } @@ -15858,7 +15993,7 @@ func (ec *executionContext) _Query_examsInSlot(ctx context.Context, field graphq }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ExamsInSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) + return ec.resolvers.Query().Teacher(rctx, fc.Args["id"].(int)) }) if err != nil { ec.Error(ctx, err) @@ -15867,12 +16002,12 @@ func (ec *executionContext) _Query_examsInSlot(ctx context.Context, field graphq if resTmp == nil { return graphql.Null } - res := resTmp.([]*model.ExamInPlan) + res := resTmp.(*model.Teacher) fc.Result = res - return ec.marshalOExamInPlan2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamInPlanᚄ(ctx, field.Selections, res) + return ec.marshalOTeacher2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐTeacher(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_examsInSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_teacher(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -15880,16 +16015,28 @@ func (ec *executionContext) fieldContext_Query_examsInSlot(ctx context.Context, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "exam": - return ec.fieldContext_ExamInPlan_exam(ctx, field) - case "constraints": - return ec.fieldContext_ExamInPlan_constraints(ctx, field) - case "nta": - return ec.fieldContext_ExamInPlan_nta(ctx, field) - case "slot": - return ec.fieldContext_ExamInPlan_slot(ctx, field) + case "shortname": + return ec.fieldContext_Teacher_shortname(ctx, field) + case "fullname": + return ec.fieldContext_Teacher_fullname(ctx, field) + case "isProf": + return ec.fieldContext_Teacher_isProf(ctx, field) + case "isLBA": + return ec.fieldContext_Teacher_isLBA(ctx, field) + case "isProfHC": + return ec.fieldContext_Teacher_isProfHC(ctx, field) + case "isStaff": + return ec.fieldContext_Teacher_isStaff(ctx, field) + case "lastSemester": + return ec.fieldContext_Teacher_lastSemester(ctx, field) + case "fk": + return ec.fieldContext_Teacher_fk(ctx, field) + case "id": + return ec.fieldContext_Teacher_id(ctx, field) + case "email": + return ec.fieldContext_Teacher_email(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ExamInPlan", field.Name) + return nil, fmt.Errorf("no field named %q was found under type Teacher", field.Name) }, } defer func() { @@ -15899,15 +16046,15 @@ func (ec *executionContext) fieldContext_Query_examsInSlot(ctx context.Context, } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_examsInSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_Query_teacher_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } return fc, nil } -func (ec *executionContext) _Query_examsInSlotWithRooms(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_examsInSlotWithRooms(ctx, field) +func (ec *executionContext) _Query_teachers(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_teachers(ctx, field) if err != nil { return graphql.Null } @@ -15920,21 +16067,24 @@ func (ec *executionContext) _Query_examsInSlotWithRooms(ctx context.Context, fie }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ExamsInSlotWithRooms(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) + return ec.resolvers.Query().Teachers(rctx, fc.Args["fromZPA"].(*bool)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.([]*model.ExamWithRegsAndRooms) + res := resTmp.([]*model.Teacher) fc.Result = res - return ec.marshalOExamWithRegsAndRooms2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegsAndRoomsᚄ(ctx, field.Selections, res) + return ec.marshalNTeacher2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐTeacherᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_examsInSlotWithRooms(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_teachers(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -15942,16 +16092,28 @@ func (ec *executionContext) fieldContext_Query_examsInSlotWithRooms(ctx context. IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "exam": - return ec.fieldContext_ExamWithRegsAndRooms_exam(ctx, field) - case "normalRegs": - return ec.fieldContext_ExamWithRegsAndRooms_normalRegs(ctx, field) - case "ntaRegs": - return ec.fieldContext_ExamWithRegsAndRooms_ntaRegs(ctx, field) - case "rooms": - return ec.fieldContext_ExamWithRegsAndRooms_rooms(ctx, field) + case "shortname": + return ec.fieldContext_Teacher_shortname(ctx, field) + case "fullname": + return ec.fieldContext_Teacher_fullname(ctx, field) + case "isProf": + return ec.fieldContext_Teacher_isProf(ctx, field) + case "isLBA": + return ec.fieldContext_Teacher_isLBA(ctx, field) + case "isProfHC": + return ec.fieldContext_Teacher_isProfHC(ctx, field) + case "isStaff": + return ec.fieldContext_Teacher_isStaff(ctx, field) + case "lastSemester": + return ec.fieldContext_Teacher_lastSemester(ctx, field) + case "fk": + return ec.fieldContext_Teacher_fk(ctx, field) + case "id": + return ec.fieldContext_Teacher_id(ctx, field) + case "email": + return ec.fieldContext_Teacher_email(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ExamWithRegsAndRooms", field.Name) + return nil, fmt.Errorf("no field named %q was found under type Teacher", field.Name) }, } defer func() { @@ -15961,15 +16123,15 @@ func (ec *executionContext) fieldContext_Query_examsInSlotWithRooms(ctx context. } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_examsInSlotWithRooms_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_Query_teachers_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } return fc, nil } -func (ec *executionContext) _Query_rooms(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_rooms(ctx, field) +func (ec *executionContext) _Query_invigilators(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_invigilators(ctx, field) if err != nil { return graphql.Null } @@ -15982,7 +16144,7 @@ func (ec *executionContext) _Query_rooms(ctx context.Context, field graphql.Coll }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Rooms(rctx) + return ec.resolvers.Query().Invigilators(rctx) }) if err != nil { ec.Error(ctx, err) @@ -15994,44 +16156,32 @@ func (ec *executionContext) _Query_rooms(ctx context.Context, field graphql.Coll } return graphql.Null } - res := resTmp.([]*model.Room) + res := resTmp.([]*model.ZPAInvigilator) fc.Result = res - return ec.marshalNRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomᚄ(ctx, field.Selections, res) + return ec.marshalNZPAInvigilator2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAInvigilatorᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_rooms(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_invigilators(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, IsMethod: true, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "name": - return ec.fieldContext_Room_name(ctx, field) - case "seats": - return ec.fieldContext_Room_seats(ctx, field) - case "handicap": - return ec.fieldContext_Room_handicap(ctx, field) - case "lab": - return ec.fieldContext_Room_lab(ctx, field) - case "placesWithSocket": - return ec.fieldContext_Room_placesWithSocket(ctx, field) - case "needsRequest": - return ec.fieldContext_Room_needsRequest(ctx, field) - case "exahm": - return ec.fieldContext_Room_exahm(ctx, field) - case "seb": - return ec.fieldContext_Room_seb(ctx, field) + switch field.Name { + case "teacher": + return ec.fieldContext_ZPAInvigilator_teacher(ctx, field) + case "hasSubmittedRequirements": + return ec.fieldContext_ZPAInvigilator_hasSubmittedRequirements(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type Room", field.Name) + return nil, fmt.Errorf("no field named %q was found under type ZPAInvigilator", field.Name) }, } return fc, nil } -func (ec *executionContext) _Query_roomsWithConstraints(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_roomsWithConstraints(ctx, field) +func (ec *executionContext) _Query_fk07programs(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_fk07programs(ctx, field) if err != nil { return graphql.Null } @@ -16044,7 +16194,7 @@ func (ec *executionContext) _Query_roomsWithConstraints(ctx context.Context, fie }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().RoomsWithConstraints(rctx, fc.Args["handicap"].(bool), fc.Args["lab"].(bool), fc.Args["placesWithSocket"].(bool), fc.Args["exahm"].(*bool)) + return ec.resolvers.Query().Fk07programs(rctx) }) if err != nil { ec.Error(ctx, err) @@ -16056,12 +16206,12 @@ func (ec *executionContext) _Query_roomsWithConstraints(ctx context.Context, fie } return graphql.Null } - res := resTmp.([]*model.Room) + res := resTmp.([]*model.FK07Program) fc.Result = res - return ec.marshalNRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomᚄ(ctx, field.Selections, res) + return ec.marshalNFK07Program2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐFK07Programᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_roomsWithConstraints(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_fk07programs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -16070,41 +16220,16 @@ func (ec *executionContext) fieldContext_Query_roomsWithConstraints(ctx context. Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { case "name": - return ec.fieldContext_Room_name(ctx, field) - case "seats": - return ec.fieldContext_Room_seats(ctx, field) - case "handicap": - return ec.fieldContext_Room_handicap(ctx, field) - case "lab": - return ec.fieldContext_Room_lab(ctx, field) - case "placesWithSocket": - return ec.fieldContext_Room_placesWithSocket(ctx, field) - case "needsRequest": - return ec.fieldContext_Room_needsRequest(ctx, field) - case "exahm": - return ec.fieldContext_Room_exahm(ctx, field) - case "seb": - return ec.fieldContext_Room_seb(ctx, field) + return ec.fieldContext_FK07Program_name(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type Room", field.Name) + return nil, fmt.Errorf("no field named %q was found under type FK07Program", field.Name) }, } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_roomsWithConstraints_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } return fc, nil } -func (ec *executionContext) _Query_roomsForSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_roomsForSlot(ctx, field) +func (ec *executionContext) _Query_zpaExams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_zpaExams(ctx, field) if err != nil { return graphql.Null } @@ -16117,21 +16242,24 @@ func (ec *executionContext) _Query_roomsForSlot(ctx context.Context, field graph }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().RoomsForSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) + return ec.resolvers.Query().ZpaExams(rctx, fc.Args["fromZPA"].(*bool)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*model.SlotWithRooms) + res := resTmp.([]*model.ZPAExam) fc.Result = res - return ec.marshalOSlotWithRooms2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSlotWithRooms(ctx, field.Selections, res) + return ec.marshalNZPAExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_roomsForSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_zpaExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -16139,20 +16267,30 @@ func (ec *executionContext) fieldContext_Query_roomsForSlot(ctx context.Context, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "dayNumber": - return ec.fieldContext_SlotWithRooms_dayNumber(ctx, field) - case "slotNumber": - return ec.fieldContext_SlotWithRooms_slotNumber(ctx, field) - case "normalRooms": - return ec.fieldContext_SlotWithRooms_normalRooms(ctx, field) - case "exahmRooms": - return ec.fieldContext_SlotWithRooms_exahmRooms(ctx, field) - case "labRooms": - return ec.fieldContext_SlotWithRooms_labRooms(ctx, field) - case "ntaRooms": - return ec.fieldContext_SlotWithRooms_ntaRooms(ctx, field) + case "zpaID": + return ec.fieldContext_ZPAExam_zpaID(ctx, field) + case "semester": + return ec.fieldContext_ZPAExam_semester(ctx, field) + case "ancode": + return ec.fieldContext_ZPAExam_ancode(ctx, field) + case "module": + return ec.fieldContext_ZPAExam_module(ctx, field) + case "mainExamer": + return ec.fieldContext_ZPAExam_mainExamer(ctx, field) + case "mainExamerID": + return ec.fieldContext_ZPAExam_mainExamerID(ctx, field) + case "examType": + return ec.fieldContext_ZPAExam_examType(ctx, field) + case "examTypeFull": + return ec.fieldContext_ZPAExam_examTypeFull(ctx, field) + case "duration": + return ec.fieldContext_ZPAExam_duration(ctx, field) + case "isRepeaterExam": + return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) + case "groups": + return ec.fieldContext_ZPAExam_groups(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type SlotWithRooms", field.Name) + return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) }, } defer func() { @@ -16162,15 +16300,15 @@ func (ec *executionContext) fieldContext_Query_roomsForSlot(ctx context.Context, } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_roomsForSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_Query_zpaExams_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } return fc, nil } -func (ec *executionContext) _Query_plannedRoomNames(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_plannedRoomNames(ctx, field) +func (ec *executionContext) _Query_zpaExamsByType(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_zpaExamsByType(ctx, field) if err != nil { return graphql.Null } @@ -16183,35 +16321,44 @@ func (ec *executionContext) _Query_plannedRoomNames(ctx context.Context, field g }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().PlannedRoomNames(rctx) + return ec.resolvers.Query().ZpaExamsByType(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.([]string) + res := resTmp.([]*model.ZPAExamsForType) fc.Result = res - return ec.marshalOString2ᚕstringᚄ(ctx, field.Selections, res) + return ec.marshalNZPAExamsForType2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamsForTypeᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_plannedRoomNames(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_zpaExamsByType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, IsMethod: true, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + switch field.Name { + case "type": + return ec.fieldContext_ZPAExamsForType_type(ctx, field) + case "exams": + return ec.fieldContext_ZPAExamsForType_exams(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ZPAExamsForType", field.Name) }, } return fc, nil } -func (ec *executionContext) _Query_plannedRoomNamesInSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_plannedRoomNamesInSlot(ctx, field) +func (ec *executionContext) _Query_zpaExamsToPlan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_zpaExamsToPlan(ctx, field) if err != nil { return graphql.Null } @@ -16224,46 +16371,62 @@ func (ec *executionContext) _Query_plannedRoomNamesInSlot(ctx context.Context, f }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().PlannedRoomNamesInSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) + return ec.resolvers.Query().ZpaExamsToPlan(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.([]string) + res := resTmp.([]*model.ZPAExam) fc.Result = res - return ec.marshalOString2ᚕstringᚄ(ctx, field.Selections, res) + return ec.marshalNZPAExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_plannedRoomNamesInSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_zpaExamsToPlan(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, IsMethod: true, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + switch field.Name { + case "zpaID": + return ec.fieldContext_ZPAExam_zpaID(ctx, field) + case "semester": + return ec.fieldContext_ZPAExam_semester(ctx, field) + case "ancode": + return ec.fieldContext_ZPAExam_ancode(ctx, field) + case "module": + return ec.fieldContext_ZPAExam_module(ctx, field) + case "mainExamer": + return ec.fieldContext_ZPAExam_mainExamer(ctx, field) + case "mainExamerID": + return ec.fieldContext_ZPAExam_mainExamerID(ctx, field) + case "examType": + return ec.fieldContext_ZPAExam_examType(ctx, field) + case "examTypeFull": + return ec.fieldContext_ZPAExam_examTypeFull(ctx, field) + case "duration": + return ec.fieldContext_ZPAExam_duration(ctx, field) + case "isRepeaterExam": + return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) + case "groups": + return ec.fieldContext_ZPAExam_groups(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) }, } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_plannedRoomNamesInSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } return fc, nil } -func (ec *executionContext) _Query_invigilatorsWithReq(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_invigilatorsWithReq(ctx, field) +func (ec *executionContext) _Query_zpaExamsNotToPlan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_zpaExamsNotToPlan(ctx, field) if err != nil { return graphql.Null } @@ -16276,7 +16439,7 @@ func (ec *executionContext) _Query_invigilatorsWithReq(ctx context.Context, fiel }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().InvigilatorsWithReq(rctx) + return ec.resolvers.Query().ZpaExamsNotToPlan(rctx) }) if err != nil { ec.Error(ctx, err) @@ -16288,12 +16451,12 @@ func (ec *executionContext) _Query_invigilatorsWithReq(ctx context.Context, fiel } return graphql.Null } - res := resTmp.([]*model.Invigilator) + res := resTmp.([]*model.ZPAExam) fc.Result = res - return ec.marshalNInvigilator2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilatorᚄ(ctx, field.Selections, res) + return ec.marshalNZPAExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_invigilatorsWithReq(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_zpaExamsNotToPlan(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -16301,21 +16464,37 @@ func (ec *executionContext) fieldContext_Query_invigilatorsWithReq(ctx context.C IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "teacher": - return ec.fieldContext_Invigilator_teacher(ctx, field) - case "requirements": - return ec.fieldContext_Invigilator_requirements(ctx, field) - case "todos": - return ec.fieldContext_Invigilator_todos(ctx, field) + case "zpaID": + return ec.fieldContext_ZPAExam_zpaID(ctx, field) + case "semester": + return ec.fieldContext_ZPAExam_semester(ctx, field) + case "ancode": + return ec.fieldContext_ZPAExam_ancode(ctx, field) + case "module": + return ec.fieldContext_ZPAExam_module(ctx, field) + case "mainExamer": + return ec.fieldContext_ZPAExam_mainExamer(ctx, field) + case "mainExamerID": + return ec.fieldContext_ZPAExam_mainExamerID(ctx, field) + case "examType": + return ec.fieldContext_ZPAExam_examType(ctx, field) + case "examTypeFull": + return ec.fieldContext_ZPAExam_examTypeFull(ctx, field) + case "duration": + return ec.fieldContext_ZPAExam_duration(ctx, field) + case "isRepeaterExam": + return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) + case "groups": + return ec.fieldContext_ZPAExam_groups(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type Invigilator", field.Name) + return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) }, } return fc, nil } -func (ec *executionContext) _Query_invigilatorTodos(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_invigilatorTodos(ctx, field) +func (ec *executionContext) _Query_zpaExamsPlaningStatusUnknown(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_zpaExamsPlaningStatusUnknown(ctx, field) if err != nil { return graphql.Null } @@ -16328,53 +16507,62 @@ func (ec *executionContext) _Query_invigilatorTodos(ctx context.Context, field g }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().InvigilatorTodos(rctx) + return ec.resolvers.Query().ZpaExamsPlaningStatusUnknown(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*model.InvigilationTodos) + res := resTmp.([]*model.ZPAExam) fc.Result = res - return ec.marshalOInvigilationTodos2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilationTodos(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_invigilatorTodos(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "sumExamRooms": - return ec.fieldContext_InvigilationTodos_sumExamRooms(ctx, field) - case "sumReserve": - return ec.fieldContext_InvigilationTodos_sumReserve(ctx, field) - case "sumOtherContributions": - return ec.fieldContext_InvigilationTodos_sumOtherContributions(ctx, field) - case "sumOtherContributionsOvertimeCutted": - return ec.fieldContext_InvigilationTodos_sumOtherContributionsOvertimeCutted(ctx, field) - case "invigilatorCount": - return ec.fieldContext_InvigilationTodos_invigilatorCount(ctx, field) - case "todoPerInvigilator": - return ec.fieldContext_InvigilationTodos_todoPerInvigilator(ctx, field) - case "todoPerInvigilatorOvertimeCutted": - return ec.fieldContext_InvigilationTodos_todoPerInvigilatorOvertimeCutted(ctx, field) - case "invigilators": - return ec.fieldContext_InvigilationTodos_invigilators(ctx, field) + return ec.marshalNZPAExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_zpaExamsPlaningStatusUnknown(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "zpaID": + return ec.fieldContext_ZPAExam_zpaID(ctx, field) + case "semester": + return ec.fieldContext_ZPAExam_semester(ctx, field) + case "ancode": + return ec.fieldContext_ZPAExam_ancode(ctx, field) + case "module": + return ec.fieldContext_ZPAExam_module(ctx, field) + case "mainExamer": + return ec.fieldContext_ZPAExam_mainExamer(ctx, field) + case "mainExamerID": + return ec.fieldContext_ZPAExam_mainExamerID(ctx, field) + case "examType": + return ec.fieldContext_ZPAExam_examType(ctx, field) + case "examTypeFull": + return ec.fieldContext_ZPAExam_examTypeFull(ctx, field) + case "duration": + return ec.fieldContext_ZPAExam_duration(ctx, field) + case "isRepeaterExam": + return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) + case "groups": + return ec.fieldContext_ZPAExam_groups(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type InvigilationTodos", field.Name) + return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) }, } return fc, nil } -func (ec *executionContext) _Query_roomsWithInvigilationsForSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_roomsWithInvigilationsForSlot(ctx, field) +func (ec *executionContext) _Query_zpaExam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_zpaExam(ctx, field) if err != nil { return graphql.Null } @@ -16387,7 +16575,7 @@ func (ec *executionContext) _Query_roomsWithInvigilationsForSlot(ctx context.Con }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().RoomsWithInvigilationsForSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) + return ec.resolvers.Query().ZpaExam(rctx, fc.Args["ancode"].(int)) }) if err != nil { ec.Error(ctx, err) @@ -16396,12 +16584,12 @@ func (ec *executionContext) _Query_roomsWithInvigilationsForSlot(ctx context.Con if resTmp == nil { return graphql.Null } - res := resTmp.(*model.InvigilationSlot) + res := resTmp.(*model.ZPAExam) fc.Result = res - return ec.marshalOInvigilationSlot2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilationSlot(ctx, field.Selections, res) + return ec.marshalOZPAExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExam(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_roomsWithInvigilationsForSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_zpaExam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -16409,12 +16597,30 @@ func (ec *executionContext) fieldContext_Query_roomsWithInvigilationsForSlot(ctx IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "reserve": - return ec.fieldContext_InvigilationSlot_reserve(ctx, field) - case "roomsWithInvigilators": - return ec.fieldContext_InvigilationSlot_roomsWithInvigilators(ctx, field) + case "zpaID": + return ec.fieldContext_ZPAExam_zpaID(ctx, field) + case "semester": + return ec.fieldContext_ZPAExam_semester(ctx, field) + case "ancode": + return ec.fieldContext_ZPAExam_ancode(ctx, field) + case "module": + return ec.fieldContext_ZPAExam_module(ctx, field) + case "mainExamer": + return ec.fieldContext_ZPAExam_mainExamer(ctx, field) + case "mainExamerID": + return ec.fieldContext_ZPAExam_mainExamerID(ctx, field) + case "examType": + return ec.fieldContext_ZPAExam_examType(ctx, field) + case "examTypeFull": + return ec.fieldContext_ZPAExam_examTypeFull(ctx, field) + case "duration": + return ec.fieldContext_ZPAExam_duration(ctx, field) + case "isRepeaterExam": + return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) + case "groups": + return ec.fieldContext_ZPAExam_groups(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type InvigilationSlot", field.Name) + return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) }, } defer func() { @@ -16424,15 +16630,15 @@ func (ec *executionContext) fieldContext_Query_roomsWithInvigilationsForSlot(ctx } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_roomsWithInvigilationsForSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_Query_zpaExam_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } return fc, nil } -func (ec *executionContext) _Query_invigilatorsForDay(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_invigilatorsForDay(ctx, field) +func (ec *executionContext) _Query_zpaAnCodes(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_zpaAnCodes(ctx, field) if err != nil { return graphql.Null } @@ -16445,7 +16651,7 @@ func (ec *executionContext) _Query_invigilatorsForDay(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().InvigilatorsForDay(rctx, fc.Args["day"].(int)) + return ec.resolvers.Query().ZpaAnCodes(rctx) }) if err != nil { ec.Error(ctx, err) @@ -16454,12 +16660,12 @@ func (ec *executionContext) _Query_invigilatorsForDay(ctx context.Context, field if resTmp == nil { return graphql.Null } - res := resTmp.(*model.InvigilatorsForDay) + res := resTmp.([]*model.AnCode) fc.Result = res - return ec.marshalOInvigilatorsForDay2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilatorsForDay(ctx, field.Selections, res) + return ec.marshalOAnCode2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAnCode(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_invigilatorsForDay(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_zpaAnCodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -16467,30 +16673,17 @@ func (ec *executionContext) fieldContext_Query_invigilatorsForDay(ctx context.Co IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "want": - return ec.fieldContext_InvigilatorsForDay_want(ctx, field) - case "can": - return ec.fieldContext_InvigilatorsForDay_can(ctx, field) + case "ancode": + return ec.fieldContext_AnCode_ancode(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type InvigilatorsForDay", field.Name) + return nil, fmt.Errorf("no field named %q was found under type AnCode", field.Name) }, } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_invigilatorsForDay_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } return fc, nil } -func (ec *executionContext) _Query_dayOkForInvigilator(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_dayOkForInvigilator(ctx, field) +func (ec *executionContext) _Query_studentRegsImportErrors(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_studentRegsImportErrors(ctx, field) if err != nil { return graphql.Null } @@ -16503,41 +16696,39 @@ func (ec *executionContext) _Query_dayOkForInvigilator(ctx context.Context, fiel }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().DayOkForInvigilator(rctx, fc.Args["day"].(int), fc.Args["invigilatorID"].(int)) + return ec.resolvers.Query().StudentRegsImportErrors(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*bool) + res := resTmp.([]*model.RegWithError) fc.Result = res - return ec.marshalOBoolean2ᚖbool(ctx, field.Selections, res) + return ec.marshalNRegWithError2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRegWithErrorᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_dayOkForInvigilator(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_studentRegsImportErrors(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, IsMethod: true, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Boolean does not have child fields") + switch field.Name { + case "registration": + return ec.fieldContext_RegWithError_registration(ctx, field) + case "error": + return ec.fieldContext_RegWithError_error(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type RegWithError", field.Name) }, } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_dayOkForInvigilator_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } return fc, nil } @@ -25766,7 +25957,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "teacher": + case "additionalExams": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -25775,7 +25966,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_teacher(ctx, field) + res = ec._Query_additionalExams(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -25785,7 +25979,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "teachers": + case "primussExams": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -25794,10 +25988,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_teachers(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } + res = ec._Query_primussExams(ctx, field) return res } @@ -25807,7 +25998,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "invigilators": + case "primussExam": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -25816,7 +26007,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_invigilators(ctx, field) + res = ec._Query_primussExam(ctx, field) if res == graphql.Null { atomic.AddUint32(&fs.Invalids, 1) } @@ -25829,7 +26020,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "fk07programs": + case "primussExamsForAnCode": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -25838,10 +26029,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_fk07programs(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } + res = ec._Query_primussExamsForAnCode(ctx, field) return res } @@ -25851,7 +26039,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "zpaExams": + case "studentRegsForProgram": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -25860,10 +26048,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_zpaExams(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } + res = ec._Query_studentRegsForProgram(ctx, field) return res } @@ -25873,7 +26058,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "zpaExamsByType": + case "connectedExam": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -25882,10 +26067,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_zpaExamsByType(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } + res = ec._Query_connectedExam(ctx, field) return res } @@ -25895,7 +26077,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "zpaExamsToPlan": + case "connectedExams": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -25904,7 +26086,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_zpaExamsToPlan(ctx, field) + res = ec._Query_connectedExams(ctx, field) if res == graphql.Null { atomic.AddUint32(&fs.Invalids, 1) } @@ -25917,7 +26099,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "zpaExamsNotToPlan": + case "examWithRegs": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -25926,10 +26108,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_zpaExamsNotToPlan(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } + res = ec._Query_examWithRegs(ctx, field) return res } @@ -25939,7 +26118,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "zpaExamsPlaningStatusUnknown": + case "examsWithRegs": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -25948,10 +26127,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_zpaExamsPlaningStatusUnknown(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } + res = ec._Query_examsWithRegs(ctx, field) return res } @@ -25961,7 +26137,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "zpaExam": + case "constraintForAncode": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -25970,7 +26146,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_zpaExam(ctx, field) + res = ec._Query_constraintForAncode(ctx, field) return res } @@ -25980,7 +26156,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "zpaAnCodes": + case "zpaExamsToPlanWithConstraints": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -25989,7 +26165,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_zpaAnCodes(ctx, field) + res = ec._Query_zpaExamsToPlanWithConstraints(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -25999,7 +26178,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "studentRegsImportErrors": + case "examGroups": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26008,7 +26187,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_studentRegsImportErrors(ctx, field) + res = ec._Query_examGroups(ctx, field) if res == graphql.Null { atomic.AddUint32(&fs.Invalids, 1) } @@ -26021,7 +26200,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "additionalExams": + case "examGroup": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26030,10 +26209,45 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_additionalExams(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } + res = ec._Query_examGroup(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "conflictingGroupCodes": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_conflictingGroupCodes(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "ntas": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_ntas(ctx, field) return res } @@ -26043,7 +26257,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "primussExams": + case "ntasWithRegs": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26052,7 +26266,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_primussExams(ctx, field) + res = ec._Query_ntasWithRegs(ctx, field) return res } @@ -26062,7 +26276,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "primussExam": + case "ntasWithRegsByTeacher": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26071,10 +26285,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_primussExam(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } + res = ec._Query_ntasWithRegsByTeacher(ctx, field) return res } @@ -26084,7 +26295,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "primussExamsForAnCode": + case "nta": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26093,7 +26304,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_primussExamsForAnCode(ctx, field) + res = ec._Query_nta(ctx, field) return res } @@ -26103,7 +26314,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "studentRegsForProgram": + case "allowedSlots": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26112,7 +26323,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_studentRegsForProgram(ctx, field) + res = ec._Query_allowedSlots(ctx, field) return res } @@ -26122,7 +26333,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "connectedExam": + case "awkwardSlots": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26131,7 +26342,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_connectedExam(ctx, field) + res = ec._Query_awkwardSlots(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -26141,7 +26355,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "connectedExams": + case "examGroupsInSlot": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26150,10 +26364,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_connectedExams(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } + res = ec._Query_examGroupsInSlot(ctx, field) return res } @@ -26163,7 +26374,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "examWithRegs": + case "examGroupsWithoutSlot": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26172,7 +26383,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_examWithRegs(ctx, field) + res = ec._Query_examGroupsWithoutSlot(ctx, field) return res } @@ -26182,7 +26393,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "examsWithRegs": + case "allProgramsInPlan": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26191,7 +26402,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_examsWithRegs(ctx, field) + res = ec._Query_allProgramsInPlan(ctx, field) return res } @@ -26201,7 +26412,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "constraintForAncode": + case "ancodesInPlan": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26210,7 +26421,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_constraintForAncode(ctx, field) + res = ec._Query_ancodesInPlan(ctx, field) return res } @@ -26220,7 +26431,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "zpaExamsToPlanWithConstraints": + case "examerInPlan": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26229,10 +26440,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_zpaExamsToPlanWithConstraints(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } + res = ec._Query_examerInPlan(ctx, field) return res } @@ -26242,7 +26450,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "examGroups": + case "plannedExamsInSlot": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26251,10 +26459,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_examGroups(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } + res = ec._Query_plannedExamsInSlot(ctx, field) return res } @@ -26264,7 +26469,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "examGroup": + case "examsInPlan": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26273,7 +26478,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_examGroup(ctx, field) + res = ec._Query_examsInPlan(ctx, field) return res } @@ -26283,7 +26488,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "conflictingGroupCodes": + case "examsInSlot": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26292,7 +26497,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_conflictingGroupCodes(ctx, field) + res = ec._Query_examsInSlot(ctx, field) return res } @@ -26302,7 +26507,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "ntas": + case "examsInSlotWithRooms": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26311,7 +26516,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_ntas(ctx, field) + res = ec._Query_examsInSlotWithRooms(ctx, field) return res } @@ -26321,7 +26526,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "ntasWithRegs": + case "rooms": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26330,7 +26535,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_ntasWithRegs(ctx, field) + res = ec._Query_rooms(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -26340,7 +26548,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "ntasWithRegsByTeacher": + case "roomsWithConstraints": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26349,7 +26557,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_ntasWithRegsByTeacher(ctx, field) + res = ec._Query_roomsWithConstraints(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -26359,7 +26570,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "nta": + case "roomsForSlot": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26368,7 +26579,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_nta(ctx, field) + res = ec._Query_roomsForSlot(ctx, field) return res } @@ -26378,7 +26589,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "allowedSlots": + case "plannedRoomNames": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26387,7 +26598,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_allowedSlots(ctx, field) + res = ec._Query_plannedRoomNames(ctx, field) return res } @@ -26397,7 +26608,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "awkwardSlots": + case "plannedRoomNamesInSlot": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26406,10 +26617,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_awkwardSlots(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } + res = ec._Query_plannedRoomNamesInSlot(ctx, field) return res } @@ -26419,7 +26627,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "examGroupsInSlot": + case "invigilatorsWithReq": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26428,7 +26636,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_examGroupsInSlot(ctx, field) + res = ec._Query_invigilatorsWithReq(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -26438,7 +26649,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "examGroupsWithoutSlot": + case "invigilatorTodos": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26447,7 +26658,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_examGroupsWithoutSlot(ctx, field) + res = ec._Query_invigilatorTodos(ctx, field) return res } @@ -26457,7 +26668,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "allProgramsInPlan": + case "roomsWithInvigilationsForSlot": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26466,7 +26677,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_allProgramsInPlan(ctx, field) + res = ec._Query_roomsWithInvigilationsForSlot(ctx, field) return res } @@ -26476,7 +26687,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "ancodesInPlan": + case "invigilatorsForDay": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26485,7 +26696,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_ancodesInPlan(ctx, field) + res = ec._Query_invigilatorsForDay(ctx, field) return res } @@ -26495,7 +26706,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "examerInPlan": + case "dayOkForInvigilator": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26504,7 +26715,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_examerInPlan(ctx, field) + res = ec._Query_dayOkForInvigilator(ctx, field) return res } @@ -26514,7 +26725,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "plannedExamsInSlot": + case "exams": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26523,7 +26734,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_plannedExamsInSlot(ctx, field) + res = ec._Query_exams(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -26533,7 +26747,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "examsInPlan": + case "exam": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26542,7 +26756,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_examsInPlan(ctx, field) + res = ec._Query_exam(ctx, field) return res } @@ -26552,7 +26766,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "examsInSlot": + case "teacher": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26561,7 +26775,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_examsInSlot(ctx, field) + res = ec._Query_teacher(ctx, field) return res } @@ -26571,7 +26785,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "examsInSlotWithRooms": + case "teachers": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26580,7 +26794,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_examsInSlotWithRooms(ctx, field) + res = ec._Query_teachers(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -26590,7 +26807,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "rooms": + case "invigilators": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26599,7 +26816,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_rooms(ctx, field) + res = ec._Query_invigilators(ctx, field) if res == graphql.Null { atomic.AddUint32(&fs.Invalids, 1) } @@ -26612,7 +26829,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "roomsWithConstraints": + case "fk07programs": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26621,7 +26838,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_roomsWithConstraints(ctx, field) + res = ec._Query_fk07programs(ctx, field) if res == graphql.Null { atomic.AddUint32(&fs.Invalids, 1) } @@ -26634,7 +26851,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "roomsForSlot": + case "zpaExams": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26643,7 +26860,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_roomsForSlot(ctx, field) + res = ec._Query_zpaExams(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -26653,7 +26873,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "plannedRoomNames": + case "zpaExamsByType": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26662,7 +26882,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_plannedRoomNames(ctx, field) + res = ec._Query_zpaExamsByType(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -26672,7 +26895,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "plannedRoomNamesInSlot": + case "zpaExamsToPlan": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26681,7 +26904,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_plannedRoomNamesInSlot(ctx, field) + res = ec._Query_zpaExamsToPlan(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -26691,7 +26917,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "invigilatorsWithReq": + case "zpaExamsNotToPlan": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26700,7 +26926,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_invigilatorsWithReq(ctx, field) + res = ec._Query_zpaExamsNotToPlan(ctx, field) if res == graphql.Null { atomic.AddUint32(&fs.Invalids, 1) } @@ -26713,7 +26939,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "invigilatorTodos": + case "zpaExamsPlaningStatusUnknown": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26722,7 +26948,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_invigilatorTodos(ctx, field) + res = ec._Query_zpaExamsPlaningStatusUnknown(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -26732,7 +26961,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "roomsWithInvigilationsForSlot": + case "zpaExam": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26741,7 +26970,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_roomsWithInvigilationsForSlot(ctx, field) + res = ec._Query_zpaExam(ctx, field) return res } @@ -26751,7 +26980,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "invigilatorsForDay": + case "zpaAnCodes": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26760,7 +26989,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_invigilatorsForDay(ctx, field) + res = ec._Query_zpaAnCodes(ctx, field) return res } @@ -26770,7 +26999,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "dayOkForInvigilator": + case "studentRegsImportErrors": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26779,7 +27008,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_dayOkForInvigilator(ctx, field) + res = ec._Query_studentRegsImportErrors(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -28769,6 +29001,60 @@ func (ec *executionContext) marshalNConnectedExam2ᚖgithubᚗcomᚋobcodeᚋple return ec._ConnectedExam(ctx, sel, v) } +func (ec *executionContext) marshalNExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Exam) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExam(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExam(ctx context.Context, sel ast.SelectionSet, v *model.Exam) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._Exam(ctx, sel, v) +} + func (ec *executionContext) marshalNExamDay2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamDayᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExamDay) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup @@ -30749,6 +31035,13 @@ func (ec *executionContext) marshalOConstraints2ᚖgithubᚗcomᚋobcodeᚋplexa return ec._Constraints(ctx, sel, v) } +func (ec *executionContext) marshalOExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExam(ctx context.Context, sel ast.SelectionSet, v *model.Exam) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._Exam(ctx, sel, v) +} + func (ec *executionContext) marshalOExamGroup2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroup(ctx context.Context, sel ast.SelectionSet, v []*model.ExamGroup) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/graph/query.graphqls b/graph/query.graphqls index c7444eb..e6242b5 100644 --- a/graph/query.graphqls +++ b/graph/query.graphqls @@ -5,18 +5,7 @@ type Query { semester: Semester! semesterConfig: SemesterConfig! # ZPA - teacher(id: Int!): Teacher - teachers(fromZPA: Boolean): [Teacher!]! - invigilators: [ZPAInvigilator!]! - fk07programs: [FK07Program!]! - zpaExams(fromZPA: Boolean): [ZPAExam!]! - zpaExamsByType: [ZPAExamsForType!]! - zpaExamsToPlan: [ZPAExam!]! - zpaExamsNotToPlan: [ZPAExam!]! - zpaExamsPlaningStatusUnknown: [ZPAExam!]! - zpaExam(ancode: Int!): ZPAExam - zpaAnCodes: [AnCode] - studentRegsImportErrors: [RegWithError!]! + # Additional Exams additionalExams: [AdditionalExam!]! # Primuss diff --git a/graph/query.resolvers.go b/graph/query.resolvers.go index 802e25d..b811b5c 100644 --- a/graph/query.resolvers.go +++ b/graph/query.resolvers.go @@ -37,66 +37,6 @@ func (r *queryResolver) SemesterConfig(ctx context.Context) (*model.SemesterConf return r.plexams.GetSemesterConfig(), nil } -// Teacher is the resolver for the teacher field. -func (r *queryResolver) Teacher(ctx context.Context, id int) (*model.Teacher, error) { - return r.plexams.GetTeacher(ctx, id) -} - -// Teachers is the resolver for the teachers field. -func (r *queryResolver) Teachers(ctx context.Context, fromZpa *bool) ([]*model.Teacher, error) { - return r.plexams.GetTeachers(ctx, fromZpa) -} - -// Invigilators is the resolver for the invigilators field. -func (r *queryResolver) Invigilators(ctx context.Context) ([]*model.ZPAInvigilator, error) { - return r.plexams.GetInvigilators(ctx) -} - -// Fk07programs is the resolver for the fk07programs field. -func (r *queryResolver) Fk07programs(ctx context.Context) ([]*model.FK07Program, error) { - return r.plexams.GetFk07programs(ctx) -} - -// ZpaExams is the resolver for the zpaExams field. -func (r *queryResolver) ZpaExams(ctx context.Context, fromZpa *bool) ([]*model.ZPAExam, error) { - return r.plexams.GetZPAExams(ctx, fromZpa) -} - -// ZpaExamsByType is the resolver for the zpaExamsByType field. -func (r *queryResolver) ZpaExamsByType(ctx context.Context) ([]*model.ZPAExamsForType, error) { - return r.plexams.GetZPAExamsGroupedByType(ctx) -} - -// ZpaExamsToPlan is the resolver for the zpaExamsToPlan field. -func (r *queryResolver) ZpaExamsToPlan(ctx context.Context) ([]*model.ZPAExam, error) { - return r.plexams.GetZpaExamsToPlan(ctx) -} - -// ZpaExamsNotToPlan is the resolver for the zpaExamsNotToPlan field. -func (r *queryResolver) ZpaExamsNotToPlan(ctx context.Context) ([]*model.ZPAExam, error) { - return r.plexams.GetZpaExamsNotToPlan(ctx) -} - -// ZpaExamsPlaningStatusUnknown is the resolver for the zpaExamsPlaningStatusUnknown field. -func (r *queryResolver) ZpaExamsPlaningStatusUnknown(ctx context.Context) ([]*model.ZPAExam, error) { - return r.plexams.ZpaExamsPlaningStatusUnknown(ctx) -} - -// ZpaExam is the resolver for the zpaExam field. -func (r *queryResolver) ZpaExam(ctx context.Context, ancode int) (*model.ZPAExam, error) { - return r.plexams.GetZpaExamByAncode(ctx, ancode) -} - -// ZpaAnCodes is the resolver for the zpaAnCodes field. -func (r *queryResolver) ZpaAnCodes(ctx context.Context) ([]*model.AnCode, error) { - return r.plexams.GetZpaAnCodes(ctx) -} - -// StudentRegsImportErrors is the resolver for the studentRegsImportErrors field. -func (r *queryResolver) StudentRegsImportErrors(ctx context.Context) ([]*model.RegWithError, error) { - return r.plexams.StudentRegsImportErrors(ctx) -} - // AdditionalExams is the resolver for the additionalExams field. func (r *queryResolver) AdditionalExams(ctx context.Context) ([]*model.AdditionalExam, error) { return r.plexams.AdditionalExams(ctx) diff --git a/graph/zpa.graphqls b/graph/zpa.graphqls index 905007b..43b272c 100644 --- a/graph/zpa.graphqls +++ b/graph/zpa.graphqls @@ -1,3 +1,18 @@ +extend type Query { + teacher(id: Int!): Teacher + teachers(fromZPA: Boolean): [Teacher!]! + invigilators: [ZPAInvigilator!]! + fk07programs: [FK07Program!]! + zpaExams(fromZPA: Boolean): [ZPAExam!]! + zpaExamsByType: [ZPAExamsForType!]! + zpaExamsToPlan: [ZPAExam!]! + zpaExamsNotToPlan: [ZPAExam!]! + zpaExamsPlaningStatusUnknown: [ZPAExam!]! + zpaExam(ancode: Int!): ZPAExam + zpaAnCodes: [AnCode] + studentRegsImportErrors: [RegWithError!]! +} + type ZPAExam { zpaID: Int! semester: String! @@ -40,7 +55,7 @@ type FK07Program { name: String! } -# TODO: remove me +# Deprecated: remove me type ZPAExamWithConstraints { zpaExam: ZPAExam! constraints: Constraints # == nil if no constraint diff --git a/graph/zpa.resolvers.go b/graph/zpa.resolvers.go new file mode 100644 index 0000000..ea2b54f --- /dev/null +++ b/graph/zpa.resolvers.go @@ -0,0 +1,71 @@ +package graph + +// This file will be automatically regenerated based on the schema, any resolver implementations +// will be copied through when generating and any unknown code will be moved to the end. +// Code generated by github.com/99designs/gqlgen version v0.17.34 + +import ( + "context" + + "github.com/obcode/plexams.go/graph/model" +) + +// Teacher is the resolver for the teacher field. +func (r *queryResolver) Teacher(ctx context.Context, id int) (*model.Teacher, error) { + return r.plexams.GetTeacher(ctx, id) +} + +// Teachers is the resolver for the teachers field. +func (r *queryResolver) Teachers(ctx context.Context, fromZpa *bool) ([]*model.Teacher, error) { + return r.plexams.GetTeachers(ctx, fromZpa) +} + +// Invigilators is the resolver for the invigilators field. +func (r *queryResolver) Invigilators(ctx context.Context) ([]*model.ZPAInvigilator, error) { + return r.plexams.GetInvigilators(ctx) +} + +// Fk07programs is the resolver for the fk07programs field. +func (r *queryResolver) Fk07programs(ctx context.Context) ([]*model.FK07Program, error) { + return r.plexams.GetFk07programs(ctx) +} + +// ZpaExams is the resolver for the zpaExams field. +func (r *queryResolver) ZpaExams(ctx context.Context, fromZpa *bool) ([]*model.ZPAExam, error) { + return r.plexams.GetZPAExams(ctx, fromZpa) +} + +// ZpaExamsByType is the resolver for the zpaExamsByType field. +func (r *queryResolver) ZpaExamsByType(ctx context.Context) ([]*model.ZPAExamsForType, error) { + return r.plexams.GetZPAExamsGroupedByType(ctx) +} + +// ZpaExamsToPlan is the resolver for the zpaExamsToPlan field. +func (r *queryResolver) ZpaExamsToPlan(ctx context.Context) ([]*model.ZPAExam, error) { + return r.plexams.GetZpaExamsToPlan(ctx) +} + +// ZpaExamsNotToPlan is the resolver for the zpaExamsNotToPlan field. +func (r *queryResolver) ZpaExamsNotToPlan(ctx context.Context) ([]*model.ZPAExam, error) { + return r.plexams.GetZpaExamsNotToPlan(ctx) +} + +// ZpaExamsPlaningStatusUnknown is the resolver for the zpaExamsPlaningStatusUnknown field. +func (r *queryResolver) ZpaExamsPlaningStatusUnknown(ctx context.Context) ([]*model.ZPAExam, error) { + return r.plexams.ZpaExamsPlaningStatusUnknown(ctx) +} + +// ZpaExam is the resolver for the zpaExam field. +func (r *queryResolver) ZpaExam(ctx context.Context, ancode int) (*model.ZPAExam, error) { + return r.plexams.GetZpaExamByAncode(ctx, ancode) +} + +// ZpaAnCodes is the resolver for the zpaAnCodes field. +func (r *queryResolver) ZpaAnCodes(ctx context.Context) ([]*model.AnCode, error) { + return r.plexams.GetZpaAnCodes(ctx) +} + +// StudentRegsImportErrors is the resolver for the studentRegsImportErrors field. +func (r *queryResolver) StudentRegsImportErrors(ctx context.Context) ([]*model.RegWithError, error) { + return r.plexams.StudentRegsImportErrors(ctx) +} diff --git a/plexams/exam.go b/plexams/exam.go index 98c4e96..f4f7a48 100644 --- a/plexams/exam.go +++ b/plexams/exam.go @@ -324,22 +324,27 @@ func (p *Plexams) RemovePrimussExam(ctx context.Context, input *model.PrimussExa // }, nil // } +// Deprecated: Remove me func (p *Plexams) ExamWithRegs(ctx context.Context, ancode int) (*model.ExamWithRegs, error) { return p.dbClient.ExamWithRegs(ctx, ancode) } +// Deprecated: Remove me func (p *Plexams) ExamsWithRegs(ctx context.Context) ([]*model.ExamWithRegs, error) { return p.dbClient.ExamsWithRegs(ctx) } +// Deprecated: Remove me func (p *Plexams) ExamGroup(ctx context.Context, examGroupCode int) (*model.ExamGroup, error) { return p.dbClient.ExamGroup(ctx, examGroupCode) } +// FIXME: Remove me func (p *Plexams) ExamGroups(ctx context.Context) ([]*model.ExamGroup, error) { return p.dbClient.ExamGroups(ctx) } +// Deprecated: Remove me func (p *Plexams) ConflictingGroupCodes(ctx context.Context, examGroupCode int) ([]*model.ExamGroupConflict, error) { examGroup, err := p.ExamGroup(ctx, examGroupCode) if err != nil { From 65e975e9dbab4d7fec2d6fd42e5a7427a3df77ee Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Sun, 6 Aug 2023 16:49:01 +0200 Subject: [PATCH 09/78] =?UTF-8?q?=F0=9F=9A=A7=20exam?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/primuss_conflicts.go | 11 +- db/primuss_studentregs.go | 20 +- graph/exam.graphqls | 14 +- graph/exam.resolvers.go | 18 +- graph/generated/generated.go | 748 +++++++++++++++++++++++++---------- graph/model/models_gen.go | 9 +- graph/primuss.graphqls | 9 +- graph/query.graphqls | 6 +- graph/query.resolvers.go | 10 - graph/studentregs.graphqls | 1 + plexams/exam.go | 58 +++ 11 files changed, 671 insertions(+), 233 deletions(-) diff --git a/db/primuss_conflicts.go b/db/primuss_conflicts.go index bb36fb6..425bdad 100644 --- a/db/primuss_conflicts.go +++ b/db/primuss_conflicts.go @@ -2,6 +2,7 @@ package db import ( "context" + "sort" "strconv" "github.com/obcode/plexams.go/graph/model" @@ -38,11 +39,17 @@ func (db *DB) GetPrimussConflictsForAncode(ctx context.Context, program string, return nil, err } + keys := make([]int, 0, len(conflicts.Conflicts)) + for k := range conflicts.Conflicts { + keys = append(keys, k) + } + sort.Ints(keys) + conflictsSlice := make([]*model.Conflict, 0) - for k, v := range conflicts.Conflicts { + for _, k := range keys { conflictsSlice = append(conflictsSlice, &model.Conflict{ AnCode: k, - NumberOfStuds: v, + NumberOfStuds: conflicts.Conflicts[k], }) } diff --git a/db/primuss_studentregs.go b/db/primuss_studentregs.go index 73d7e6e..b58f256 100644 --- a/db/primuss_studentregs.go +++ b/db/primuss_studentregs.go @@ -7,15 +7,31 @@ import ( "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo/options" ) func (db *DB) GetPrimussStudentRegsForProgrammAncode(ctx context.Context, program string, ancode int) ([]*model.StudentReg, error) { - studentRegs, err := db.GetPrimussStudentRegsPerAncode(ctx, program) + collection := db.getCollection(program, StudentRegs) + + findOptions := options.Find() + findOptions.SetSort(bson.D{{Key: "name", Value: 1}}) + + cur, err := collection.Find(ctx, bson.D{{Key: "AnCode", Value: ancode}}, findOptions) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Str("program", program).Msg("MongoDB Find (studentregs)") + return nil, err + } + defer cur.Close(ctx) + + var studentRegs []*model.StudentReg + + err = cur.All(ctx, &studentRegs) if err != nil { + log.Error().Err(err).Int("ancode", ancode).Str("program", program).Msg("cannot decode to studentregs") return nil, err } - return studentRegs[ancode], nil + return studentRegs, nil } func (db *DB) GetPrimussStudentRegsPerAncode(ctx context.Context, program string) (map[int][]*model.StudentReg, error) { diff --git a/graph/exam.graphqls b/graph/exam.graphqls index 967ba20..4887399 100644 --- a/graph/exam.graphqls +++ b/graph/exam.graphqls @@ -1,6 +1,9 @@ extend type Query { - exams: [Exam!]! + connectedExam(ancode: Int!): ConnectedExam + connectedExams: [ConnectedExam!]! + exam(ancode: Int!): Exam + exams: [Exam!]! } # Deprecated: remove me @@ -87,13 +90,20 @@ type ExternalExam { program: String! } +type ConnectedExam { + zpaExam: ZPAExam! + primussExams: [PrimussExam!]! + otherPrimussExams: [PrimussExam!]! + errors: [String!]! +} + type Exam { ancode: Int! zpaExam: ZPAExam externalExam: ExternalExam primussExams: [PrimussExam!]! studentRegs: [StudentRegsPerAncodeAndProgram!]! - conflicts: [ConflictPerProgram!]! + conflicts: [ConflictsPerProgramAncode!]! connectErrors: [String!]! constraints: Constraints nta: [NTAWithRegs!] diff --git a/graph/exam.resolvers.go b/graph/exam.resolvers.go index 961461f..16e9506 100644 --- a/graph/exam.resolvers.go +++ b/graph/exam.resolvers.go @@ -11,12 +11,22 @@ import ( "github.com/obcode/plexams.go/graph/model" ) -// Exams is the resolver for the exams field. -func (r *queryResolver) Exams(ctx context.Context) ([]*model.Exam, error) { - panic(fmt.Errorf("not implemented: Exams - exams")) +// ConnectedExam is the resolver for the connectedExam field. +func (r *queryResolver) ConnectedExam(ctx context.Context, ancode int) (*model.ConnectedExam, error) { + return r.plexams.GetConnectedExam(ctx, ancode) +} + +// ConnectedExams is the resolver for the connectedExams field. +func (r *queryResolver) ConnectedExams(ctx context.Context) ([]*model.ConnectedExam, error) { + return r.plexams.GetConnectedExams(ctx) } // Exam is the resolver for the exam field. func (r *queryResolver) Exam(ctx context.Context, ancode int) (*model.Exam, error) { - panic(fmt.Errorf("not implemented: Exam - exam")) + return r.plexams.Exam(ctx, ancode) +} + +// Exams is the resolver for the exams field. +func (r *queryResolver) Exams(ctx context.Context) ([]*model.Exam, error) { + panic(fmt.Errorf("not implemented: Exams - exams")) } diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 61125d6..c8f5de5 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -78,6 +78,12 @@ type ComplexityRoot struct { Module func(childComplexity int) int } + ConflictsPerProgramAncode struct { + Ancode func(childComplexity int) int + Conflicts func(childComplexity int) int + Program func(childComplexity int) int + } + ConnectedExam struct { Errors func(childComplexity int) int OtherPrimussExams func(childComplexity int) int @@ -501,6 +507,7 @@ type ComplexityRoot struct { } StudentRegsPerAncodeAndProgram struct { + Ancode func(childComplexity int) int Program func(childComplexity int) int StudentRegs func(childComplexity int) int } @@ -603,8 +610,6 @@ type QueryResolver interface { PrimussExam(ctx context.Context, program string, ancode int) (*model.PrimussExam, error) PrimussExamsForAnCode(ctx context.Context, ancode int) ([]*model.PrimussExam, error) StudentRegsForProgram(ctx context.Context, program string) ([]*model.StudentReg, error) - ConnectedExam(ctx context.Context, ancode int) (*model.ConnectedExam, error) - ConnectedExams(ctx context.Context) ([]*model.ConnectedExam, error) ExamWithRegs(ctx context.Context, ancode int) (*model.ExamWithRegs, error) ExamsWithRegs(ctx context.Context) ([]*model.ExamWithRegs, error) ConstraintForAncode(ctx context.Context, ancode int) (*model.Constraints, error) @@ -637,8 +642,10 @@ type QueryResolver interface { RoomsWithInvigilationsForSlot(ctx context.Context, day int, time int) (*model.InvigilationSlot, error) InvigilatorsForDay(ctx context.Context, day int) (*model.InvigilatorsForDay, error) DayOkForInvigilator(ctx context.Context, day int, invigilatorID int) (*bool, error) - Exams(ctx context.Context) ([]*model.Exam, error) + ConnectedExam(ctx context.Context, ancode int) (*model.ConnectedExam, error) + ConnectedExams(ctx context.Context) ([]*model.ConnectedExam, error) Exam(ctx context.Context, ancode int) (*model.Exam, error) + Exams(ctx context.Context) ([]*model.Exam, error) Teacher(ctx context.Context, id int) (*model.Teacher, error) Teachers(ctx context.Context, fromZpa *bool) ([]*model.Teacher, error) Invigilators(ctx context.Context) ([]*model.ZPAInvigilator, error) @@ -783,6 +790,27 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Conflicts.Module(childComplexity), true + case "ConflictsPerProgramAncode.ancode": + if e.complexity.ConflictsPerProgramAncode.Ancode == nil { + break + } + + return e.complexity.ConflictsPerProgramAncode.Ancode(childComplexity), true + + case "ConflictsPerProgramAncode.conflicts": + if e.complexity.ConflictsPerProgramAncode.Conflicts == nil { + break + } + + return e.complexity.ConflictsPerProgramAncode.Conflicts(childComplexity), true + + case "ConflictsPerProgramAncode.program": + if e.complexity.ConflictsPerProgramAncode.Program == nil { + break + } + + return e.complexity.ConflictsPerProgramAncode.Program(childComplexity), true + case "ConnectedExam.errors": if e.complexity.ConnectedExam.Errors == nil { break @@ -2954,6 +2982,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.StudentRegsPerAncode.PerProgram(childComplexity), true + case "StudentRegsPerAncodeAndProgram.ancode": + if e.complexity.StudentRegsPerAncodeAndProgram.Ancode == nil { + break + } + + return e.complexity.StudentRegsPerAncodeAndProgram.Ancode(childComplexity), true + case "StudentRegsPerAncodeAndProgram.program": if e.complexity.StudentRegsPerAncodeAndProgram.Program == nil { break @@ -3337,8 +3372,11 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er var sources = []*ast.Source{ {Name: "../exam.graphqls", Input: `extend type Query { - exams: [Exam!]! + connectedExam(ancode: Int!): ConnectedExam + connectedExams: [ConnectedExam!]! + exam(ancode: Int!): Exam + exams: [Exam!]! } # Deprecated: remove me @@ -3425,13 +3463,20 @@ type ExternalExam { program: String! } +type ConnectedExam { + zpaExam: ZPAExam! + primussExams: [PrimussExam!]! + otherPrimussExams: [PrimussExam!]! + errors: [String!]! +} + type Exam { ancode: Int! zpaExam: ZPAExam externalExam: ExternalExam primussExams: [PrimussExam!]! studentRegs: [StudentRegsPerAncodeAndProgram!]! - conflicts: [ConflictPerProgram!]! + conflicts: [ConflictsPerProgramAncode!]! connectErrors: [String!]! constraints: Constraints nta: [NTAWithRegs!] @@ -3699,11 +3744,10 @@ type ConflictPerProgram { conflicts: [Conflict!]! } -type ConnectedExam { - zpaExam: ZPAExam! - primussExams: [PrimussExam!]! - otherPrimussExams: [PrimussExam!]! - errors: [String!]! +type ConflictsPerProgramAncode { + program: String! + ancode: Int! + conflicts: Conflicts } `, BuiltIn: false}, {Name: "../query.graphqls", Input: `type Query { @@ -3712,8 +3756,6 @@ type ConnectedExam { allSemesterNames: [Semester!]! semester: Semester! semesterConfig: SemesterConfig! - # ZPA - # Additional Exams additionalExams: [AdditionalExam!]! # Primuss @@ -3721,9 +3763,7 @@ type ConnectedExam { primussExam(program: String!, ancode: Int!): PrimussExam! primussExamsForAnCode(ancode: Int!): [PrimussExam!] studentRegsForProgram(program: String!): [StudentReg!] - # Exams connected - connectedExam(ancode: Int!): ConnectedExam - connectedExams: [ConnectedExam!]! + # exam with regs examWithRegs(ancode: Int!): ExamWithRegs examsWithRegs: [ExamWithRegs!] @@ -3837,6 +3877,7 @@ type StudentRegsPerAncode { type StudentRegsPerAncodeAndProgram { program: String! + ancode: Int! studentRegs: [StudentReg!]! } @@ -5536,6 +5577,145 @@ func (ec *executionContext) fieldContext_Conflicts_conflicts(ctx context.Context return fc, nil } +func (ec *executionContext) _ConflictsPerProgramAncode_program(ctx context.Context, field graphql.CollectedField, obj *model.ConflictsPerProgramAncode) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ConflictsPerProgramAncode_program(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Program, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ConflictsPerProgramAncode_program(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ConflictsPerProgramAncode", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _ConflictsPerProgramAncode_ancode(ctx context.Context, field graphql.CollectedField, obj *model.ConflictsPerProgramAncode) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ConflictsPerProgramAncode_ancode(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Ancode, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ConflictsPerProgramAncode_ancode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ConflictsPerProgramAncode", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _ConflictsPerProgramAncode_conflicts(ctx context.Context, field graphql.CollectedField, obj *model.ConflictsPerProgramAncode) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ConflictsPerProgramAncode_conflicts(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Conflicts, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.Conflicts) + fc.Result = res + return ec.marshalOConflicts2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflicts(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ConflictsPerProgramAncode_conflicts(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ConflictsPerProgramAncode", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "ancode": + return ec.fieldContext_Conflicts_ancode(ctx, field) + case "module": + return ec.fieldContext_Conflicts_module(ctx, field) + case "mainExamer": + return ec.fieldContext_Conflicts_mainExamer(ctx, field) + case "conflicts": + return ec.fieldContext_Conflicts_conflicts(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Conflicts", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _ConnectedExam_zpaExam(ctx context.Context, field graphql.CollectedField, obj *model.ConnectedExam) (ret graphql.Marshaler) { fc, err := ec.fieldContext_ConnectedExam_zpaExam(ctx, field) if err != nil { @@ -6419,6 +6599,8 @@ func (ec *executionContext) fieldContext_Exam_studentRegs(ctx context.Context, f switch field.Name { case "program": return ec.fieldContext_StudentRegsPerAncodeAndProgram_program(ctx, field) + case "ancode": + return ec.fieldContext_StudentRegsPerAncodeAndProgram_ancode(ctx, field) case "studentRegs": return ec.fieldContext_StudentRegsPerAncodeAndProgram_studentRegs(ctx, field) } @@ -6454,9 +6636,9 @@ func (ec *executionContext) _Exam_conflicts(ctx context.Context, field graphql.C } return graphql.Null } - res := resTmp.([]*model.ConflictPerProgram) + res := resTmp.([]*model.ConflictsPerProgramAncode) fc.Result = res - return ec.marshalNConflictPerProgram2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictPerProgramᚄ(ctx, field.Selections, res) + return ec.marshalNConflictsPerProgramAncode2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictsPerProgramAncodeᚄ(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Exam_conflicts(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -6468,11 +6650,13 @@ func (ec *executionContext) fieldContext_Exam_conflicts(ctx context.Context, fie Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { case "program": - return ec.fieldContext_ConflictPerProgram_program(ctx, field) + return ec.fieldContext_ConflictsPerProgramAncode_program(ctx, field) + case "ancode": + return ec.fieldContext_ConflictsPerProgramAncode_ancode(ctx, field) case "conflicts": - return ec.fieldContext_ConflictPerProgram_conflicts(ctx, field) + return ec.fieldContext_ConflictsPerProgramAncode_conflicts(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ConflictPerProgram", field.Name) + return nil, fmt.Errorf("no field named %q was found under type ConflictsPerProgramAncode", field.Name) }, } return fc, nil @@ -8105,6 +8289,8 @@ func (ec *executionContext) fieldContext_ExamWithRegs_studentRegs(ctx context.Co switch field.Name { case "program": return ec.fieldContext_StudentRegsPerAncodeAndProgram_program(ctx, field) + case "ancode": + return ec.fieldContext_StudentRegsPerAncodeAndProgram_ancode(ctx, field) case "studentRegs": return ec.fieldContext_StudentRegsPerAncodeAndProgram_studentRegs(ctx, field) } @@ -13922,122 +14108,6 @@ func (ec *executionContext) fieldContext_Query_studentRegsForProgram(ctx context return fc, nil } -func (ec *executionContext) _Query_connectedExam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_connectedExam(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ConnectedExam(rctx, fc.Args["ancode"].(int)) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.(*model.ConnectedExam) - fc.Result = res - return ec.marshalOConnectedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExam(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_connectedExam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "zpaExam": - return ec.fieldContext_ConnectedExam_zpaExam(ctx, field) - case "primussExams": - return ec.fieldContext_ConnectedExam_primussExams(ctx, field) - case "otherPrimussExams": - return ec.fieldContext_ConnectedExam_otherPrimussExams(ctx, field) - case "errors": - return ec.fieldContext_ConnectedExam_errors(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type ConnectedExam", field.Name) - }, - } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_connectedExam_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } - return fc, nil -} - -func (ec *executionContext) _Query_connectedExams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_connectedExams(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ConnectedExams(rctx) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.([]*model.ConnectedExam) - fc.Result = res - return ec.marshalNConnectedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExamᚄ(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_connectedExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "zpaExam": - return ec.fieldContext_ConnectedExam_zpaExam(ctx, field) - case "primussExams": - return ec.fieldContext_ConnectedExam_primussExams(ctx, field) - case "otherPrimussExams": - return ec.fieldContext_ConnectedExam_otherPrimussExams(ctx, field) - case "errors": - return ec.fieldContext_ConnectedExam_errors(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type ConnectedExam", field.Name) - }, - } - return fc, nil -} - func (ec *executionContext) _Query_examWithRegs(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_examWithRegs(ctx, field) if err != nil { @@ -15835,8 +15905,8 @@ func (ec *executionContext) fieldContext_Query_dayOkForInvigilator(ctx context.C return fc, nil } -func (ec *executionContext) _Query_exams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_exams(ctx, field) +func (ec *executionContext) _Query_connectedExam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_connectedExam(ctx, field) if err != nil { return graphql.Null } @@ -15849,7 +15919,69 @@ func (ec *executionContext) _Query_exams(ctx context.Context, field graphql.Coll }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Exams(rctx) + return ec.resolvers.Query().ConnectedExam(rctx, fc.Args["ancode"].(int)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.ConnectedExam) + fc.Result = res + return ec.marshalOConnectedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExam(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_connectedExam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "zpaExam": + return ec.fieldContext_ConnectedExam_zpaExam(ctx, field) + case "primussExams": + return ec.fieldContext_ConnectedExam_primussExams(ctx, field) + case "otherPrimussExams": + return ec.fieldContext_ConnectedExam_otherPrimussExams(ctx, field) + case "errors": + return ec.fieldContext_ConnectedExam_errors(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ConnectedExam", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_connectedExam_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_connectedExams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_connectedExams(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().ConnectedExams(rctx) }) if err != nil { ec.Error(ctx, err) @@ -15861,12 +15993,63 @@ func (ec *executionContext) _Query_exams(ctx context.Context, field graphql.Coll } return graphql.Null } - res := resTmp.([]*model.Exam) + res := resTmp.([]*model.ConnectedExam) fc.Result = res - return ec.marshalNExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamᚄ(ctx, field.Selections, res) + return ec.marshalNConnectedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExamᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_exams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_connectedExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "zpaExam": + return ec.fieldContext_ConnectedExam_zpaExam(ctx, field) + case "primussExams": + return ec.fieldContext_ConnectedExam_primussExams(ctx, field) + case "otherPrimussExams": + return ec.fieldContext_ConnectedExam_otherPrimussExams(ctx, field) + case "errors": + return ec.fieldContext_ConnectedExam_errors(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ConnectedExam", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Query_exam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_exam(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Exam(rctx, fc.Args["ancode"].(int)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.Exam) + fc.Result = res + return ec.marshalOExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExam(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_exam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -15900,11 +16083,22 @@ func (ec *executionContext) fieldContext_Query_exams(ctx context.Context, field return nil, fmt.Errorf("no field named %q was found under type Exam", field.Name) }, } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_exam_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } return fc, nil } -func (ec *executionContext) _Query_exam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_exam(ctx, field) +func (ec *executionContext) _Query_exams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_exams(ctx, field) if err != nil { return graphql.Null } @@ -15917,21 +16111,24 @@ func (ec *executionContext) _Query_exam(ctx context.Context, field graphql.Colle }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Exam(rctx, fc.Args["ancode"].(int)) + return ec.resolvers.Query().Exams(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*model.Exam) + res := resTmp.([]*model.Exam) fc.Result = res - return ec.marshalOExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExam(ctx, field.Selections, res) + return ec.marshalNExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_exam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_exams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -15965,17 +16162,6 @@ func (ec *executionContext) fieldContext_Query_exam(ctx context.Context, field g return nil, fmt.Errorf("no field named %q was found under type Exam", field.Name) }, } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_exam_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } return fc, nil } @@ -19835,6 +20021,8 @@ func (ec *executionContext) fieldContext_StudentRegsPerAncode_perProgram(ctx con switch field.Name { case "program": return ec.fieldContext_StudentRegsPerAncodeAndProgram_program(ctx, field) + case "ancode": + return ec.fieldContext_StudentRegsPerAncodeAndProgram_ancode(ctx, field) case "studentRegs": return ec.fieldContext_StudentRegsPerAncodeAndProgram_studentRegs(ctx, field) } @@ -19888,6 +20076,50 @@ func (ec *executionContext) fieldContext_StudentRegsPerAncodeAndProgram_program( return fc, nil } +func (ec *executionContext) _StudentRegsPerAncodeAndProgram_ancode(ctx context.Context, field graphql.CollectedField, obj *model.StudentRegsPerAncodeAndProgram) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_StudentRegsPerAncodeAndProgram_ancode(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Ancode, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_StudentRegsPerAncodeAndProgram_ancode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "StudentRegsPerAncodeAndProgram", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _StudentRegsPerAncodeAndProgram_studentRegs(ctx context.Context, field graphql.CollectedField, obj *model.StudentRegsPerAncodeAndProgram) (ret graphql.Marshaler) { fc, err := ec.fieldContext_StudentRegsPerAncodeAndProgram_studentRegs(ctx, field) if err != nil { @@ -23998,6 +24230,52 @@ func (ec *executionContext) _Conflicts(ctx context.Context, sel ast.SelectionSet return out } +var conflictsPerProgramAncodeImplementors = []string{"ConflictsPerProgramAncode"} + +func (ec *executionContext) _ConflictsPerProgramAncode(ctx context.Context, sel ast.SelectionSet, obj *model.ConflictsPerProgramAncode) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, conflictsPerProgramAncodeImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("ConflictsPerProgramAncode") + case "program": + out.Values[i] = ec._ConflictsPerProgramAncode_program(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "ancode": + out.Values[i] = ec._ConflictsPerProgramAncode_ancode(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "conflicts": + out.Values[i] = ec._ConflictsPerProgramAncode_conflicts(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var connectedExamImplementors = []string{"ConnectedExam"} func (ec *executionContext) _ConnectedExam(ctx context.Context, sel ast.SelectionSet, obj *model.ConnectedExam) graphql.Marshaler { @@ -26057,47 +26335,6 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "connectedExam": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_connectedExam(ctx, field) - return res - } - - rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, - func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - } - - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "connectedExams": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_connectedExams(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } - return res - } - - rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, - func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "examWithRegs": field := field @@ -26725,7 +26962,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "exams": + case "connectedExam": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -26734,7 +26971,26 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_exams(ctx, field) + res = ec._Query_connectedExam(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "connectedExams": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_connectedExams(ctx, field) if res == graphql.Null { atomic.AddUint32(&fs.Invalids, 1) } @@ -26765,6 +27021,28 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "exams": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_exams(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "teacher": field := field @@ -27943,6 +28221,11 @@ func (ec *executionContext) _StudentRegsPerAncodeAndProgram(ctx context.Context, if out.Values[i] == graphql.Null { out.Invalids++ } + case "ancode": + out.Values[i] = ec._StudentRegsPerAncodeAndProgram_ancode(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } case "studentRegs": out.Values[i] = ec._StudentRegsPerAncodeAndProgram_studentRegs(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -28947,6 +29230,60 @@ func (ec *executionContext) marshalNConflicts2ᚖgithubᚗcomᚋobcodeᚋplexams return ec._Conflicts(ctx, sel, v) } +func (ec *executionContext) marshalNConflictsPerProgramAncode2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictsPerProgramAncodeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ConflictsPerProgramAncode) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNConflictsPerProgramAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictsPerProgramAncode(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNConflictsPerProgramAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictsPerProgramAncode(ctx context.Context, sel ast.SelectionSet, v *model.ConflictsPerProgramAncode) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._ConflictsPerProgramAncode(ctx, sel, v) +} + func (ec *executionContext) marshalNConnectedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ConnectedExam) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup @@ -31021,6 +31358,13 @@ func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast return res } +func (ec *executionContext) marshalOConflicts2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflicts(ctx context.Context, sel ast.SelectionSet, v *model.Conflicts) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._Conflicts(ctx, sel, v) +} + func (ec *executionContext) marshalOConnectedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExam(ctx context.Context, sel ast.SelectionSet, v *model.ConnectedExam) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index a4ac6ba..b46b1fd 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -34,6 +34,12 @@ type ConflictPerProgram struct { Conflicts []*Conflict `json:"conflicts"` } +type ConflictsPerProgramAncode struct { + Program string `json:"program"` + Ancode int `json:"ancode"` + Conflicts *Conflicts `json:"conflicts,omitempty"` +} + type ConnectedExam struct { ZpaExam *ZPAExam `json:"zpaExam"` PrimussExams []*PrimussExam `json:"primussExams"` @@ -59,7 +65,7 @@ type Exam struct { ExternalExam *ExternalExam `json:"externalExam,omitempty"` PrimussExams []*PrimussExam `json:"primussExams"` StudentRegs []*StudentRegsPerAncodeAndProgram `json:"studentRegs"` - Conflicts []*ConflictPerProgram `json:"conflicts"` + Conflicts []*ConflictsPerProgramAncode `json:"conflicts"` ConnectErrors []string `json:"connectErrors"` Constraints *Constraints `json:"constraints,omitempty"` Nta []*NTAWithRegs `json:"nta,omitempty"` @@ -340,6 +346,7 @@ type StudentRegsPerAncode struct { type StudentRegsPerAncodeAndProgram struct { Program string `json:"program"` + Ancode int `json:"ancode"` StudentRegs []*StudentReg `json:"studentRegs"` } diff --git a/graph/primuss.graphqls b/graph/primuss.graphqls index ff539e2..fe33885 100644 --- a/graph/primuss.graphqls +++ b/graph/primuss.graphqls @@ -45,9 +45,8 @@ type ConflictPerProgram { conflicts: [Conflict!]! } -type ConnectedExam { - zpaExam: ZPAExam! - primussExams: [PrimussExam!]! - otherPrimussExams: [PrimussExam!]! - errors: [String!]! +type ConflictsPerProgramAncode { + program: String! + ancode: Int! + conflicts: Conflicts } diff --git a/graph/query.graphqls b/graph/query.graphqls index e6242b5..1665bd3 100644 --- a/graph/query.graphqls +++ b/graph/query.graphqls @@ -4,8 +4,6 @@ type Query { allSemesterNames: [Semester!]! semester: Semester! semesterConfig: SemesterConfig! - # ZPA - # Additional Exams additionalExams: [AdditionalExam!]! # Primuss @@ -13,9 +11,7 @@ type Query { primussExam(program: String!, ancode: Int!): PrimussExam! primussExamsForAnCode(ancode: Int!): [PrimussExam!] studentRegsForProgram(program: String!): [StudentReg!] - # Exams connected - connectedExam(ancode: Int!): ConnectedExam - connectedExams: [ConnectedExam!]! + # exam with regs examWithRegs(ancode: Int!): ExamWithRegs examsWithRegs: [ExamWithRegs!] diff --git a/graph/query.resolvers.go b/graph/query.resolvers.go index b811b5c..5fcdcb2 100644 --- a/graph/query.resolvers.go +++ b/graph/query.resolvers.go @@ -62,16 +62,6 @@ func (r *queryResolver) StudentRegsForProgram(ctx context.Context, program strin return r.plexams.StudentRegsForProgram(ctx, program) } -// ConnectedExam is the resolver for the connectedExam field. -func (r *queryResolver) ConnectedExam(ctx context.Context, ancode int) (*model.ConnectedExam, error) { - return r.plexams.GetConnectedExam(ctx, ancode) -} - -// ConnectedExams is the resolver for the connectedExams field. -func (r *queryResolver) ConnectedExams(ctx context.Context) ([]*model.ConnectedExam, error) { - return r.plexams.GetConnectedExams(ctx) -} - // ExamWithRegs is the resolver for the examWithRegs field. func (r *queryResolver) ExamWithRegs(ctx context.Context, ancode int) (*model.ExamWithRegs, error) { return r.plexams.ExamWithRegs(ctx, ancode) diff --git a/graph/studentregs.graphqls b/graph/studentregs.graphqls index a0caf1e..2cf105e 100644 --- a/graph/studentregs.graphqls +++ b/graph/studentregs.graphqls @@ -10,6 +10,7 @@ type StudentRegsPerAncode { type StudentRegsPerAncodeAndProgram { program: String! + ancode: Int! studentRegs: [StudentReg!]! } diff --git a/plexams/exam.go b/plexams/exam.go index f4f7a48..7973175 100644 --- a/plexams/exam.go +++ b/plexams/exam.go @@ -149,6 +149,64 @@ func (p *Plexams) PrepareConnectedExam(ancode int) error { return nil } +func (p *Plexams) Exam(ctx context.Context, ancode int) (*model.Exam, error) { + connectedExam, err := p.GetConnectedExam(ctx, ancode) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("cannot get connected exam") + return nil, err + } + // TODO: maybe external exam? + + studentRegs := make([]*model.StudentRegsPerAncodeAndProgram, 0, len(connectedExam.PrimussExams)) + // TODO: only conflicts of planned primussExams? + conflicts := make([]*model.ConflictsPerProgramAncode, 0, len(connectedExam.PrimussExams)) + + for _, primussExam := range connectedExam.PrimussExams { + studentRegsProgram, err := p.dbClient.GetPrimussStudentRegsForProgrammAncode(ctx, primussExam.Program, primussExam.AnCode) + if err != nil { + log.Error().Err(err).Int("ancode", primussExam.AnCode).Str("program", primussExam.Program).Msg("cannot get studentregs") + return nil, err + } + studentRegs = append(studentRegs, &model.StudentRegsPerAncodeAndProgram{ + Program: primussExam.Program, + Ancode: primussExam.AnCode, + StudentRegs: studentRegsProgram, + }) + + conflictsProgram, err := p.dbClient.GetPrimussConflictsForAncode(ctx, primussExam.Program, primussExam.AnCode) + if err != nil { + log.Error().Err(err).Int("ancode", primussExam.AnCode).Str("program", primussExam.Program).Msg("cannot get studentregs") + return nil, err + } + conflicts = append(conflicts, &model.ConflictsPerProgramAncode{ + Program: primussExam.Program, + Ancode: primussExam.AnCode, + Conflicts: conflictsProgram, + }) + } + + constraints, err := p.ConstraintForAncode(ctx, ancode) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("cannot get constraints for ancode") + } + + // TODO: Maybe make plausibility checks? + + return &model.Exam{ + Ancode: ancode, + ZpaExam: connectedExam.ZpaExam, + ExternalExam: nil, + PrimussExams: connectedExam.PrimussExams, + StudentRegs: studentRegs, + Conflicts: conflicts, + ConnectErrors: connectedExam.Errors, + Constraints: constraints, + Nta: nil, + Slot: nil, + Rooms: nil, + }, nil +} + // func (p *Plexams) PrepareExams(ctx context.Context, inputs []*model.PrimussExamInput) (bool, error) { // if p.dbClient.ExamsAlreadyPrepared(ctx) { // oks := true From dd8b73f359137a2c332ccef72d2b8845e275d2ca Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Mon, 7 Aug 2023 19:47:48 +0200 Subject: [PATCH 10/78] studentByMtknr, studentsByName --- db/studentregs.go | 123 ++++++++++ graph/generated/generated.go | 432 ++++++++++++++++++++++++++++++++- graph/model/models_gen.go | 2 + graph/studentregs.graphqls | 7 + graph/studentregs.resolvers.go | 21 ++ plexams/studentRegs.go | 8 + 6 files changed, 592 insertions(+), 1 deletion(-) create mode 100644 graph/studentregs.resolvers.go diff --git a/db/studentregs.go b/db/studentregs.go index 062957a..6eb7f31 100644 --- a/db/studentregs.go +++ b/db/studentregs.go @@ -2,10 +2,13 @@ package db import ( "context" + "sort" + set "github.com/deckarep/golang-set/v2" "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/bson/primitive" ) func (db *DB) GetStudentRegsPerAncodePlanned(ctx context.Context) ([]*model.StudentRegsPerAncode, error) { @@ -84,3 +87,123 @@ func (db *DB) StudentRegsPerStudentAll(ctx context.Context) ([]*model.StudentReg return studentRegs, nil } + +func (db *DB) StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, error) { + collectionNames, err := db.studentRegsCollectionNames(ctx) + + if err != nil { + log.Error().Err(err).Msg("cannot get student regs collections") + return nil, err + } + + var student *model.Student + + for _, collectionName := range collectionNames { + log.Debug().Str("collection", collectionName).Str("mtkntr", mtknr). + Msg("searching for student in collection") + + collection := db.Client.Database(db.databaseName).Collection(collectionName) + + cur, err := collection.Find(ctx, bson.D{{Key: "MTKNR", Value: mtknr}}) + if err != nil { + log.Error().Err(err).Str("collection", collectionName).Str("mtkntr", mtknr). + Msg("error while searching for student in collection") + } + defer cur.Close(ctx) + + var results []*model.StudentReg + + err = cur.All(ctx, &results) + if err != nil { + log.Error().Err(err).Str("collection", collectionName).Str("mtkntr", mtknr). + Msg("error while decoding student from collection") + } + + if len(results) > 0 { + log.Debug().Interface("regs", results).Str("collection", collectionName).Str("mtkntr", mtknr). + Msg("found regs for student") + + if student != nil { + log.Error().Str("collection", collectionName).Str("mtkntr", mtknr). + Msg("found student in more than one programs") + + } + + regs := make([]int, 0, len(results)) + + for _, res := range results { + regs = append(regs, res.AnCode) + } + + sort.Ints(regs) + + student = &model.Student{ + Mtknr: mtknr, + Program: results[0].Program, + Group: results[0].Group, + Name: results[0].Name, + Regs: regs, + Nta: nil, + } + + } + + } + + return student, nil +} + +func (db *DB) StudentsByName(ctx context.Context, regex string) ([]*model.Student, error) { + collectionNames, err := db.studentRegsCollectionNames(ctx) + + if err != nil { + log.Error().Err(err).Msg("cannot get student regs collections") + return nil, err + } + + studentMtknrs := set.NewSet[string]() + + for _, collectionName := range collectionNames { + collection := db.Client.Database(db.databaseName).Collection(collectionName) + + cur, err := collection.Find(ctx, bson.D{{Key: "name", Value: bson.D{ + primitive.E{Key: "$regex", + Value: primitive.Regex{Pattern: regex}, + }}}}) + if err != nil { + log.Error().Err(err).Str("collection", collectionName).Str("regex", regex). + Msg("error while searching for student in collection") + } + defer cur.Close(ctx) + + for cur.Next(ctx) { + mtknr := cur.Current.Lookup("MTKNR").StringValue() + studentMtknrs.Add(mtknr) + } + } + + students := make([]*model.Student, 0, studentMtknrs.Cardinality()) + + for _, mtknr := range studentMtknrs.ToSlice() { + student, err := db.StudentByMtknr(ctx, mtknr) + if err != nil { + log.Error().Err(err).Str("mtknr", mtknr).Msg("error while trying to get student") + } else { + students = append(students, student) + } + } + + return students, nil +} + +func (db *DB) studentRegsCollectionNames(ctx context.Context) ([]string, error) { + return db.Client.Database(db.databaseName).ListCollectionNames(ctx, + bson.D{primitive.E{ + Key: "name", + Value: bson.D{ + primitive.E{Key: "$regex", + Value: primitive.Regex{Pattern: "studentregs_..$"}, + }, + }, + }}) +} diff --git a/graph/generated/generated.go b/graph/generated/generated.go index c8f5de5..c06fe22 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -380,8 +380,10 @@ type ComplexityRoot struct { RoomsWithInvigilationsForSlot func(childComplexity int, day int, time int) int Semester func(childComplexity int) int SemesterConfig func(childComplexity int) int + StudentByMtknr func(childComplexity int, mtknr string) int StudentRegsForProgram func(childComplexity int, program string) int StudentRegsImportErrors func(childComplexity int) int + StudentsByName func(childComplexity int, regex string) int Teacher func(childComplexity int, id int) int Teachers func(childComplexity int, fromZpa *bool) int Workflow func(childComplexity int) int @@ -489,7 +491,9 @@ type ComplexityRoot struct { Group func(childComplexity int) int Mtknr func(childComplexity int) int Name func(childComplexity int) int + Nta func(childComplexity int) int Program func(childComplexity int) int + Regs func(childComplexity int) int } StudentReg struct { @@ -646,6 +650,8 @@ type QueryResolver interface { ConnectedExams(ctx context.Context) ([]*model.ConnectedExam, error) Exam(ctx context.Context, ancode int) (*model.Exam, error) Exams(ctx context.Context) ([]*model.Exam, error) + StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, error) + StudentsByName(ctx context.Context, regex string) ([]*model.Student, error) Teacher(ctx context.Context, id int) (*model.Teacher, error) Teachers(ctx context.Context, fromZpa *bool) ([]*model.Teacher, error) Invigilators(ctx context.Context) ([]*model.ZPAInvigilator, error) @@ -2425,6 +2431,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.SemesterConfig(childComplexity), true + case "Query.studentByMtknr": + if e.complexity.Query.StudentByMtknr == nil { + break + } + + args, err := ec.field_Query_studentByMtknr_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.StudentByMtknr(childComplexity, args["mtknr"].(string)), true + case "Query.studentRegsForProgram": if e.complexity.Query.StudentRegsForProgram == nil { break @@ -2444,6 +2462,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.StudentRegsImportErrors(childComplexity), true + case "Query.studentsByName": + if e.complexity.Query.StudentsByName == nil { + break + } + + args, err := ec.field_Query_studentsByName_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.StudentsByName(childComplexity, args["regex"].(string)), true + case "Query.teacher": if e.complexity.Query.Teacher == nil { break @@ -2919,6 +2949,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Student.Name(childComplexity), true + case "Student.nta": + if e.complexity.Student.Nta == nil { + break + } + + return e.complexity.Student.Nta(childComplexity), true + case "Student.program": if e.complexity.Student.Program == nil { break @@ -2926,6 +2963,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Student.Program(childComplexity), true + case "Student.regs": + if e.complexity.Student.Regs == nil { + break + } + + return e.complexity.Student.Regs(childComplexity), true + case "StudentReg.ancode": if e.complexity.StudentReg.AnCode == nil { break @@ -3865,7 +3909,12 @@ type AnCode { ancode: Int! } `, BuiltIn: false}, - {Name: "../studentregs.graphqls", Input: `type StudentRegsPerStudent { + {Name: "../studentregs.graphqls", Input: `extend type Query { + studentByMtknr(mtknr: String!): Student + studentsByName(regex: String!): [Student!] +} + +type StudentRegsPerStudent { student: Student! ancodes: [Int!]! } @@ -3886,6 +3935,8 @@ type Student { program: String! group: String! name: String! + regs: [Int!]! + nta: NTA } `, BuiltIn: false}, {Name: "../workflow.graphqls", Input: `scalar Time @@ -4748,6 +4799,21 @@ func (ec *executionContext) field_Query_roomsWithInvigilationsForSlot_args(ctx c return args, nil } +func (ec *executionContext) field_Query_studentByMtknr_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["mtknr"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("mtknr")) + arg0, err = ec.unmarshalNString2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["mtknr"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query_studentRegsForProgram_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -4763,6 +4829,21 @@ func (ec *executionContext) field_Query_studentRegsForProgram_args(ctx context.C return args, nil } +func (ec *executionContext) field_Query_studentsByName_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["regex"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("regex")) + arg0, err = ec.unmarshalNString2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["regex"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query_teacher_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -16165,6 +16246,138 @@ func (ec *executionContext) fieldContext_Query_exams(ctx context.Context, field return fc, nil } +func (ec *executionContext) _Query_studentByMtknr(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_studentByMtknr(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().StudentByMtknr(rctx, fc.Args["mtknr"].(string)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.Student) + fc.Result = res + return ec.marshalOStudent2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudent(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_studentByMtknr(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "mtknr": + return ec.fieldContext_Student_mtknr(ctx, field) + case "program": + return ec.fieldContext_Student_program(ctx, field) + case "group": + return ec.fieldContext_Student_group(ctx, field) + case "name": + return ec.fieldContext_Student_name(ctx, field) + case "regs": + return ec.fieldContext_Student_regs(ctx, field) + case "nta": + return ec.fieldContext_Student_nta(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Student", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_studentByMtknr_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_studentsByName(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_studentsByName(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().StudentsByName(rctx, fc.Args["regex"].(string)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.Student) + fc.Result = res + return ec.marshalOStudent2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_studentsByName(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "mtknr": + return ec.fieldContext_Student_mtknr(ctx, field) + case "program": + return ec.fieldContext_Student_program(ctx, field) + case "group": + return ec.fieldContext_Student_group(ctx, field) + case "name": + return ec.fieldContext_Student_name(ctx, field) + case "regs": + return ec.fieldContext_Student_regs(ctx, field) + case "nta": + return ec.fieldContext_Student_nta(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Student", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_studentsByName_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Query_teacher(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_teacher(ctx, field) if err != nil { @@ -19672,6 +19885,113 @@ func (ec *executionContext) fieldContext_Student_name(ctx context.Context, field return fc, nil } +func (ec *executionContext) _Student_regs(ctx context.Context, field graphql.CollectedField, obj *model.Student) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Student_regs(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Regs, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]int) + fc.Result = res + return ec.marshalNInt2ᚕintᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Student_regs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Student", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Student_nta(ctx context.Context, field graphql.CollectedField, obj *model.Student) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Student_nta(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Nta, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.NTA) + fc.Result = res + return ec.marshalONTA2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTA(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Student_nta(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Student", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext_NTA_name(ctx, field) + case "mtknr": + return ec.fieldContext_NTA_mtknr(ctx, field) + case "compensation": + return ec.fieldContext_NTA_compensation(ctx, field) + case "deltaDurationPercent": + return ec.fieldContext_NTA_deltaDurationPercent(ctx, field) + case "needsRoomAlone": + return ec.fieldContext_NTA_needsRoomAlone(ctx, field) + case "program": + return ec.fieldContext_NTA_program(ctx, field) + case "from": + return ec.fieldContext_NTA_from(ctx, field) + case "until": + return ec.fieldContext_NTA_until(ctx, field) + case "lastSemester": + return ec.fieldContext_NTA_lastSemester(ctx, field) + case "exams": + return ec.fieldContext_NTA_exams(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type NTA", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _StudentReg_mtknr(ctx context.Context, field graphql.CollectedField, obj *model.StudentReg) (ret graphql.Marshaler) { fc, err := ec.fieldContext_StudentReg_mtknr(ctx, field) if err != nil { @@ -20225,6 +20545,10 @@ func (ec *executionContext) fieldContext_StudentRegsPerStudent_student(ctx conte return ec.fieldContext_Student_group(ctx, field) case "name": return ec.fieldContext_Student_name(ctx, field) + case "regs": + return ec.fieldContext_Student_regs(ctx, field) + case "nta": + return ec.fieldContext_Student_nta(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Student", field.Name) }, @@ -27043,6 +27367,44 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "studentByMtknr": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_studentByMtknr(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "studentsByName": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_studentsByName(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "teacher": field := field @@ -28074,6 +28436,13 @@ func (ec *executionContext) _Student(ctx context.Context, sel ast.SelectionSet, if out.Values[i] == graphql.Null { out.Invalids++ } + case "regs": + out.Values[i] = ec._Student_regs(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "nta": + out.Values[i] = ec._Student_nta(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -32006,6 +32375,13 @@ func (ec *executionContext) marshalONTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗ return ret } +func (ec *executionContext) marshalONTA2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTA(ctx context.Context, sel ast.SelectionSet, v *model.NTA) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._NTA(ctx, sel, v) +} + func (ec *executionContext) marshalONTAWithRegs2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.NTAWithRegs) graphql.Marshaler { if v == nil { return graphql.Null @@ -32542,6 +32918,60 @@ func (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel as return res } +func (ec *executionContext) marshalOStudent2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Student) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNStudent2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudent(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalOStudent2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudent(ctx context.Context, sel ast.SelectionSet, v *model.Student) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._Student(ctx, sel, v) +} + func (ec *executionContext) marshalOStudentReg2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentRegᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.StudentReg) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index b46b1fd..732ae1c 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -337,6 +337,8 @@ type Student struct { Program string `json:"program"` Group string `json:"group"` Name string `json:"name"` + Regs []int `json:"regs"` + Nta *NTA `json:"nta,omitempty"` } type StudentRegsPerAncode struct { diff --git a/graph/studentregs.graphqls b/graph/studentregs.graphqls index 2cf105e..d2aa60d 100644 --- a/graph/studentregs.graphqls +++ b/graph/studentregs.graphqls @@ -1,3 +1,8 @@ +extend type Query { + studentByMtknr(mtknr: String!): Student + studentsByName(regex: String!): [Student!] +} + type StudentRegsPerStudent { student: Student! ancodes: [Int!]! @@ -19,4 +24,6 @@ type Student { program: String! group: String! name: String! + regs: [Int!]! + nta: NTA } diff --git a/graph/studentregs.resolvers.go b/graph/studentregs.resolvers.go new file mode 100644 index 0000000..88d1ffd --- /dev/null +++ b/graph/studentregs.resolvers.go @@ -0,0 +1,21 @@ +package graph + +// This file will be automatically regenerated based on the schema, any resolver implementations +// will be copied through when generating and any unknown code will be moved to the end. +// Code generated by github.com/99designs/gqlgen version v0.17.34 + +import ( + "context" + + "github.com/obcode/plexams.go/graph/model" +) + +// StudentByMtknr is the resolver for the studentByMtknr field. +func (r *queryResolver) StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, error) { + return r.plexams.StudentByMtknr(ctx, mtknr) +} + +// StudentsByName is the resolver for the studentsByName field. +func (r *queryResolver) StudentsByName(ctx context.Context, regex string) ([]*model.Student, error) { + return r.plexams.StudentsByName(ctx, regex) +} diff --git a/plexams/studentRegs.go b/plexams/studentRegs.go index 5c06346..bb3688a 100644 --- a/plexams/studentRegs.go +++ b/plexams/studentRegs.go @@ -112,3 +112,11 @@ func (p *Plexams) GetExamsForStudent(name string) error { return nil } + +func (p *Plexams) StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, error) { + return p.dbClient.StudentByMtknr(ctx, mtknr) +} + +func (p *Plexams) StudentsByName(ctx context.Context, regex string) ([]*model.Student, error) { + return p.dbClient.StudentsByName(ctx, regex) +} From 9efe19836b8bb02955d0988cf5bec493667f5ed0 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Mon, 7 Aug 2023 22:23:56 +0200 Subject: [PATCH 11/78] students in exam --- cmd/prepare.go | 6 +- db/nta.go | 26 ++++++- db/studentregs.go | 30 +++++-- graph/exam.graphqls | 3 +- graph/generated/generated.go | 138 ++++++++++++++++++++++++++------- graph/model/models_gen.go | 23 +++--- graph/studentregs.resolvers.go | 2 +- plexams/exam.go | 28 ++++--- plexams/nta.go | 2 +- plexams/studentRegs.go | 42 +++++++++- 10 files changed, 233 insertions(+), 67 deletions(-) diff --git a/cmd/prepare.go b/cmd/prepare.go index 9513c20..6d97be2 100644 --- a/cmd/prepare.go +++ b/cmd/prepare.go @@ -75,13 +75,13 @@ var ( os.Exit(1) } - case "studentregs": + case "studentregs": // Deprecated: no longer needed err := plexams.PrepareStudentRegs() if err != nil { os.Exit(1) } - case "exams-with-regs": + case "exams-with-regs": // Deprecated: no longer needed err := plexams.PrepareExamsWithRegs() if err != nil { os.Exit(1) @@ -118,7 +118,7 @@ var ( os.Exit(1) } - case "nta": + case "nta": // Deprecated: no longer needed? err := plexams.PrepareNta() if err != nil { os.Exit(1) diff --git a/db/nta.go b/db/nta.go index beb52a5..7be2949 100644 --- a/db/nta.go +++ b/db/nta.go @@ -6,6 +6,7 @@ import ( "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) @@ -21,6 +22,25 @@ func (db *DB) AddNta(ctx context.Context, nta *model.NTA) (*model.NTA, error) { return nta, nil // FIXME: return NTA from DB? } +func (db *DB) Nta(ctx context.Context, mtknr string) (*model.NTA, error) { + collection := db.Client.Database("plexams").Collection(collectionNameNTAs) + + res := collection.FindOne(ctx, bson.D{{Key: "mtknr", Value: mtknr}}) + if res.Err() == mongo.ErrNoDocuments { + return nil, nil + } + + var nta *model.NTA + + err := res.Decode(&nta) + if err != nil { + log.Error().Err(res.Err()).Str("mtknr", mtknr).Msg("error while finding nta") + return nil, err + } + + return nta, nil +} + func (db *DB) Ntas(ctx context.Context) ([]*model.NTA, error) { collection := db.Client.Database("plexams").Collection(collectionNameNTAs) @@ -44,6 +64,7 @@ func (db *DB) Ntas(ctx context.Context) ([]*model.NTA, error) { return ntas, nil } +// Deprecated: remove me func (db *DB) NtasWithRegs(ctx context.Context) ([]*model.NTAWithRegs, error) { collection := db.Client.Database(db.databaseName).Collection(collectionNameNTAs) @@ -67,7 +88,8 @@ func (db *DB) NtasWithRegs(ctx context.Context) ([]*model.NTAWithRegs, error) { return ntas, nil } -func (db *DB) Nta(ctx context.Context, mtknr string) (*model.NTAWithRegs, error) { +// Deprecated: remove me +func (db *DB) NtaWithRegs(ctx context.Context, mtknr string) (*model.NTAWithRegs, error) { collection := db.Client.Database(db.databaseName).Collection(collectionNameNTAs) var nta model.NTAWithRegs @@ -85,6 +107,7 @@ func (db *DB) Nta(ctx context.Context, mtknr string) (*model.NTAWithRegs, error) return &nta, nil } +// Deprecated: remove me func (db *DB) SaveSemesterNTAs(ctx context.Context, ntaWithRegs []*model.NTAWithRegs) error { collection := db.Client.Database(db.databaseName).Collection(collectionNameNTAs) @@ -119,6 +142,7 @@ func (db *DB) SaveSemesterNTAs(ctx context.Context, ntaWithRegs []*model.NTAWith return nil } +// TODO: when to call? func (db *DB) setCurrentSemesterOnNTA(ctx context.Context, mtknr string) error { collection := db.Client.Database("plexams").Collection(collectionNameNTAs) diff --git a/db/studentregs.go b/db/studentregs.go index 6eb7f31..8032c84 100644 --- a/db/studentregs.go +++ b/db/studentregs.go @@ -88,7 +88,7 @@ func (db *DB) StudentRegsPerStudentAll(ctx context.Context) ([]*model.StudentReg return studentRegs, nil } -func (db *DB) StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, error) { +func (db *DB) StudentByMtknr(ctx context.Context, mtknr string, ntas map[string]*model.NTA) (*model.Student, error) { collectionNames, err := db.studentRegsCollectionNames(ctx) if err != nil { @@ -123,13 +123,20 @@ func (db *DB) StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, log.Debug().Interface("regs", results).Str("collection", collectionName).Str("mtkntr", mtknr). Msg("found regs for student") - if student != nil { + var regs []int + + if student != nil && (student.Program != results[0].Program || + student.Group != results[0].Group || + student.Name != results[0].Name) { log.Error().Str("collection", collectionName).Str("mtkntr", mtknr). Msg("found student in more than one programs") - } - regs := make([]int, 0, len(results)) + if student != nil { + regs = student.Regs + } else { + regs = make([]int, 0, len(results)) + } for _, res := range results { regs = append(regs, res.AnCode) @@ -137,13 +144,24 @@ func (db *DB) StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, sort.Ints(regs) + var nta *model.NTA + + if ntas == nil { + nta, err = db.Nta(ctx, mtknr) + if err != nil { + log.Error().Err(err).Str("mtknr", mtknr).Msg("error while checking nta") + } + } else { + nta = ntas[mtknr] + } + student = &model.Student{ Mtknr: mtknr, Program: results[0].Program, Group: results[0].Group, Name: results[0].Name, Regs: regs, - Nta: nil, + Nta: nta, } } @@ -185,7 +203,7 @@ func (db *DB) StudentsByName(ctx context.Context, regex string) ([]*model.Studen students := make([]*model.Student, 0, studentMtknrs.Cardinality()) for _, mtknr := range studentMtknrs.ToSlice() { - student, err := db.StudentByMtknr(ctx, mtknr) + student, err := db.StudentByMtknr(ctx, mtknr, nil) if err != nil { log.Error().Err(err).Str("mtknr", mtknr).Msg("error while trying to get student") } else { diff --git a/graph/exam.graphqls b/graph/exam.graphqls index 4887399..345bf54 100644 --- a/graph/exam.graphqls +++ b/graph/exam.graphqls @@ -106,7 +106,8 @@ type Exam { conflicts: [ConflictsPerProgramAncode!]! connectErrors: [String!]! constraints: Constraints - nta: [NTAWithRegs!] + regularStudents: [Student!] + ntaStudents: [Student!] slot: Slot rooms: [RoomForExam!] } diff --git a/graph/generated/generated.go b/graph/generated/generated.go index c06fe22..cd3237a 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -104,17 +104,18 @@ type ComplexityRoot struct { } Exam struct { - Ancode func(childComplexity int) int - Conflicts func(childComplexity int) int - ConnectErrors func(childComplexity int) int - Constraints func(childComplexity int) int - ExternalExam func(childComplexity int) int - Nta func(childComplexity int) int - PrimussExams func(childComplexity int) int - Rooms func(childComplexity int) int - Slot func(childComplexity int) int - StudentRegs func(childComplexity int) int - ZpaExam func(childComplexity int) int + Ancode func(childComplexity int) int + Conflicts func(childComplexity int) int + ConnectErrors func(childComplexity int) int + Constraints func(childComplexity int) int + ExternalExam func(childComplexity int) int + NtaStudents func(childComplexity int) int + PrimussExams func(childComplexity int) int + RegularStudents func(childComplexity int) int + Rooms func(childComplexity int) int + Slot func(childComplexity int) int + StudentRegs func(childComplexity int) int + ZpaExam func(childComplexity int) int } ExamDay struct { @@ -943,12 +944,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Exam.ExternalExam(childComplexity), true - case "Exam.nta": - if e.complexity.Exam.Nta == nil { + case "Exam.ntaStudents": + if e.complexity.Exam.NtaStudents == nil { break } - return e.complexity.Exam.Nta(childComplexity), true + return e.complexity.Exam.NtaStudents(childComplexity), true case "Exam.primussExams": if e.complexity.Exam.PrimussExams == nil { @@ -957,6 +958,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Exam.PrimussExams(childComplexity), true + case "Exam.regularStudents": + if e.complexity.Exam.RegularStudents == nil { + break + } + + return e.complexity.Exam.RegularStudents(childComplexity), true + case "Exam.rooms": if e.complexity.Exam.Rooms == nil { break @@ -3523,7 +3531,8 @@ type Exam { conflicts: [ConflictsPerProgramAncode!]! connectErrors: [String!]! constraints: Constraints - nta: [NTAWithRegs!] + regularStudents: [Student!] + ntaStudents: [Student!] slot: Slot rooms: [RoomForExam!] } @@ -6848,8 +6857,8 @@ func (ec *executionContext) fieldContext_Exam_constraints(ctx context.Context, f return fc, nil } -func (ec *executionContext) _Exam_nta(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Exam_nta(ctx, field) +func (ec *executionContext) _Exam_regularStudents(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Exam_regularStudents(ctx, field) if err != nil { return graphql.Null } @@ -6862,7 +6871,7 @@ func (ec *executionContext) _Exam_nta(ctx context.Context, field graphql.Collect }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Nta, nil + return obj.RegularStudents, nil }) if err != nil { ec.Error(ctx, err) @@ -6871,12 +6880,12 @@ func (ec *executionContext) _Exam_nta(ctx context.Context, field graphql.Collect if resTmp == nil { return graphql.Null } - res := resTmp.([]*model.NTAWithRegs) + res := resTmp.([]*model.Student) fc.Result = res - return ec.marshalONTAWithRegs2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsᚄ(ctx, field.Selections, res) + return ec.marshalOStudent2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Exam_nta(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Exam_regularStudents(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Exam", Field: field, @@ -6884,12 +6893,75 @@ func (ec *executionContext) fieldContext_Exam_nta(ctx context.Context, field gra IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { + case "mtknr": + return ec.fieldContext_Student_mtknr(ctx, field) + case "program": + return ec.fieldContext_Student_program(ctx, field) + case "group": + return ec.fieldContext_Student_group(ctx, field) + case "name": + return ec.fieldContext_Student_name(ctx, field) + case "regs": + return ec.fieldContext_Student_regs(ctx, field) case "nta": - return ec.fieldContext_NTAWithRegs_nta(ctx, field) + return ec.fieldContext_Student_nta(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Student", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Exam_ntaStudents(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Exam_ntaStudents(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.NtaStudents, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.Student) + fc.Result = res + return ec.marshalOStudent2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Exam_ntaStudents(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Exam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "mtknr": + return ec.fieldContext_Student_mtknr(ctx, field) + case "program": + return ec.fieldContext_Student_program(ctx, field) + case "group": + return ec.fieldContext_Student_group(ctx, field) + case "name": + return ec.fieldContext_Student_name(ctx, field) case "regs": - return ec.fieldContext_NTAWithRegs_regs(ctx, field) + return ec.fieldContext_Student_regs(ctx, field) + case "nta": + return ec.fieldContext_Student_nta(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type NTAWithRegs", field.Name) + return nil, fmt.Errorf("no field named %q was found under type Student", field.Name) }, } return fc, nil @@ -16154,8 +16226,10 @@ func (ec *executionContext) fieldContext_Query_exam(ctx context.Context, field g return ec.fieldContext_Exam_connectErrors(ctx, field) case "constraints": return ec.fieldContext_Exam_constraints(ctx, field) - case "nta": - return ec.fieldContext_Exam_nta(ctx, field) + case "regularStudents": + return ec.fieldContext_Exam_regularStudents(ctx, field) + case "ntaStudents": + return ec.fieldContext_Exam_ntaStudents(ctx, field) case "slot": return ec.fieldContext_Exam_slot(ctx, field) case "rooms": @@ -16233,8 +16307,10 @@ func (ec *executionContext) fieldContext_Query_exams(ctx context.Context, field return ec.fieldContext_Exam_connectErrors(ctx, field) case "constraints": return ec.fieldContext_Exam_constraints(ctx, field) - case "nta": - return ec.fieldContext_Exam_nta(ctx, field) + case "regularStudents": + return ec.fieldContext_Exam_regularStudents(ctx, field) + case "ntaStudents": + return ec.fieldContext_Exam_ntaStudents(ctx, field) case "slot": return ec.fieldContext_Exam_slot(ctx, field) case "rooms": @@ -24757,8 +24833,10 @@ func (ec *executionContext) _Exam(ctx context.Context, sel ast.SelectionSet, obj } case "constraints": out.Values[i] = ec._Exam_constraints(ctx, field, obj) - case "nta": - out.Values[i] = ec._Exam_nta(ctx, field, obj) + case "regularStudents": + out.Values[i] = ec._Exam_regularStudents(ctx, field, obj) + case "ntaStudents": + out.Values[i] = ec._Exam_ntaStudents(ctx, field, obj) case "slot": out.Values[i] = ec._Exam_slot(ctx, field, obj) case "rooms": diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index 732ae1c..ec1a5e4 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -60,17 +60,18 @@ type Constraints struct { } type Exam struct { - Ancode int `json:"ancode"` - ZpaExam *ZPAExam `json:"zpaExam,omitempty"` - ExternalExam *ExternalExam `json:"externalExam,omitempty"` - PrimussExams []*PrimussExam `json:"primussExams"` - StudentRegs []*StudentRegsPerAncodeAndProgram `json:"studentRegs"` - Conflicts []*ConflictsPerProgramAncode `json:"conflicts"` - ConnectErrors []string `json:"connectErrors"` - Constraints *Constraints `json:"constraints,omitempty"` - Nta []*NTAWithRegs `json:"nta,omitempty"` - Slot *Slot `json:"slot,omitempty"` - Rooms []*RoomForExam `json:"rooms,omitempty"` + Ancode int `json:"ancode"` + ZpaExam *ZPAExam `json:"zpaExam,omitempty"` + ExternalExam *ExternalExam `json:"externalExam,omitempty"` + PrimussExams []*PrimussExam `json:"primussExams"` + StudentRegs []*StudentRegsPerAncodeAndProgram `json:"studentRegs"` + Conflicts []*ConflictsPerProgramAncode `json:"conflicts"` + ConnectErrors []string `json:"connectErrors"` + Constraints *Constraints `json:"constraints,omitempty"` + RegularStudents []*Student `json:"regularStudents,omitempty"` + NtaStudents []*Student `json:"ntaStudents,omitempty"` + Slot *Slot `json:"slot,omitempty"` + Rooms []*RoomForExam `json:"rooms,omitempty"` } type ExamDay struct { diff --git a/graph/studentregs.resolvers.go b/graph/studentregs.resolvers.go index 88d1ffd..28e9fb3 100644 --- a/graph/studentregs.resolvers.go +++ b/graph/studentregs.resolvers.go @@ -12,7 +12,7 @@ import ( // StudentByMtknr is the resolver for the studentByMtknr field. func (r *queryResolver) StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, error) { - return r.plexams.StudentByMtknr(ctx, mtknr) + return r.plexams.StudentByMtknr(ctx, mtknr, nil) } // StudentsByName is the resolver for the studentsByName field. diff --git a/plexams/exam.go b/plexams/exam.go index 7973175..c4cc9bc 100644 --- a/plexams/exam.go +++ b/plexams/exam.go @@ -190,20 +190,26 @@ func (p *Plexams) Exam(ctx context.Context, ancode int) (*model.Exam, error) { log.Error().Err(err).Int("ancode", ancode).Msg("cannot get constraints for ancode") } + regularStuds, ntaStuds, err := p.StudentsFromStudentRegs(ctx, studentRegs) + if err != nil { + log.Error().Err(err).Msg("cannot get students from student regs") + } + // TODO: Maybe make plausibility checks? return &model.Exam{ - Ancode: ancode, - ZpaExam: connectedExam.ZpaExam, - ExternalExam: nil, - PrimussExams: connectedExam.PrimussExams, - StudentRegs: studentRegs, - Conflicts: conflicts, - ConnectErrors: connectedExam.Errors, - Constraints: constraints, - Nta: nil, - Slot: nil, - Rooms: nil, + Ancode: ancode, + ZpaExam: connectedExam.ZpaExam, + ExternalExam: nil, + PrimussExams: connectedExam.PrimussExams, + StudentRegs: studentRegs, + Conflicts: conflicts, + ConnectErrors: connectedExam.Errors, + Constraints: constraints, + RegularStudents: regularStuds, + NtaStudents: ntaStuds, + Slot: nil, + Rooms: nil, }, nil } diff --git a/plexams/nta.go b/plexams/nta.go index 20ed554..a05cedf 100644 --- a/plexams/nta.go +++ b/plexams/nta.go @@ -21,7 +21,7 @@ func (p *Plexams) NtasWithRegs(ctx context.Context) ([]*model.NTAWithRegs, error } func (p *Plexams) Nta(ctx context.Context, mtknr string) (*model.NTAWithRegs, error) { - return p.dbClient.Nta(ctx, mtknr) + return p.dbClient.NtaWithRegs(ctx, mtknr) } func (p *Plexams) PrepareNta() error { diff --git a/plexams/studentRegs.go b/plexams/studentRegs.go index bb3688a..dc96341 100644 --- a/plexams/studentRegs.go +++ b/plexams/studentRegs.go @@ -113,10 +113,48 @@ func (p *Plexams) GetExamsForStudent(name string) error { return nil } -func (p *Plexams) StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, error) { - return p.dbClient.StudentByMtknr(ctx, mtknr) +func (p *Plexams) StudentByMtknr(ctx context.Context, mtknr string, ntas map[string]*model.NTA) (*model.Student, error) { + return p.dbClient.StudentByMtknr(ctx, mtknr, ntas) } func (p *Plexams) StudentsByName(ctx context.Context, regex string) ([]*model.Student, error) { return p.dbClient.StudentsByName(ctx, regex) } + +func (p *Plexams) StudentsFromStudentRegs(ctx context.Context, studentRegs []*model.StudentRegsPerAncodeAndProgram) ( + regularStuds, ntaStuds []*model.Student, err error) { + regularStuds = make([]*model.Student, 0) + ntaStuds = make([]*model.Student, 0) + + ntaSlice, err := p.Ntas(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get ntas") + return nil, nil, err + } + + ntas := make(map[string]*model.NTA) + for _, nta := range ntaSlice { + ntas[nta.Mtknr] = nta + } + + for _, program := range studentRegs { + for _, studentReg := range program.StudentRegs { + student, err := p.StudentByMtknr(ctx, studentReg.Mtknr, ntas) + if err != nil { + log.Error().Err(err).Str("mtknr", studentReg.Mtknr).Msg("error while trying to get student") + return nil, nil, err + } + if student.Nta != nil { + ntaStuds = append(ntaStuds, student) + } else { + regularStuds = append(regularStuds, student) + } + } + } + + if len(ntaStuds) == 0 { + ntaStuds = nil + } + + return regularStuds, ntaStuds, nil +} From eebfba462a026814cd8ea292d6ed869bc1f5694a Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Mon, 7 Aug 2023 22:26:42 +0200 Subject: [PATCH 12/78] make golangci-lint happy --- cmd/prepare.go | 3 +++ db/nta.go | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cmd/prepare.go b/cmd/prepare.go index 6d97be2..f390180 100644 --- a/cmd/prepare.go +++ b/cmd/prepare.go @@ -16,6 +16,9 @@ var ( Long: `Prepare collections. connected-exams --- prepare connected exams --- step 1 connect-exam ancode program --- connect an unconnected exam --- step 1,5 + cached-exam ancode + + studentregs --- regs per exam & regs per student --- step 2 nta --- find NTAs for semester --- step 3 exams-with-regs --- exams from connected-exams and studentregs --- step 4 diff --git a/db/nta.go b/db/nta.go index 7be2949..d696194 100644 --- a/db/nta.go +++ b/db/nta.go @@ -64,7 +64,7 @@ func (db *DB) Ntas(ctx context.Context) ([]*model.NTA, error) { return ntas, nil } -// Deprecated: remove me +// // Deprecated: remove me func (db *DB) NtasWithRegs(ctx context.Context) ([]*model.NTAWithRegs, error) { collection := db.Client.Database(db.databaseName).Collection(collectionNameNTAs) @@ -88,7 +88,7 @@ func (db *DB) NtasWithRegs(ctx context.Context) ([]*model.NTAWithRegs, error) { return ntas, nil } -// Deprecated: remove me +// // Deprecated: remove me func (db *DB) NtaWithRegs(ctx context.Context, mtknr string) (*model.NTAWithRegs, error) { collection := db.Client.Database(db.databaseName).Collection(collectionNameNTAs) @@ -107,7 +107,7 @@ func (db *DB) NtaWithRegs(ctx context.Context, mtknr string) (*model.NTAWithRegs return &nta, nil } -// Deprecated: remove me +// // Deprecated: remove me func (db *DB) SaveSemesterNTAs(ctx context.Context, ntaWithRegs []*model.NTAWithRegs) error { collection := db.Client.Database(db.databaseName).Collection(collectionNameNTAs) From c4431b81db3626ec819e3554456dd3d80ec30daa Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Mon, 7 Aug 2023 23:02:48 +0200 Subject: [PATCH 13/78] cached-exam --- cmd/prepare.go | 15 +++++++++++++++ db/collection.go | 2 ++ db/exam.go | 26 ++++++++++++++++++++++++++ graph/exam.resolvers.go | 6 +++++- plexams/exam.go | 18 ++++++++++++++++++ 5 files changed, 66 insertions(+), 1 deletion(-) diff --git a/cmd/prepare.go b/cmd/prepare.go index f390180..840f2d0 100644 --- a/cmd/prepare.go +++ b/cmd/prepare.go @@ -78,6 +78,21 @@ var ( os.Exit(1) } + case "cached-exam": + if len(args) < 2 { + log.Fatal("need ancode") + } + ancode, err := strconv.Atoi(args[1]) + if err != nil { + fmt.Printf("cannot use %s as ancode", args[1]) + os.Exit(1) + } + + err = plexams.CacheExam(ancode) + if err != nil { + os.Exit(1) + } + case "studentregs": // Deprecated: no longer needed err := plexams.PrepareStudentRegs() if err != nil { diff --git a/db/collection.go b/db/collection.go index 5903699..30e80c6 100644 --- a/db/collection.go +++ b/db/collection.go @@ -30,6 +30,8 @@ const ( collectionExamsInPlan = "exams_in_plan" + collectionCachedExams = "cached_exams" + collectionRooms = "rooms" collectionRoomsPlanned = "rooms_planned" collectionRoomsForExams = "rooms_for_exams" diff --git a/db/exam.go b/db/exam.go index c12da40..fa7019c 100644 --- a/db/exam.go +++ b/db/exam.go @@ -6,9 +6,35 @@ import ( "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) +func (db *DB) CacheExam(ctx context.Context, exam *model.Exam) error { + collection := db.Client.Database(db.databaseName).Collection(collectionCachedExams) + + res, err := collection.ReplaceOne(ctx, bson.D{{Key: "ancode", Value: exam.Ancode}}, exam, options.Replace().SetUpsert(true)) + + log.Debug().Interface("res", res).Msg("replaced") + + return err +} + +func (db *DB) CachedExam(ctx context.Context, ancode int) (*model.Exam, error) { + collection := db.Client.Database(db.databaseName).Collection(collectionCachedExams) + + res := collection.FindOne(ctx, bson.D{{Key: "ancode", Value: ancode}}) + if res.Err() == mongo.ErrNoDocuments { + return nil, nil + } + + var exam model.Exam + + err := res.Decode(&exam) + + return &exam, err +} + func (db *DB) AddAdditionalExam(ctx context.Context, exam model.AdditionalExamInput) (bool, error) { collection := db.Client.Database(db.databaseName).Collection(collectionNameAdditionalExams) _, err := collection.InsertOne(ctx, exam) diff --git a/graph/exam.resolvers.go b/graph/exam.resolvers.go index 16e9506..792b706 100644 --- a/graph/exam.resolvers.go +++ b/graph/exam.resolvers.go @@ -23,7 +23,11 @@ func (r *queryResolver) ConnectedExams(ctx context.Context) ([]*model.ConnectedE // Exam is the resolver for the exam field. func (r *queryResolver) Exam(ctx context.Context, ancode int) (*model.Exam, error) { - return r.plexams.Exam(ctx, ancode) + exam, err := r.plexams.CachedExam(ctx, ancode) + if err != nil || exam == nil { + return r.plexams.Exam(ctx, ancode) + } + return exam, err } // Exams is the resolver for the exams field. diff --git a/plexams/exam.go b/plexams/exam.go index c4cc9bc..a37abc6 100644 --- a/plexams/exam.go +++ b/plexams/exam.go @@ -213,6 +213,24 @@ func (p *Plexams) Exam(ctx context.Context, ancode int) (*model.Exam, error) { }, nil } +func (p *Plexams) CacheExam(ancode int) error { + ctx := context.Background() + exam, err := p.Exam(ctx, ancode) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("error while getting exam") + return err + } + if exam.ZpaExam != nil { + log.Debug().Int("ancode", exam.Ancode).Str("module", exam.ZpaExam.Module).Str("examer", exam.ZpaExam.MainExamer). + Msg("caching exam") + } + return p.dbClient.CacheExam(ctx, exam) +} + +func (p *Plexams) CachedExam(ctx context.Context, ancode int) (*model.Exam, error) { + return p.dbClient.CachedExam(ctx, ancode) +} + // func (p *Plexams) PrepareExams(ctx context.Context, inputs []*model.PrimussExamInput) (bool, error) { // if p.dbClient.ExamsAlreadyPrepared(ctx) { // oks := true From 5cbe44473b9ad146b65d7465595c5ede4f8952a3 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Sun, 13 Aug 2023 09:10:07 +0200 Subject: [PATCH 14/78] cache exams --- README.md | 9 ++++ cmd/cache.go | 65 ++++++++++++++++++++++ cmd/prepare.go | 16 ------ cmd/root.go | 2 +- db/exam.go | 26 --------- db/exam_cache.go | 61 +++++++++++++++++++++ db/nta.go | 4 +- go.mod | 5 ++ go.sum | 13 +++++ graph/exam.resolvers.go | 3 +- plexams/exam.go | 25 +++------ plexams/exam_cache.go | 116 ++++++++++++++++++++++++++++++++++++++++ plexams/plexams.go | 7 ++- 13 files changed, 283 insertions(+), 69 deletions(-) create mode 100644 cmd/cache.go create mode 100644 db/exam_cache.go create mode 100644 plexams/exam_cache.go diff --git a/README.md b/README.md index 8b2aa14..d78cef0 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,15 @@ erDiagram ## Ablauf +```mermaid +flowchart TD + ZPA_Exams --> Connected_Exams + Primuss_Exams --> Connected_Exams + Connected_Exams --> Exams/Cached_Exams + Primuss_StudentRegs/Conflicts --> Exams/Cached_Exams + NTAs --> Exams/Cached_Exams +``` + 1. Prüfungen aus dem ZPA importieren (bei Änderungen erneut): ``` diff --git a/cmd/cache.go b/cmd/cache.go new file mode 100644 index 0000000..e1d3c31 --- /dev/null +++ b/cmd/cache.go @@ -0,0 +1,65 @@ +package cmd + +import ( + "fmt" + "log" + "os" + "strconv" + + "github.com/logrusorgru/aurora" + "github.com/spf13/cobra" +) + +var ( + cacheCmd = &cobra.Command{ + Use: "cache", + Short: "cache [subcommand]", + Long: `cache collections. + exam + exams + rm-exams +`, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + plexams := initPlexamsConfig() + switch args[0] { + + case "exam": + if len(args) < 2 { + log.Fatal("need ancode") + } + ancode, err := strconv.Atoi(args[1]) + if err != nil { + fmt.Printf("cannot use %s as ancode", args[1]) + os.Exit(1) + } + + err = plexams.CacheExam(ancode) + if err != nil { + os.Exit(1) + } + + case "exams": + err := plexams.CacheExams() + if err != nil { + os.Exit(1) + } + + case "rm-exams": + err := plexams.RmCacheExams() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + fmt.Println(aurora.Green("successfully removed the cached exams")) + + default: + fmt.Println("cache called with unknown sub command") + } + }, + } +) + +func init() { + rootCmd.AddCommand(cacheCmd) +} diff --git a/cmd/prepare.go b/cmd/prepare.go index 840f2d0..37684f5 100644 --- a/cmd/prepare.go +++ b/cmd/prepare.go @@ -16,7 +16,6 @@ var ( Long: `Prepare collections. connected-exams --- prepare connected exams --- step 1 connect-exam ancode program --- connect an unconnected exam --- step 1,5 - cached-exam ancode studentregs --- regs per exam & regs per student --- step 2 @@ -78,21 +77,6 @@ var ( os.Exit(1) } - case "cached-exam": - if len(args) < 2 { - log.Fatal("need ancode") - } - ancode, err := strconv.Atoi(args[1]) - if err != nil { - fmt.Printf("cannot use %s as ancode", args[1]) - os.Exit(1) - } - - err = plexams.CacheExam(ancode) - if err != nil { - os.Exit(1) - } - case "studentregs": // Deprecated: no longer needed err := plexams.PrepareStudentRegs() if err != nil { diff --git a/cmd/root.go b/cmd/root.go index 8a6248f..8f19db9 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -110,7 +110,7 @@ func initPlexamsConfig() *plexams.Plexams { panic(fmt.Errorf("fatal cannot create mongo client: %w", err)) } - plexams.PrintSemester() + plexams.PrintInfo() return plexams } diff --git a/db/exam.go b/db/exam.go index fa7019c..c12da40 100644 --- a/db/exam.go +++ b/db/exam.go @@ -6,35 +6,9 @@ import ( "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) -func (db *DB) CacheExam(ctx context.Context, exam *model.Exam) error { - collection := db.Client.Database(db.databaseName).Collection(collectionCachedExams) - - res, err := collection.ReplaceOne(ctx, bson.D{{Key: "ancode", Value: exam.Ancode}}, exam, options.Replace().SetUpsert(true)) - - log.Debug().Interface("res", res).Msg("replaced") - - return err -} - -func (db *DB) CachedExam(ctx context.Context, ancode int) (*model.Exam, error) { - collection := db.Client.Database(db.databaseName).Collection(collectionCachedExams) - - res := collection.FindOne(ctx, bson.D{{Key: "ancode", Value: ancode}}) - if res.Err() == mongo.ErrNoDocuments { - return nil, nil - } - - var exam model.Exam - - err := res.Decode(&exam) - - return &exam, err -} - func (db *DB) AddAdditionalExam(ctx context.Context, exam model.AdditionalExamInput) (bool, error) { collection := db.Client.Database(db.databaseName).Collection(collectionNameAdditionalExams) _, err := collection.InsertOne(ctx, exam) diff --git a/db/exam_cache.go b/db/exam_cache.go new file mode 100644 index 0000000..2de4c10 --- /dev/null +++ b/db/exam_cache.go @@ -0,0 +1,61 @@ +package db + +import ( + "context" + + "github.com/obcode/plexams.go/graph/model" + "github.com/rs/zerolog/log" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" +) + +func (db *DB) CacheExam(ctx context.Context, exam *model.Exam) error { + collection := db.Client.Database(db.databaseName).Collection(collectionCachedExams) + + res, err := collection.ReplaceOne(ctx, bson.D{{Key: "ancode", Value: exam.Ancode}}, exam, options.Replace().SetUpsert(true)) + + log.Debug().Interface("res", res).Msg("replaced") + + return err +} + +func (db *DB) CachedExam(ctx context.Context, ancode int) (*model.Exam, error) { + collection := db.Client.Database(db.databaseName).Collection(collectionCachedExams) + + res := collection.FindOne(ctx, bson.D{{Key: "ancode", Value: ancode}}) + if res.Err() == mongo.ErrNoDocuments { + return nil, nil + } + + var exam model.Exam + + err := res.Decode(&exam) + + return &exam, err +} + +func (db *DB) CachedExams(ctx context.Context) ([]*model.Exam, error) { + collection := db.Client.Database(db.databaseName).Collection(collectionCachedExams) + + cur, err := collection.Find(ctx, bson.M{}) + if err != nil { + log.Error().Err(err).Msg("cannot get cached exams") + return nil, err + } + defer cur.Close(ctx) + + exams := make([]*model.Exam, 0) + + err = cur.All(ctx, &exams) + if err != nil { + log.Error().Err(err).Msg("cannot decode cached exams") + return nil, err + } + + return exams, nil +} + +func (db *DB) RmCacheExams(ctx context.Context) error { + return db.Client.Database(db.databaseName).Collection(collectionCachedExams).Drop(ctx) +} diff --git a/db/nta.go b/db/nta.go index d696194..df96f2c 100644 --- a/db/nta.go +++ b/db/nta.go @@ -133,7 +133,7 @@ func (db *DB) SaveSemesterNTAs(ctx context.Context, ntaWithRegs []*model.NTAWith } for _, nta := range ntaWithRegs { - err := db.setCurrentSemesterOnNTA(ctx, nta.Nta.Mtknr) + err := db.SetCurrentSemesterOnNTA(ctx, nta.Nta.Mtknr) if err != nil { return err } @@ -143,7 +143,7 @@ func (db *DB) SaveSemesterNTAs(ctx context.Context, ntaWithRegs []*model.NTAWith } // TODO: when to call? -func (db *DB) setCurrentSemesterOnNTA(ctx context.Context, mtknr string) error { +func (db *DB) SetCurrentSemesterOnNTA(ctx context.Context, mtknr string) error { collection := db.Client.Database("plexams").Collection(collectionNameNTAs) filter := bson.D{{Key: "mtknr", Value: mtknr}} diff --git a/go.mod b/go.mod index 6696740..d97a89a 100644 --- a/go.mod +++ b/go.mod @@ -9,11 +9,13 @@ require ( github.com/gookit/color v1.5.3 github.com/johnfercher/maroto v0.42.0 github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible + github.com/logrusorgru/aurora v2.0.3+incompatible github.com/mitchellh/go-homedir v1.1.0 github.com/rs/cors v1.9.0 github.com/rs/zerolog v1.29.1 github.com/spf13/cobra v1.7.0 github.com/spf13/viper v1.16.0 + github.com/theckman/yacspin v0.13.12 github.com/vektah/gqlparser/v2 v2.5.6 go.mongodb.org/mongo-driver v1.12.0 ) @@ -22,6 +24,7 @@ require ( github.com/agnivade/levenshtein v1.1.1 // indirect github.com/boombuler/barcode v1.0.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/fatih/color v1.13.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.3.0 // indirect @@ -34,9 +37,11 @@ require ( github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/montanaflynn/stats v0.6.6 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/rivo/uniseg v0.2.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245 // indirect github.com/spf13/afero v1.9.5 // indirect diff --git a/go.sum b/go.sum index a345627..93c726e 100644 --- a/go.sum +++ b/go.sum @@ -73,6 +73,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= @@ -176,15 +178,21 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= +github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -204,6 +212,8 @@ github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qR github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= @@ -246,6 +256,8 @@ github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gt github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/theckman/yacspin v0.13.12 h1:CdZ57+n0U6JMuh2xqjnjRq5Haj6v1ner2djtLQRzJr4= +github.com/theckman/yacspin v0.13.12/go.mod h1:Rd2+oG2LmQi5f3zC3yeZAOl245z8QOvrH4OPOJNZxLg= github.com/urfave/cli/v2 v2.25.5 h1:d0NIAyhh5shGscroL7ek/Ya9QYQE0KNabJgiUinIQkc= github.com/urfave/cli/v2 v2.25.5/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/vektah/gqlparser/v2 v2.5.6 h1:Ou14T0N1s191eRMZ1gARVqohcbe1e8FrcONScsq8cRU= @@ -393,6 +405,7 @@ golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/graph/exam.resolvers.go b/graph/exam.resolvers.go index 792b706..3d302bd 100644 --- a/graph/exam.resolvers.go +++ b/graph/exam.resolvers.go @@ -6,7 +6,6 @@ package graph import ( "context" - "fmt" "github.com/obcode/plexams.go/graph/model" ) @@ -32,5 +31,5 @@ func (r *queryResolver) Exam(ctx context.Context, ancode int) (*model.Exam, erro // Exams is the resolver for the exams field. func (r *queryResolver) Exams(ctx context.Context) ([]*model.Exam, error) { - panic(fmt.Errorf("not implemented: Exams - exams")) + return r.plexams.CachedExams(ctx) } diff --git a/plexams/exam.go b/plexams/exam.go index a37abc6..a6988a2 100644 --- a/plexams/exam.go +++ b/plexams/exam.go @@ -195,6 +195,13 @@ func (p *Plexams) Exam(ctx context.Context, ancode int) (*model.Exam, error) { log.Error().Err(err).Msg("cannot get students from student regs") } + for _, nta := range ntaStuds { + err := p.dbClient.SetCurrentSemesterOnNTA(ctx, nta.Mtknr) + if err != nil { + log.Error().Err(err).Interface("nta", nta).Msg("cannot set current semester on nta") + } + } + // TODO: Maybe make plausibility checks? return &model.Exam{ @@ -213,24 +220,6 @@ func (p *Plexams) Exam(ctx context.Context, ancode int) (*model.Exam, error) { }, nil } -func (p *Plexams) CacheExam(ancode int) error { - ctx := context.Background() - exam, err := p.Exam(ctx, ancode) - if err != nil { - log.Error().Err(err).Int("ancode", ancode).Msg("error while getting exam") - return err - } - if exam.ZpaExam != nil { - log.Debug().Int("ancode", exam.Ancode).Str("module", exam.ZpaExam.Module).Str("examer", exam.ZpaExam.MainExamer). - Msg("caching exam") - } - return p.dbClient.CacheExam(ctx, exam) -} - -func (p *Plexams) CachedExam(ctx context.Context, ancode int) (*model.Exam, error) { - return p.dbClient.CachedExam(ctx, ancode) -} - // func (p *Plexams) PrepareExams(ctx context.Context, inputs []*model.PrimussExamInput) (bool, error) { // if p.dbClient.ExamsAlreadyPrepared(ctx) { // oks := true diff --git a/plexams/exam_cache.go b/plexams/exam_cache.go new file mode 100644 index 0000000..b340991 --- /dev/null +++ b/plexams/exam_cache.go @@ -0,0 +1,116 @@ +package plexams + +import ( + "context" + "fmt" + "time" + + "github.com/logrusorgru/aurora" + "github.com/obcode/plexams.go/graph/model" + "github.com/rs/zerolog/log" + "github.com/theckman/yacspin" +) + +func (p *Plexams) CacheExam(ancode int) error { + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Cyan(" caching exam %d"), + aurora.Yellow(ancode), + ), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + ctx := context.Background() + + spinner.Message("generating exam") + exam, err := p.Exam(ctx, ancode) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("error while getting exam") + spinner.StopFailMessage(fmt.Sprintf("problem: %v", err)) + + err := spinner.StopFail() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + return err + } + if exam.ZpaExam != nil { + log.Debug().Int("ancode", exam.Ancode).Str("module", exam.ZpaExam.Module).Str("examer", exam.ZpaExam.MainExamer). + Msg("caching exam") + } + + spinner.Message("caching exam") + err = p.dbClient.CacheExam(ctx, exam) + if err == nil { + if exam.ZpaExam != nil { + str := aurora.Sprintf(aurora.Green("%s, %s"), exam.ZpaExam.MainExamer, exam.ZpaExam.Module) + if len(exam.RegularStudents) > 0 { + str = fmt.Sprintf("%s, %s", str, aurora.Sprintf(aurora.Magenta("%d stud"), + len(exam.RegularStudents)+len(exam.NtaStudents))) + } + if len(exam.NtaStudents) > 0 { + str = fmt.Sprintf("%s + %s", str, aurora.Sprintf(aurora.Red("%d nta"), + len(exam.NtaStudents))) + } + + spinner.StopMessage(str) + } + } else { + spinner.StopFailMessage(fmt.Sprintf("problem: %v", err)) + + err := spinner.StopFail() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + } + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + return nil +} + +func (p *Plexams) CacheExams() error { + ctx := context.Background() + ancodes, err := p.GetZpaAnCodesToPlan(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get zpa ancodes to plan") + return err + } + for _, ancode := range ancodes { + err = p.CacheExam(ancode.Ancode) + if err != nil { + log.Error().Err(err).Int("ancode", ancode.Ancode).Msg("cannot cache exam") + return err + } + log.Debug().Int("ancode", ancode.Ancode).Msg("successfully cached exam") + } + fmt.Println(aurora.Sprintf(aurora.Green("%d exams successfully cached.\n"), len(ancodes))) + return nil +} + +func (p *Plexams) RmCacheExams() error { + return p.dbClient.RmCacheExams(context.Background()) +} + +func (p *Plexams) CachedExam(ctx context.Context, ancode int) (*model.Exam, error) { + return p.dbClient.CachedExam(ctx, ancode) +} + +func (p *Plexams) CachedExams(ctx context.Context) ([]*model.Exam, error) { + return p.dbClient.CachedExams(ctx) +} diff --git a/plexams/plexams.go b/plexams/plexams.go index 65d2e37..90dd1d8 100644 --- a/plexams/plexams.go +++ b/plexams/plexams.go @@ -7,7 +7,7 @@ import ( "strings" "time" - "github.com/gookit/color" + "github.com/logrusorgru/aurora" "github.com/obcode/plexams.go/db" "github.com/obcode/plexams.go/graph/model" "github.com/obcode/plexams.go/zpa" @@ -231,9 +231,8 @@ func (p *Plexams) getSlotTime(dayNumber, slotNumber int) time.Time { return time.Date(0, 0, 0, 0, 0, 0, 0, nil) } -func (p *Plexams) PrintSemester() { - color.Style{color.FgCyan, color.BgYellow, color.OpBold}.Printf(" --- Planning Semester: %s --- ", p.semester) - color.Println() +func (p *Plexams) PrintInfo() { + fmt.Println(aurora.Sprintf(aurora.Magenta(" --- Planning Semester: %s --- \n"), p.semester)) } func (p *Plexams) setRoomInfo() { From 5ba319be38c96bdba063673260a04ceda6eb5c48 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Tue, 12 Sep 2023 18:19:33 +0200 Subject: [PATCH 15/78] add a todo --- plexams/email.go | 1 + 1 file changed, 1 insertion(+) diff --git a/plexams/email.go b/plexams/email.go index 7723b83..fe79bbb 100644 --- a/plexams/email.go +++ b/plexams/email.go @@ -9,6 +9,7 @@ import ( "net/smtp" "net/textproto" + // TODO: Ersetzen durch github.com/wneessen/go-mail "github.com/jordan-wright/email" "github.com/rs/zerolog/log" ) From 4aa821abf1499838f452a9bc722a78ec29f05906 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Mon, 9 Oct 2023 11:58:57 +0200 Subject: [PATCH 16/78] tiny, cosmetic change --- plexams/plexams.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plexams/plexams.go b/plexams/plexams.go index 90dd1d8..6ff6ae3 100644 --- a/plexams/plexams.go +++ b/plexams/plexams.go @@ -64,7 +64,7 @@ func NewPlexams(semester, dbUri, zpaBaseurl, zpaUsername, zpaPassword string, fk client, err = db.NewDB(dbUri, semester, databaseName) if err != nil { - panic(fmt.Errorf("fatal cannot create mongo client: %w", err)) + log.Fatal().Err(err).Msg("cannot connect to plexams.db") } } From 78c8ca8164d73f5b6d69373f2f62ff2e4f475db3 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Fri, 10 Nov 2023 21:21:40 +0100 Subject: [PATCH 17/78] primuss ancodes in zpa exams --- cmd/zpa.go | 2 +- db/zpa_exams.go | 6 +- graph/generated/generated.go | 294 +++++++++++++++++++++++++++++++++++ graph/model/zpa.go | 32 ++-- graph/zpa.graphqls | 6 + 5 files changed, 325 insertions(+), 15 deletions(-) diff --git a/cmd/zpa.go b/cmd/zpa.go index 68b5a50..216c8d9 100644 --- a/cmd/zpa.go +++ b/cmd/zpa.go @@ -43,7 +43,7 @@ var ( log.Fatal().Err(err).Msg("cannot get teachers") } for _, exam := range exams { - fmt.Printf("%3d. %s (%s)\n", exam.AnCode, exam.Module, exam.MainExamer) + fmt.Printf("%3d. %s (%s): %v\n", exam.AnCode, exam.Module, exam.MainExamer, exam.PrimussAncodes) } // TODO: wenn schon in der DB vorhanden, Änderungen anzeigen diff --git a/db/zpa_exams.go b/db/zpa_exams.go index bec12c8..79629b9 100644 --- a/db/zpa_exams.go +++ b/db/zpa_exams.go @@ -141,7 +141,11 @@ func (db *DB) RmZpaExamFromPlan(ctx context.Context, ancode int) (bool, error) { func (db *DB) addZpaExamToPlanOrNot(ctx context.Context, ancode int, toPlan bool) (bool, error) { collection := db.Client.Database(db.databaseName).Collection(collectionToPlan) - res, err := collection.ReplaceOne(ctx, bson.D{{Key: "ancode", Value: ancode}}, ExamToPlanType{Ancode: ancode, ToPlan: toPlan}) + replaceOptions := options.Replace() + replaceOptions.SetUpsert(true) + + res, err := collection.ReplaceOne(ctx, bson.D{{Key: "ancode", Value: ancode}}, + ExamToPlanType{Ancode: ancode, ToPlan: toPlan}, replaceOptions) log.Debug().Interface("res", res).Msg("changing exam to plan value") diff --git a/graph/generated/generated.go b/graph/generated/generated.go index cd3237a..e034a81 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -545,6 +545,7 @@ type ComplexityRoot struct { MainExamer func(childComplexity int) int MainExamerID func(childComplexity int) int Module func(childComplexity int) int + PrimussAncodes func(childComplexity int) int Semester func(childComplexity int) int ZpaID func(childComplexity int) int } @@ -564,6 +565,11 @@ type ComplexityRoot struct { Teacher func(childComplexity int) int } + ZPAPrimussAncodes struct { + Ancode func(childComplexity int) int + Program func(childComplexity int) int + } + ZPAStudentReg struct { AnCode func(childComplexity int) int Mtknr func(childComplexity int) int @@ -3202,6 +3208,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.ZPAExam.Module(childComplexity), true + case "ZPAExam.primussAncodes": + if e.complexity.ZPAExam.PrimussAncodes == nil { + break + } + + return e.complexity.ZPAExam.PrimussAncodes(childComplexity), true + case "ZPAExam.semester": if e.complexity.ZPAExam.Semester == nil { break @@ -3258,6 +3271,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.ZPAInvigilator.Teacher(childComplexity), true + case "ZPAPrimussAncodes.ancode": + if e.complexity.ZPAPrimussAncodes.Ancode == nil { + break + } + + return e.complexity.ZPAPrimussAncodes.Ancode(childComplexity), true + + case "ZPAPrimussAncodes.program": + if e.complexity.ZPAPrimussAncodes.Program == nil { + break + } + + return e.complexity.ZPAPrimussAncodes.Program(childComplexity), true + case "ZPAStudentReg.ancode": if e.complexity.ZPAStudentReg.AnCode == nil { break @@ -3984,6 +4011,12 @@ type ZPAExam { duration: Int! isRepeaterExam: Boolean! groups: [String!]! + primussAncodes: [ZPAPrimussAncodes!]! +} + +type ZPAPrimussAncodes { + program: String! + ancode: Int! } type ZPAExamsForType { @@ -5867,6 +5900,8 @@ func (ec *executionContext) fieldContext_ConnectedExam_zpaExam(ctx context.Conte return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) case "groups": return ec.fieldContext_ZPAExam_groups(ctx, field) + case "primussAncodes": + return ec.fieldContext_ZPAExam_primussAncodes(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) }, @@ -6532,6 +6567,8 @@ func (ec *executionContext) fieldContext_Exam_zpaExam(ctx context.Context, field return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) case "groups": return ec.fieldContext_ZPAExam_groups(ctx, field) + case "primussAncodes": + return ec.fieldContext_ZPAExam_primussAncodes(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) }, @@ -8332,6 +8369,8 @@ func (ec *executionContext) fieldContext_ExamWithRegs_zpaExam(ctx context.Contex return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) case "groups": return ec.fieldContext_ZPAExam_groups(ctx, field) + case "primussAncodes": + return ec.fieldContext_ZPAExam_primussAncodes(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) }, @@ -11003,6 +11042,8 @@ func (ec *executionContext) fieldContext_Mutation_zpaExamsToPlan(ctx context.Con return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) case "groups": return ec.fieldContext_ZPAExam_groups(ctx, field) + case "primussAncodes": + return ec.fieldContext_ZPAExam_primussAncodes(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) }, @@ -12775,6 +12816,8 @@ func (ec *executionContext) fieldContext_NTAWithRegsByExam_exam(ctx context.Cont return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) case "groups": return ec.fieldContext_ZPAExam_groups(ctx, field) + case "primussAncodes": + return ec.fieldContext_ZPAExam_primussAncodes(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) }, @@ -16764,6 +16807,8 @@ func (ec *executionContext) fieldContext_Query_zpaExams(ctx context.Context, fie return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) case "groups": return ec.fieldContext_ZPAExam_groups(ctx, field) + case "primussAncodes": + return ec.fieldContext_ZPAExam_primussAncodes(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) }, @@ -16893,6 +16938,8 @@ func (ec *executionContext) fieldContext_Query_zpaExamsToPlan(ctx context.Contex return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) case "groups": return ec.fieldContext_ZPAExam_groups(ctx, field) + case "primussAncodes": + return ec.fieldContext_ZPAExam_primussAncodes(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) }, @@ -16961,6 +17008,8 @@ func (ec *executionContext) fieldContext_Query_zpaExamsNotToPlan(ctx context.Con return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) case "groups": return ec.fieldContext_ZPAExam_groups(ctx, field) + case "primussAncodes": + return ec.fieldContext_ZPAExam_primussAncodes(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) }, @@ -17029,6 +17078,8 @@ func (ec *executionContext) fieldContext_Query_zpaExamsPlaningStatusUnknown(ctx return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) case "groups": return ec.fieldContext_ZPAExam_groups(ctx, field) + case "primussAncodes": + return ec.fieldContext_ZPAExam_primussAncodes(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) }, @@ -17094,6 +17145,8 @@ func (ec *executionContext) fieldContext_Query_zpaExam(ctx context.Context, fiel return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) case "groups": return ec.fieldContext_ZPAExam_groups(ctx, field) + case "primussAncodes": + return ec.fieldContext_ZPAExam_primussAncodes(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) }, @@ -17917,6 +17970,8 @@ func (ec *executionContext) fieldContext_RoomAndExam_exam(ctx context.Context, f return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) case "groups": return ec.fieldContext_ZPAExam_groups(ctx, field) + case "primussAncodes": + return ec.fieldContext_ZPAExam_primussAncodes(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) }, @@ -21600,6 +21655,56 @@ func (ec *executionContext) fieldContext_ZPAExam_groups(ctx context.Context, fie return fc, nil } +func (ec *executionContext) _ZPAExam_primussAncodes(ctx context.Context, field graphql.CollectedField, obj *model.ZPAExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ZPAExam_primussAncodes(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PrimussAncodes, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]model.ZPAPrimussAncodes) + fc.Result = res + return ec.marshalNZPAPrimussAncodes2ᚕgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAPrimussAncodesᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ZPAExam_primussAncodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ZPAExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "program": + return ec.fieldContext_ZPAPrimussAncodes_program(ctx, field) + case "ancode": + return ec.fieldContext_ZPAPrimussAncodes_ancode(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ZPAPrimussAncodes", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _ZPAExamWithConstraints_zpaExam(ctx context.Context, field graphql.CollectedField, obj *model.ZPAExamWithConstraints) (ret graphql.Marshaler) { fc, err := ec.fieldContext_ZPAExamWithConstraints_zpaExam(ctx, field) if err != nil { @@ -21661,6 +21766,8 @@ func (ec *executionContext) fieldContext_ZPAExamWithConstraints_zpaExam(ctx cont return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) case "groups": return ec.fieldContext_ZPAExam_groups(ctx, field) + case "primussAncodes": + return ec.fieldContext_ZPAExam_primussAncodes(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) }, @@ -21834,6 +21941,8 @@ func (ec *executionContext) fieldContext_ZPAExamsForType_exams(ctx context.Conte return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) case "groups": return ec.fieldContext_ZPAExam_groups(ctx, field) + case "primussAncodes": + return ec.fieldContext_ZPAExam_primussAncodes(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) }, @@ -21951,6 +22060,94 @@ func (ec *executionContext) fieldContext_ZPAInvigilator_hasSubmittedRequirements return fc, nil } +func (ec *executionContext) _ZPAPrimussAncodes_program(ctx context.Context, field graphql.CollectedField, obj *model.ZPAPrimussAncodes) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ZPAPrimussAncodes_program(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Program, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ZPAPrimussAncodes_program(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ZPAPrimussAncodes", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _ZPAPrimussAncodes_ancode(ctx context.Context, field graphql.CollectedField, obj *model.ZPAPrimussAncodes) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ZPAPrimussAncodes_ancode(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Ancode, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ZPAPrimussAncodes_ancode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ZPAPrimussAncodes", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _ZPAStudentReg_ancode(ctx context.Context, field graphql.CollectedField, obj *model.ZPAStudentReg) (ret graphql.Marshaler) { fc, err := ec.fieldContext_ZPAStudentReg_ancode(ctx, field) if err != nil { @@ -28895,6 +29092,11 @@ func (ec *executionContext) _ZPAExam(ctx context.Context, sel ast.SelectionSet, if out.Values[i] == graphql.Null { out.Invalids++ } + case "primussAncodes": + out.Values[i] = ec._ZPAExam_primussAncodes(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -29047,6 +29249,50 @@ func (ec *executionContext) _ZPAInvigilator(ctx context.Context, sel ast.Selecti return out } +var zPAPrimussAncodesImplementors = []string{"ZPAPrimussAncodes"} + +func (ec *executionContext) _ZPAPrimussAncodes(ctx context.Context, sel ast.SelectionSet, obj *model.ZPAPrimussAncodes) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, zPAPrimussAncodesImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("ZPAPrimussAncodes") + case "program": + out.Values[i] = ec._ZPAPrimussAncodes_program(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "ancode": + out.Values[i] = ec._ZPAPrimussAncodes_ancode(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var zPAStudentRegImplementors = []string{"ZPAStudentReg"} func (ec *executionContext) _ZPAStudentReg(ctx context.Context, sel ast.SelectionSet, obj *model.ZPAStudentReg) graphql.Marshaler { @@ -31458,6 +31704,54 @@ func (ec *executionContext) marshalNZPAInvigilator2ᚖgithubᚗcomᚋobcodeᚋpl return ec._ZPAInvigilator(ctx, sel, v) } +func (ec *executionContext) marshalNZPAPrimussAncodes2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAPrimussAncodes(ctx context.Context, sel ast.SelectionSet, v model.ZPAPrimussAncodes) graphql.Marshaler { + return ec._ZPAPrimussAncodes(ctx, sel, &v) +} + +func (ec *executionContext) marshalNZPAPrimussAncodes2ᚕgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAPrimussAncodesᚄ(ctx context.Context, sel ast.SelectionSet, v []model.ZPAPrimussAncodes) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNZPAPrimussAncodes2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAPrimussAncodes(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + func (ec *executionContext) marshalNZPAStudentReg2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAStudentReg(ctx context.Context, sel ast.SelectionSet, v *model.ZPAStudentReg) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { diff --git a/graph/model/zpa.go b/graph/model/zpa.go index 8a51dad..52c3559 100644 --- a/graph/model/zpa.go +++ b/graph/model/zpa.go @@ -14,19 +14,25 @@ type Teacher struct { } type ZPAExam struct { - ZpaID int `json:"id"` - Semester string `json:"semester"` - AnCode int `json:"ancode"` - Module string `json:"module"` - MainExamer string `json:"main_examer"` - MainExamerID int `json:"main_examer_id"` - ExamType string `json:"exam_type"` - ExamTypeFull string `json:"full_name"` - Date string `json:"date"` - Starttime string `json:"start_time"` - Duration int `json:"duration"` - IsRepeaterExam bool `json:"is_repeater_exam"` - Groups []string `json:"groups"` + ZpaID int `json:"id"` + Semester string `json:"semester"` + AnCode int `json:"ancode"` + Module string `json:"module"` + MainExamer string `json:"main_examer"` + MainExamerID int `json:"main_examer_id"` + ExamType string `json:"exam_type"` + ExamTypeFull string `json:"full_name"` + Date string `json:"date"` + Starttime string `json:"start_time"` + Duration int `json:"duration"` + IsRepeaterExam bool `json:"is_repeater_exam"` + Groups []string `json:"groups"` + PrimussAncodes []ZPAPrimussAncodes `json:"primuss_ancodes"` +} + +type ZPAPrimussAncodes struct { + Program string `json:"program"` + Ancode int `json:"ancode"` } type ZPAStudentReg struct { diff --git a/graph/zpa.graphqls b/graph/zpa.graphqls index 43b272c..1aeb2af 100644 --- a/graph/zpa.graphqls +++ b/graph/zpa.graphqls @@ -25,6 +25,12 @@ type ZPAExam { duration: Int! isRepeaterExam: Boolean! groups: [String!]! + primussAncodes: [ZPAPrimussAncodes!]! +} + +type ZPAPrimussAncodes { + program: String! + ancode: Int! } type ZPAExamsForType { From c15395122b534fc58fcf21a6fa1d3e43698aa293 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Sat, 11 Nov 2023 20:45:11 +0100 Subject: [PATCH 18/78] pdf sorted by ancode, examer and module --- plexams/pdf.go | 121 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 120 insertions(+), 1 deletion(-) diff --git a/plexams/pdf.go b/plexams/pdf.go index c1d5237..0ae6116 100644 --- a/plexams/pdf.go +++ b/plexams/pdf.go @@ -60,7 +60,7 @@ func (p *Plexams) GenerateExamsToPlanPDF(ctx context.Context, outfile string) er }) }) }) - m.Row(20, func() { + m.Row(10, func() { m.Col(12, func() { m.Text( fmt.Sprintf("Melden Sie sich bitte umgehend per E-Mail (%s) bei mir (%s), wenn Ihre Prüfung hier fehlt oder hier nicht stehen sollte.", @@ -71,6 +71,16 @@ func (p *Plexams) GenerateExamsToPlanPDF(ctx context.Context, outfile string) er }) }) }) + m.Row(10, func() { + m.Col(12, func() { + m.Text( + "Dieses Dokument enthält alle Prüfungen in 3 Sortierungen.", props.Text{ + Top: 3, + Style: consts.Normal, + Align: consts.Center, + }) + }) + }) header := []string{"AnCode", "Modul", "Prüfer:in", "Gruppe(n)", "Form"} @@ -79,6 +89,17 @@ func (p *Plexams) GenerateExamsToPlanPDF(ctx context.Context, outfile string) er log.Error().Err(err).Msg("error while getting exams") } + m.Row(20, func() { + m.Col(12, func() { + m.Text( + "Sortiert nach AnCode (= der Code im ZPA)", props.Text{ + Top: 5, + Style: consts.Bold, + Align: consts.Center, + }) + }) + }) + contents := make([][]string, 0, len(exams)) for _, exam := range exams { @@ -106,6 +127,104 @@ func (p *Plexams) GenerateExamsToPlanPDF(ctx context.Context, outfile string) er Line: false, }) + m.Row(20, func() { + m.Col(12, func() { + m.Text( + "Sortiert nach dem Namen der Prüfer:in", props.Text{ + Top: 5, + Style: consts.Bold, + Align: consts.Center, + }) + }) + }) + + examsByExamers := make(map[string][]*model.ZPAExam) + for _, exam := range exams { + examsByExamer, ok := examsByExamers[exam.MainExamer] + if !ok { + examsByExamer = make([]*model.ZPAExam, 0, 1) + } + examsByExamers[exam.MainExamer] = append(examsByExamer, exam) + } + + keys := make([]string, 0, len(examsByExamers)) + for k := range examsByExamers { + keys = append(keys, k) + } + sort.Strings(keys) + + contents = make([][]string, 0, len(exams)) + + for _, key := range keys { + for _, exam := range examsByExamers[key] { + contents = append(contents, []string{strconv.Itoa(exam.AnCode), exam.Module, exam.MainExamer, fmt.Sprintf("%v", exam.Groups), exam.ExamTypeFull}) + } + } + + m.TableList(header, contents, props.TableList{ + HeaderProp: props.TableListContent{ + Size: 9, + GridSizes: []uint{1, 4, 2, 2, 3}, + }, + ContentProp: props.TableListContent{ + Size: 8, + GridSizes: []uint{1, 4, 2, 2, 3}, + }, + Align: consts.Left, + AlternatedBackground: &grayColor, + HeaderContentSpace: 1, + Line: false, + }) + + m.Row(20, func() { + m.Col(12, func() { + m.Text( + "Sortiert nach dem Prüfungsnamen", props.Text{ + Top: 5, + Style: consts.Bold, + Align: consts.Center, + }) + }) + }) + + examsByModules := make(map[string][]*model.ZPAExam) + for _, exam := range exams { + examsByModule, ok := examsByModules[exam.Module] + if !ok { + examsByModule = make([]*model.ZPAExam, 0, 1) + } + examsByModules[exam.Module] = append(examsByModule, exam) + } + + keys = make([]string, 0, len(examsByModules)) + for k := range examsByModules { + keys = append(keys, k) + } + sort.Strings(keys) + + contents = make([][]string, 0, len(exams)) + + for _, key := range keys { + for _, exam := range examsByModules[key] { + contents = append(contents, []string{strconv.Itoa(exam.AnCode), exam.Module, exam.MainExamer, fmt.Sprintf("%v", exam.Groups), exam.ExamTypeFull}) + } + } + + m.TableList(header, contents, props.TableList{ + HeaderProp: props.TableListContent{ + Size: 9, + GridSizes: []uint{1, 4, 2, 2, 3}, + }, + ContentProp: props.TableListContent{ + Size: 8, + GridSizes: []uint{1, 4, 2, 2, 3}, + }, + Align: consts.Left, + AlternatedBackground: &grayColor, + HeaderContentSpace: 1, + Line: false, + }) + err = m.OutputFileAndClose(outfile) if err != nil { log.Error().Err(err).Msg("Could not save PDF") From c309efd1c70f991334e7abe46ab2184a117b28e0 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Tue, 14 Nov 2023 14:54:56 +0100 Subject: [PATCH 19/78] Add primuss ancode --- cmd/primuss.go | 29 +++++++++++++++++++++++ db/collection.go | 2 ++ db/primuss.go | 58 ++++++++++++++++++++++++++++++++++++++++++++++ graph/model/zpa.go | 5 ++++ plexams/primuss.go | 4 ++++ plexams/zpa.go | 11 +++++++++ 6 files changed, 109 insertions(+) create mode 100644 plexams/zpa.go diff --git a/cmd/primuss.go b/cmd/primuss.go index 45f48f8..e0efa05 100644 --- a/cmd/primuss.go +++ b/cmd/primuss.go @@ -15,12 +15,41 @@ var primussCmd = &cobra.Command{ Use: "primuss", Short: "primuss [subcommand]", Long: `Handle primuss data. + add-ancode zpa-ancode program primuss-ancode --- add ancode to zpa-data fix-ancode program from to --- fix ancode in primuss data (exam and studentregs) rm-studentreg program ancode mtknr --- remove a student registration`, Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { plexams := initPlexamsConfig() switch args[0] { + case "add-ancode": + if len(args) < 4 { + log.Fatal("need program and primuss ancode") + } + ancode, err := strconv.Atoi(args[1]) + if err != nil { + log.Fatalf("cannot convert %s to int\n", args[2]) + } + program := args[2] + primussAncode, err := strconv.Atoi(args[3]) + if err != nil { + log.Fatalf("cannot convert %s to int\n", args[2]) + } + + ctx := context.Background() + zpaExam, err := plexams.GetZPAExam(ctx, ancode) + if err != nil { + log.Fatalf("cannot get zpa exam with ancode %d\n", ancode) + } + + fmt.Printf("Found exam: %d. %s, %s (%v)\n", zpaExam.AnCode, zpaExam.Module, zpaExam.MainExamer, zpaExam.PrimussAncodes) + + if !confirm(fmt.Sprintf("add primuss ancode %s/%d to zpa exam?", program, primussAncode), 10) { + os.Exit(0) + } + + err = plexams.AddAncode(ctx, ancode, program, primussAncode) + case "fix-ancode": if len(args) < 4 { log.Fatal("need program, from and to") diff --git a/db/collection.go b/db/collection.go index 30e80c6..7065fcc 100644 --- a/db/collection.go +++ b/db/collection.go @@ -28,6 +28,8 @@ const ( collectionAll = "zpaexams" collectionToPlan = "zpaexamsToPlan" + collectionPrimussAncodes = "primuss_ancodes" + collectionExamsInPlan = "exams_in_plan" collectionCachedExams = "cached_exams" diff --git a/db/primuss.go b/db/primuss.go index 06c011f..bc8b482 100644 --- a/db/primuss.go +++ b/db/primuss.go @@ -5,8 +5,11 @@ import ( "sort" "strings" + "github.com/obcode/plexams.go/graph/model" + "github.com/rs/zerolog/log" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/mongo/options" ) func (db *DB) GetPrograms(ctx context.Context) ([]string, error) { @@ -30,3 +33,58 @@ func (db *DB) GetPrograms(ctx context.Context) ([]string, error) { return programs, err } + +func (db *DB) AddAncode(ctx context.Context, zpaAncode int, program string, primussAncode int) error { + collection := db.Client.Database(db.databaseName).Collection(collectionPrimussAncodes) + + opts := options.Replace().SetUpsert(true) + + _, err := collection.ReplaceOne(ctx, bson.D{{Key: "ancode", Value: zpaAncode}}, + model.AddedPrimussAncode{ + Ancode: zpaAncode, + PrimussAncode: model.ZPAPrimussAncodes{ + Program: program, + Ancode: primussAncode, + }, + }, opts) + + if err != nil { + log.Error().Err(err).Int("zpaAncode", zpaAncode).Str("program", program).Int("primussAncode", primussAncode). + Msg("cannot add primuss ancode for zpa ancode") + return err + } + return nil +} + +func (db *DB) GetAddedAncodes(ctx context.Context) (map[int][]*model.ZPAPrimussAncodes, error) { + collection := db.Client.Database(db.databaseName).Collection(collectionPrimussAncodes) + + cur, err := collection.Find(ctx, bson.M{}) + if err != nil { + log.Error().Err(err).Msg("cannot get added ancodes") + return nil, err + } + + var addedAncodes []*model.AddedPrimussAncode + err = cur.All(ctx, addedAncodes) + if err != nil { + log.Error().Err(err).Msg("cannot decode added ancodes") + return nil, err + } + + addedAcodesMap := make(map[int][]*model.ZPAPrimussAncodes) + for _, addedAncode := range addedAncodes { + addedAncodeEntries, ok := addedAcodesMap[addedAncode.Ancode] + if !ok { + addedAncodeEntries = make([]*model.ZPAPrimussAncodes, 0, 1) + } + addedAcodesMap[addedAncode.Ancode] = append(addedAncodeEntries, &addedAncode.PrimussAncode) + } + + return addedAcodesMap, nil +} + +func (db *DB) GetAddedAncodesForAncode(ctx context.Context, ancode int) ([]*model.ZPAPrimussAncodes, error) { + // IMPLEMENT ME + return nil, nil +} diff --git a/graph/model/zpa.go b/graph/model/zpa.go index 52c3559..a376fb5 100644 --- a/graph/model/zpa.go +++ b/graph/model/zpa.go @@ -35,6 +35,11 @@ type ZPAPrimussAncodes struct { Ancode int `json:"ancode"` } +type AddedPrimussAncode struct { + Ancode int `json:"ancode"` + PrimussAncode ZPAPrimussAncodes `json:"primuss_ancodes"` +} + type ZPAStudentReg struct { Semester string `json:"semester"` AnCode int `json:"anCode" bson:"ancode"` diff --git a/plexams/primuss.go b/plexams/primuss.go index 69b4da8..01665e4 100644 --- a/plexams/primuss.go +++ b/plexams/primuss.go @@ -41,3 +41,7 @@ func (p *Plexams) StudentRegsImportErrors(ctx context.Context) ([]*model.RegWith func (p *Plexams) GetConflicts(ctx context.Context, exam *model.PrimussExam) (*model.Conflicts, error) { return p.dbClient.GetPrimussConflictsForAncode(ctx, exam.Program, exam.AnCode) } + +func (p *Plexams) AddAncode(ctx context.Context, zpaAncode int, program string, primussAncode int) error { + return p.dbClient.AddAncode(ctx, zpaAncode, program, primussAncode) +} diff --git a/plexams/zpa.go b/plexams/zpa.go new file mode 100644 index 0000000..85db8b3 --- /dev/null +++ b/plexams/zpa.go @@ -0,0 +1,11 @@ +package plexams + +import ( + "context" + + "github.com/obcode/plexams.go/graph/model" +) + +func (p *Plexams) GetZPAExam(ctx context.Context, ancode int) (*model.ZPAExam, error) { + return p.dbClient.GetZpaExamByAncode(ctx, ancode) +} From 23687ad177f36a233f598efa61e574f59145af7b Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Wed, 15 Nov 2023 17:09:44 +0100 Subject: [PATCH 20/78] added ancodes and missing ancodes --- db/primuss.go | 14 +++++++------- db/zpa_exams.go | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/db/primuss.go b/db/primuss.go index bc8b482..3074341 100644 --- a/db/primuss.go +++ b/db/primuss.go @@ -39,7 +39,7 @@ func (db *DB) AddAncode(ctx context.Context, zpaAncode int, program string, prim opts := options.Replace().SetUpsert(true) - _, err := collection.ReplaceOne(ctx, bson.D{{Key: "ancode", Value: zpaAncode}}, + _, err := collection.ReplaceOne(ctx, bson.M{"ancode": zpaAncode, "primussancode.program": program}, model.AddedPrimussAncode{ Ancode: zpaAncode, PrimussAncode: model.ZPAPrimussAncodes{ @@ -56,7 +56,7 @@ func (db *DB) AddAncode(ctx context.Context, zpaAncode int, program string, prim return nil } -func (db *DB) GetAddedAncodes(ctx context.Context) (map[int][]*model.ZPAPrimussAncodes, error) { +func (db *DB) GetAddedAncodes(ctx context.Context) (map[int][]model.ZPAPrimussAncodes, error) { collection := db.Client.Database(db.databaseName).Collection(collectionPrimussAncodes) cur, err := collection.Find(ctx, bson.M{}) @@ -65,20 +65,20 @@ func (db *DB) GetAddedAncodes(ctx context.Context) (map[int][]*model.ZPAPrimussA return nil, err } - var addedAncodes []*model.AddedPrimussAncode - err = cur.All(ctx, addedAncodes) + var addedAncodes []model.AddedPrimussAncode + err = cur.All(ctx, &addedAncodes) if err != nil { log.Error().Err(err).Msg("cannot decode added ancodes") return nil, err } - addedAcodesMap := make(map[int][]*model.ZPAPrimussAncodes) + addedAcodesMap := make(map[int][]model.ZPAPrimussAncodes) for _, addedAncode := range addedAncodes { addedAncodeEntries, ok := addedAcodesMap[addedAncode.Ancode] if !ok { - addedAncodeEntries = make([]*model.ZPAPrimussAncodes, 0, 1) + addedAncodeEntries = make([]model.ZPAPrimussAncodes, 0, 1) } - addedAcodesMap[addedAncode.Ancode] = append(addedAncodeEntries, &addedAncode.PrimussAncode) + addedAcodesMap[addedAncode.Ancode] = append(addedAncodeEntries, addedAncode.PrimussAncode) } return addedAcodesMap, nil diff --git a/db/zpa_exams.go b/db/zpa_exams.go index 79629b9..5479308 100644 --- a/db/zpa_exams.go +++ b/db/zpa_exams.go @@ -190,10 +190,47 @@ func (db *DB) getZPAExamsPlannedOrNot(ctx context.Context, toPlan *bool) ([]*mod return nil, err } + addedAncodes, err := db.GetAddedAncodes(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get added ancodes") + return nil, err + } + exams := make([]*model.ZPAExam, 0, (*ancodeSet).Cardinality()) + // add added ancodes for _, zpaExam := range zpaExams { if (*ancodeSet).Contains(zpaExam.AnCode) { + addedAncodesForAncode, ok := addedAncodes[zpaExam.AnCode] + if ok { + + rmNewAncodes := make([]model.ZPAPrimussAncodes, 0, len(zpaExam.PrimussAncodes)) + OUTER: + for _, ancode := range zpaExam.PrimussAncodes { + for _, newAncode := range addedAncodesForAncode { + if ancode.Program == newAncode.Program { + break OUTER + } + } + rmNewAncodes = append(rmNewAncodes, ancode) + } + zpaExam.PrimussAncodes = append(rmNewAncodes, addedAncodesForAncode...) + } + // add dummy ancodes if no ancode for group is present + OUTER2: + for _, group := range zpaExam.Groups { + groupShort := group[:2] + for _, ancodes := range zpaExam.PrimussAncodes { + if ancodes.Program == groupShort { + break OUTER2 + } + } + zpaExam.PrimussAncodes = append(zpaExam.PrimussAncodes, + model.ZPAPrimussAncodes{ + Program: groupShort, + Ancode: -1, + }) + } exams = append(exams, zpaExam) } } From 343684f613a965296f7f47ca4df9fd8a93d4eeba Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Wed, 15 Nov 2023 17:11:53 +0100 Subject: [PATCH 21/78] upgrade linter --- .github/workflows/golangci-lint.yml | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 8459ff9..ef27cfa 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -7,12 +7,28 @@ jobs: name: lint runs-on: ubuntu-latest steps: - - uses: actions/setup-go@v4 - with: - go-version: "1.20" - cache: false - - uses: actions/checkout@v3 + - uses: actions/checkout@v2 - name: golangci-lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v2 with: + # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version version: latest + + # Optional: working directory, useful for monorepos + # working-directory: somedir + + # Optional: golangci-lint command line arguments. + # args: --issues-exit-code=0 + args: --timeout=10m + + # Optional: show only new issues if it's a pull request. The default value is `false`. + # only-new-issues: true + + # Optional: if set to true then the action will use pre-installed Go. + # skip-go-installation: true + + # Optional: if set to true then the action don't cache or restore ~/go/pkg. + # skip-pkg-cache: true + + # Optional: if set to true then the action don't cache or restore ~/.cache/go-build. + # skip-build-cache: true From cc506dd51faf42ff70f9e1cdff8474eaeebb8bd3 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Wed, 15 Nov 2023 17:14:35 +0100 Subject: [PATCH 22/78] make linter happy --- cmd/primuss.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/primuss.go b/cmd/primuss.go index e0efa05..afab844 100644 --- a/cmd/primuss.go +++ b/cmd/primuss.go @@ -49,6 +49,9 @@ var primussCmd = &cobra.Command{ } err = plexams.AddAncode(ctx, ancode, program, primussAncode) + if err != nil { + log.Fatalf("cannot add ancode") + } case "fix-ancode": if len(args) < 4 { From 7d412d5432a6cc395306408084ea8ea0e5633df8 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Fri, 17 Nov 2023 11:31:29 +0100 Subject: [PATCH 23/78] more added ancodes stuff --- db/primuss.go | 25 ++++++- db/zpa_exams.go | 169 ++++++++++++++++++++++++++++++++++++++++-------- plexams/exam.go | 116 ++++++++++++++++++++++----------- 3 files changed, 243 insertions(+), 67 deletions(-) diff --git a/db/primuss.go b/db/primuss.go index 3074341..588e17b 100644 --- a/db/primuss.go +++ b/db/primuss.go @@ -84,7 +84,26 @@ func (db *DB) GetAddedAncodes(ctx context.Context) (map[int][]model.ZPAPrimussAn return addedAcodesMap, nil } -func (db *DB) GetAddedAncodesForAncode(ctx context.Context, ancode int) ([]*model.ZPAPrimussAncodes, error) { - // IMPLEMENT ME - return nil, nil +func (db *DB) GetAddedAncodesForAncode(ctx context.Context, ancode int) ([]model.ZPAPrimussAncodes, error) { + collection := db.Client.Database(db.databaseName).Collection(collectionPrimussAncodes) + + cur, err := collection.Find(ctx, bson.D{{Key: "ancode", Value: ancode}}) + if err != nil { + log.Error().Err(err).Msg("cannot get added ancodes") + return nil, err + } + + var addedAncodes []model.AddedPrimussAncode + err = cur.All(ctx, &addedAncodes) + if err != nil { + log.Error().Err(err).Msg("cannot decode added ancodes") + return nil, err + } + + added := make([]model.ZPAPrimussAncodes, 0, len(addedAncodes)) + for _, addedAncode := range addedAncodes { + added = append(added, addedAncode.PrimussAncode) + } + + return added, nil } diff --git a/db/zpa_exams.go b/db/zpa_exams.go index 5479308..9d81ba3 100644 --- a/db/zpa_exams.go +++ b/db/zpa_exams.go @@ -2,6 +2,7 @@ package db import ( "context" + "sort" "time" set "github.com/deckarep/golang-set/v2" @@ -26,6 +27,12 @@ func (db *DB) GetZPAExams(ctx context.Context) ([]*model.ZPAExam, error) { } defer cur.Close(ctx) + addedAncodes, err := db.GetAddedAncodes(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get added ancodes") + return nil, err + } + for cur.Next(ctx) { var exam model.ZPAExam @@ -36,6 +43,19 @@ func (db *DB) GetZPAExams(ctx context.Context) ([]*model.ZPAExam, error) { return exams, err } + db.cleanupPrimussAncodes(&exam) + addedAncodesForAncode, ok := addedAncodes[exam.AnCode] + + if ok { + err := db.addAddedAncodesToExam(ctx, &exam, addedAncodesForAncode) + if err != nil { + log.Error().Err(err).Int("ancode", exam.AnCode). + Interface("added ancodes", addedAncodesForAncode). + Msg("error when trying to add added ancodes to exam") + return nil, err + } + } + exams = append(exams, &exam) } @@ -58,6 +78,22 @@ func (db *DB) GetZpaExamByAncode(ctx context.Context, ancode int) (*model.ZPAExa return nil, err } + db.cleanupPrimussAncodes(&result) + addedAncodes, err := db.GetAddedAncodesForAncode(ctx, result.AnCode) + if err != nil { + log.Error().Err(err).Str("semester", db.semester). + Int("ancode", ancode).Msg("cannot get added ancodes") + return nil, err + } + if addedAncodes != nil { + err := db.addAddedAncodesToExam(ctx, &result, addedAncodes) + if err != nil { + log.Error().Err(err).Str("semester", db.semester). + Int("ancode", ancode).Msg("cannot add added ancodes") + return nil, err + } + } + return &result, nil } @@ -198,39 +234,21 @@ func (db *DB) getZPAExamsPlannedOrNot(ctx context.Context, toPlan *bool) ([]*mod exams := make([]*model.ZPAExam, 0, (*ancodeSet).Cardinality()) - // add added ancodes for _, zpaExam := range zpaExams { if (*ancodeSet).Contains(zpaExam.AnCode) { + db.cleanupPrimussAncodes(zpaExam) addedAncodesForAncode, ok := addedAncodes[zpaExam.AnCode] - if ok { - rmNewAncodes := make([]model.ZPAPrimussAncodes, 0, len(zpaExam.PrimussAncodes)) - OUTER: - for _, ancode := range zpaExam.PrimussAncodes { - for _, newAncode := range addedAncodesForAncode { - if ancode.Program == newAncode.Program { - break OUTER - } - } - rmNewAncodes = append(rmNewAncodes, ancode) - } - zpaExam.PrimussAncodes = append(rmNewAncodes, addedAncodesForAncode...) - } - // add dummy ancodes if no ancode for group is present - OUTER2: - for _, group := range zpaExam.Groups { - groupShort := group[:2] - for _, ancodes := range zpaExam.PrimussAncodes { - if ancodes.Program == groupShort { - break OUTER2 - } + if ok { + err := db.addAddedAncodesToExam(ctx, zpaExam, addedAncodesForAncode) + if err != nil { + log.Error().Err(err).Int("ancode", zpaExam.AnCode). + Interface("added ancodes", addedAncodesForAncode). + Msg("error when trying to add added ancodes to exam") + return nil, err } - zpaExam.PrimussAncodes = append(zpaExam.PrimussAncodes, - model.ZPAPrimussAncodes{ - Program: groupShort, - Ancode: -1, - }) } + exams = append(exams, zpaExam) } } @@ -284,3 +302,100 @@ func (db *DB) getZpaAncodesPlannedOrNot(ctx context.Context, toPlan *bool) (*set return &resultSet, nil } + +func (db *DB) cleanupPrimussAncodes(zpaExam *model.ZPAExam) { + programs := set.NewSet[string]() + + ancodesMap := make(map[string]int) + for _, group := range zpaExam.Groups { + ancodesMap[group[:2]] = -1 + programs.Add(group[:2]) + } + + for _, primussAncode := range zpaExam.PrimussAncodes { + if programs.Contains(primussAncode.Program) { + ancodesMap[primussAncode.Program] = primussAncode.Ancode + } + } + + programSlice := programs.ToSlice() + sort.Strings(programSlice) + + newPrimussAncodes := make([]model.ZPAPrimussAncodes, 0, len(ancodesMap)) + + for _, program := range programSlice { + newPrimussAncodes = append(newPrimussAncodes, model.ZPAPrimussAncodes{ + Program: program, + Ancode: ancodesMap[program], + }) + } + + zpaExam.PrimussAncodes = newPrimussAncodes +} + +func (db *DB) addAddedAncodesToExam(ctx context.Context, zpaExam *model.ZPAExam, addedAncodesForAncode []model.ZPAPrimussAncodes) error { + if addedAncodesForAncode == nil { + var err error + addedAncodesForAncode, err = db.GetAddedAncodesForAncode(ctx, zpaExam.AnCode) + if err != nil { + log.Error().Err(err).Int("ancode", zpaExam.AnCode).Msg("cannot get added ancodes") + return err + } + if len(addedAncodesForAncode) == 0 { + return nil + } + } + + allPrimussAncodes := append(zpaExam.PrimussAncodes, addedAncodesForAncode...) + + ancodesMap := make(map[string]int) + programs := set.NewSet[string]() + for _, primussAncode := range allPrimussAncodes { + ancodesMap[primussAncode.Program] = primussAncode.Ancode + programs.Add(primussAncode.Program) + } + + programSlice := programs.ToSlice() + sort.Strings(programSlice) + + newPrimussAncodes := make([]model.ZPAPrimussAncodes, 0, len(ancodesMap)) + + for _, program := range programSlice { + newPrimussAncodes = append(newPrimussAncodes, model.ZPAPrimussAncodes{ + Program: program, + Ancode: ancodesMap[program], + }) + } + + zpaExam.PrimussAncodes = newPrimussAncodes + + // rmNewAncodes := make([]model.ZPAPrimussAncodes, 0, len(zpaExam.PrimussAncodes)) + // OUTER: + // for _, ancode := range zpaExam.PrimussAncodes { + // for _, newAncode := range addedAncodesForAncode { + // if ancode.Program == newAncode.Program { + // break OUTER + // } + // } + // rmNewAncodes = append(rmNewAncodes, ancode) + // } + // zpaExam.PrimussAncodes = append(rmNewAncodes, addedAncodesForAncode...) + + // // add dummy ancodes if no ancode for group is present + // OUTER2: + // for _, group := range zpaExam.Groups { + // groupShort := group[:2] + // for _, ancodes := range zpaExam.PrimussAncodes { + // if ancodes.Program == groupShort { + // break OUTER2 + // } + // } + // zpaExam.PrimussAncodes = append(zpaExam.PrimussAncodes, + // model.ZPAPrimussAncodes{ + // Program: groupShort, + // Ancode: -1, + // }) + // } + + return nil +} diff --git a/plexams/exam.go b/plexams/exam.go index a6988a2..4ff7f3a 100644 --- a/plexams/exam.go +++ b/plexams/exam.go @@ -22,62 +22,104 @@ func (p *Plexams) prepareConnectedExam(ctx context.Context, ancode int, allProgr return nil, err } - allKeys := make(map[string]bool) - programs := []string{} - for _, group := range zpaExam.Groups { - program := group[:2] - if _, value := allKeys[program]; !value { - allKeys[program] = true - programs = append(programs, program) - } - } + // allKeys := make(map[string]bool) + // programs := []string{} + // for _, group := range zpaExam.Groups { + // program := group[:2] + // if _, value := allKeys[program]; !value { + // allKeys[program] = true + // programs = append(programs, program) + // } + // } primussExams := make([]*model.PrimussExam, 0) var errors []string - for _, program := range programs { - primussExam, err := p.GetPrimussExam(ctx, program, ancode) + // Replace with primuss ancodes + for _, primussAncode := range zpaExam.PrimussAncodes { + primussExam, err := p.GetPrimussExam(ctx, primussAncode.Program, primussAncode.Ancode) if err != nil { if errors == nil { errors = make([]string, 0) } - errors = append(errors, fmt.Sprintf("%s/%d not found", program, ancode)) + errors = append(errors, fmt.Sprintf("%s/%d not found", primussAncode.Program, primussAncode.Ancode)) } else { primussExams = append(primussExams, primussExam) } } - otherPrograms := make([]string, 0, len(allPrograms)-len(programs)) -OUTER: - for _, aP := range allPrograms { - for _, p := range programs { - if aP == p { - continue OUTER - } - } - otherPrograms = append(otherPrograms, aP) - } + // FIXME: I do not need other programs? + // otherPrograms := make([]string, 0, len(allPrograms)-len(programs)) + // OUTER: + // for _, aP := range allPrograms { + // for _, p := range programs { + // if aP == p { + // continue OUTER + // } + // } + // otherPrograms = append(otherPrograms, aP) + // } - var otherPrimussExams []*model.PrimussExam + // var otherPrimussExams []*model.PrimussExam + + // for _, program := range otherPrograms { + // primussExam, err := p.GetPrimussExam(ctx, program, ancode) + // if err == nil { + // if otherPrimussExams == nil { + // otherPrimussExams = make([]*model.PrimussExam, 0) + // } + // if errors == nil { + // errors = make([]string, 0) + // } + // errors = append(errors, fmt.Sprintf("found %s/%d (%s: %s)", program, ancode, primussExam.MainExamer, primussExam.Module)) + // otherPrimussExams = append(otherPrimussExams, primussExam) + // } + // } - for _, program := range otherPrograms { - primussExam, err := p.GetPrimussExam(ctx, program, ancode) - if err == nil { - if otherPrimussExams == nil { - otherPrimussExams = make([]*model.PrimussExam, 0) - } - if errors == nil { - errors = make([]string, 0) - } - errors = append(errors, fmt.Sprintf("found %s/%d (%s: %s)", program, ancode, primussExam.MainExamer, primussExam.Module)) - otherPrimussExams = append(otherPrimussExams, primussExam) - } - } + // Old version: + // for _, program := range programs { + // primussExam, err := p.GetPrimussExam(ctx, program, ancode) + // if err != nil { + // if errors == nil { + // errors = make([]string, 0) + // } + // errors = append(errors, fmt.Sprintf("%s/%d not found", program, ancode)) + // } else { + // primussExams = append(primussExams, primussExam) + // } + // } + + // otherPrograms := make([]string, 0, len(allPrograms)-len(programs)) + // OUTER: + // for _, aP := range allPrograms { + // for _, p := range programs { + // if aP == p { + // continue OUTER + // } + // } + // otherPrograms = append(otherPrograms, aP) + // } + + // var otherPrimussExams []*model.PrimussExam + + // for _, program := range otherPrograms { + // primussExam, err := p.GetPrimussExam(ctx, program, ancode) + // if err == nil { + // if otherPrimussExams == nil { + // otherPrimussExams = make([]*model.PrimussExam, 0) + // } + // if errors == nil { + // errors = make([]string, 0) + // } + // errors = append(errors, fmt.Sprintf("found %s/%d (%s: %s)", program, ancode, primussExam.MainExamer, primussExam.Module)) + // otherPrimussExams = append(otherPrimussExams, primussExam) + // } + // } return &model.ConnectedExam{ ZpaExam: zpaExam, PrimussExams: primussExams, - OtherPrimussExams: otherPrimussExams, + OtherPrimussExams: nil, // otherPrimussExams, Errors: errors, }, nil } From 540d7e615d9f2e4667497530e26155c7b6a5183d Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Fri, 17 Nov 2023 16:03:39 +0100 Subject: [PATCH 24/78] add other exams --- plexams/exam.go | 53 +++++++++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/plexams/exam.go b/plexams/exam.go index 4ff7f3a..383d96b 100644 --- a/plexams/exam.go +++ b/plexams/exam.go @@ -33,48 +33,41 @@ func (p *Plexams) prepareConnectedExam(ctx context.Context, ancode int, allProgr // } primussExams := make([]*model.PrimussExam, 0) - var errors []string + errors := make([]string, 0) // Replace with primuss ancodes for _, primussAncode := range zpaExam.PrimussAncodes { primussExam, err := p.GetPrimussExam(ctx, primussAncode.Program, primussAncode.Ancode) if err != nil { - if errors == nil { - errors = make([]string, 0) - } errors = append(errors, fmt.Sprintf("%s/%d not found", primussAncode.Program, primussAncode.Ancode)) } else { primussExams = append(primussExams, primussExam) } } - // FIXME: I do not need other programs? - // otherPrograms := make([]string, 0, len(allPrograms)-len(programs)) - // OUTER: - // for _, aP := range allPrograms { - // for _, p := range programs { - // if aP == p { - // continue OUTER - // } - // } - // otherPrograms = append(otherPrograms, aP) - // } + otherPrograms := make([]string, 0, len(allPrograms)-len(zpaExam.PrimussAncodes)) +OUTER: + for _, aP := range allPrograms { + for _, p := range zpaExam.PrimussAncodes { + if aP == p.Program { + continue OUTER + } + } + otherPrograms = append(otherPrograms, aP) + } - // var otherPrimussExams []*model.PrimussExam + var otherPrimussExams []*model.PrimussExam - // for _, program := range otherPrograms { - // primussExam, err := p.GetPrimussExam(ctx, program, ancode) - // if err == nil { - // if otherPrimussExams == nil { - // otherPrimussExams = make([]*model.PrimussExam, 0) - // } - // if errors == nil { - // errors = make([]string, 0) - // } - // errors = append(errors, fmt.Sprintf("found %s/%d (%s: %s)", program, ancode, primussExam.MainExamer, primussExam.Module)) - // otherPrimussExams = append(otherPrimussExams, primussExam) - // } - // } + for _, program := range otherPrograms { + primussExam, err := p.GetPrimussExam(ctx, program, ancode) + if err == nil { + if otherPrimussExams == nil { + otherPrimussExams = make([]*model.PrimussExam, 0) + } + errors = append(errors, fmt.Sprintf("found %s/%d (%s: %s)", program, ancode, primussExam.MainExamer, primussExam.Module)) + otherPrimussExams = append(otherPrimussExams, primussExam) + } + } // Old version: // for _, program := range programs { @@ -119,7 +112,7 @@ func (p *Plexams) prepareConnectedExam(ctx context.Context, ancode int, allProgr return &model.ConnectedExam{ ZpaExam: zpaExam, PrimussExams: primussExams, - OtherPrimussExams: nil, // otherPrimussExams, + OtherPrimussExams: otherPrimussExams, Errors: errors, }, nil } From 46b02835e15b47a5fec77b67098e0116e283c90a Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Fri, 17 Nov 2023 16:03:57 +0100 Subject: [PATCH 25/78] rm comments --- plexams/exam.go | 50 ------------------------------------------------- 1 file changed, 50 deletions(-) diff --git a/plexams/exam.go b/plexams/exam.go index 383d96b..6faa0e5 100644 --- a/plexams/exam.go +++ b/plexams/exam.go @@ -22,16 +22,6 @@ func (p *Plexams) prepareConnectedExam(ctx context.Context, ancode int, allProgr return nil, err } - // allKeys := make(map[string]bool) - // programs := []string{} - // for _, group := range zpaExam.Groups { - // program := group[:2] - // if _, value := allKeys[program]; !value { - // allKeys[program] = true - // programs = append(programs, program) - // } - // } - primussExams := make([]*model.PrimussExam, 0) errors := make([]string, 0) @@ -69,46 +59,6 @@ OUTER: } } - // Old version: - // for _, program := range programs { - // primussExam, err := p.GetPrimussExam(ctx, program, ancode) - // if err != nil { - // if errors == nil { - // errors = make([]string, 0) - // } - // errors = append(errors, fmt.Sprintf("%s/%d not found", program, ancode)) - // } else { - // primussExams = append(primussExams, primussExam) - // } - // } - - // otherPrograms := make([]string, 0, len(allPrograms)-len(programs)) - // OUTER: - // for _, aP := range allPrograms { - // for _, p := range programs { - // if aP == p { - // continue OUTER - // } - // } - // otherPrograms = append(otherPrograms, aP) - // } - - // var otherPrimussExams []*model.PrimussExam - - // for _, program := range otherPrograms { - // primussExam, err := p.GetPrimussExam(ctx, program, ancode) - // if err == nil { - // if otherPrimussExams == nil { - // otherPrimussExams = make([]*model.PrimussExam, 0) - // } - // if errors == nil { - // errors = make([]string, 0) - // } - // errors = append(errors, fmt.Sprintf("found %s/%d (%s: %s)", program, ancode, primussExam.MainExamer, primussExam.Module)) - // otherPrimussExams = append(otherPrimussExams, primussExam) - // } - // } - return &model.ConnectedExam{ ZpaExam: zpaExam, PrimussExams: primussExams, From 1a5d2b0c4592bb63412e35bdfe8bcf1361bb756b Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Fri, 17 Nov 2023 17:31:32 +0100 Subject: [PATCH 26/78] add external exam --- cmd/prepare.go | 69 ++++++++++--- db/collection.go | 1 + db/exam.go | 2 + db/external_exam.go | 19 ++++ graph/exam.graphqls | 13 +++ graph/generated/generated.go | 194 ++++++++++++++++++++++++++++++++++- graph/model/models_gen.go | 7 +- plexams/external_exam.go | 17 +++ 8 files changed, 305 insertions(+), 17 deletions(-) create mode 100644 db/external_exam.go create mode 100644 plexams/external_exam.go diff --git a/cmd/prepare.go b/cmd/prepare.go index 37684f5..6a8eade 100644 --- a/cmd/prepare.go +++ b/cmd/prepare.go @@ -1,6 +1,7 @@ package cmd import ( + "context" "fmt" "log" "os" @@ -17,12 +18,15 @@ var ( connected-exams --- prepare connected exams --- step 1 connect-exam ancode program --- connect an unconnected exam --- step 1,5 + add-external-exam program ancode duration --- add an external exam - studentregs --- regs per exam & regs per student --- step 2 + exams-to-plan --- generate exams from connected-exams and primuss-data --- step 2 + + # studentregs --- regs per exam & regs per student --- step 2 nta --- find NTAs for semester --- step 3 - exams-with-regs --- exams from connected-exams and studentregs --- step 4 + # exams-with-regs --- exams from connected-exams and studentregs --- step 4 exam-groups --- group of exams in the same slot --- step 5 -- according to constraints? - partition --- generate partition of groups --- step 6 + # partition --- generate partition of groups --- step 6 Add exam after planning has started: @@ -41,6 +45,39 @@ var ( Run: func(cmd *cobra.Command, args []string) { plexams := initPlexamsConfig() switch args[0] { + case "add-external-exam": + if len(args) < 4 { + log.Fatal("need program, ancode, and duration") + } + program := args[1] + ancode, err := strconv.Atoi(args[2]) + if err != nil { + fmt.Printf("cannot use %s as ancode", args[1]) + os.Exit(1) + } + duration, err := strconv.Atoi(args[3]) + if err != nil { + fmt.Printf("cannot use %s as duration", args[1]) + os.Exit(1) + } + + ctx := context.Background() + + primussExam, err := plexams.GetPrimussExam(ctx, program, ancode) + if err != nil { + log.Fatal(err) + } + + if !confirm(fmt.Sprintf("add external exam %s/%d. %s (%s)?", + primussExam.Program, primussExam.AnCode, primussExam.Module, primussExam.MainExamer), 10) { + os.Exit(0) + } + + err = plexams.AddExternalExam(ctx, primussExam, duration) + if err != nil { + os.Exit(1) + } + case "connected-exams": err := plexams.PrepareConnectedExams() if err != nil { @@ -77,17 +114,23 @@ var ( os.Exit(1) } - case "studentregs": // Deprecated: no longer needed - err := plexams.PrepareStudentRegs() - if err != nil { - os.Exit(1) - } + // case "studentregs": // Deprecated: no longer needed + // err := plexams.PrepareStudentRegs() + // if err != nil { + // os.Exit(1) + // } - case "exams-with-regs": // Deprecated: no longer needed - err := plexams.PrepareExamsWithRegs() - if err != nil { - os.Exit(1) - } + // case "exams-with-regs": // Deprecated: no longer needed + // err := plexams.PrepareExamsWithRegs() + // if err != nil { + // os.Exit(1) + // } + + // case "exams-to-plan": + // err := plexams.PrepareExamsToPlan() + // if err != nil { + // os.Exit(1) + // } case "exam-groups": err := plexams.PrepareExamGroups() diff --git a/db/collection.go b/db/collection.go index 7065fcc..a13076f 100644 --- a/db/collection.go +++ b/db/collection.go @@ -14,6 +14,7 @@ const ( collectionConstraints = "constraints" collectionNameExamGroups = "exam_groups" collectionNameAdditionalExams = "additional_exams" + collectionNameExternalExams = "external_exams" collectionNameConnectedExams = "connected_exams" collectionNameExamsWithRegs = "exams_with_regs" collectionNameNTAs = "nta" diff --git a/db/exam.go b/db/exam.go index c12da40..c0a0ecf 100644 --- a/db/exam.go +++ b/db/exam.go @@ -9,6 +9,7 @@ import ( "go.mongodb.org/mongo-driver/mongo/options" ) +// Deprecated: rm me func (db *DB) AddAdditionalExam(ctx context.Context, exam model.AdditionalExamInput) (bool, error) { collection := db.Client.Database(db.databaseName).Collection(collectionNameAdditionalExams) _, err := collection.InsertOne(ctx, exam) @@ -19,6 +20,7 @@ func (db *DB) AddAdditionalExam(ctx context.Context, exam model.AdditionalExamIn return true, nil } +// Deprecated: rm me func (db *DB) AdditionalExams(ctx context.Context) ([]*model.AdditionalExam, error) { collection := db.Client.Database(db.databaseName).Collection(collectionNameAdditionalExams) diff --git a/db/external_exam.go b/db/external_exam.go new file mode 100644 index 0000000..32ecd05 --- /dev/null +++ b/db/external_exam.go @@ -0,0 +1,19 @@ +package db + +import ( + "context" + + "github.com/obcode/plexams.go/graph/model" + "github.com/rs/zerolog/log" +) + +func (db *DB) AddExternalExam(ctx context.Context, exam *model.ExternalExam) error { + collection := db.Client.Database(db.databaseName).Collection(collectionNameExternalExams) + _, err := collection.InsertOne(ctx, exam) + if err != nil { + log.Error().Err(err).Interface("exam", exam). + Msg("cannot insert external exam to database") + } + + return err +} diff --git a/graph/exam.graphqls b/graph/exam.graphqls index 345bf54..4cb5057 100644 --- a/graph/exam.graphqls +++ b/graph/exam.graphqls @@ -88,6 +88,9 @@ type ExamWithRegsAndRooms { type ExternalExam { ancode: Int! program: String! + module: String! + mainExamer: String! + duration: Int! } type ConnectedExam { @@ -97,6 +100,16 @@ type ConnectedExam { errors: [String!]! } +# type ExamToPlan { +# ancode: Int! +# zpaExam: ZPAExam! +# primussExams: [PrimussExam!]! +# studentRegs: [StudentRegsPerAncodeAndProgram!]! +# conflicts: [ConflictsPerProgramAncode!]! +# connectErrors: [String!]! +# constraints: Constraints +# } + type Exam { ancode: Int! zpaExam: ZPAExam diff --git a/graph/generated/generated.go b/graph/generated/generated.go index e034a81..68b79e4 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -182,8 +182,11 @@ type ComplexityRoot struct { } ExternalExam struct { - Ancode func(childComplexity int) int - Program func(childComplexity int) int + Ancode func(childComplexity int) int + Duration func(childComplexity int) int + MainExamer func(childComplexity int) int + Module func(childComplexity int) int + Program func(childComplexity int) int } FK07Program struct { @@ -1258,6 +1261,27 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.ExternalExam.Ancode(childComplexity), true + case "ExternalExam.duration": + if e.complexity.ExternalExam.Duration == nil { + break + } + + return e.complexity.ExternalExam.Duration(childComplexity), true + + case "ExternalExam.mainExamer": + if e.complexity.ExternalExam.MainExamer == nil { + break + } + + return e.complexity.ExternalExam.MainExamer(childComplexity), true + + case "ExternalExam.module": + if e.complexity.ExternalExam.Module == nil { + break + } + + return e.complexity.ExternalExam.Module(childComplexity), true + case "ExternalExam.program": if e.complexity.ExternalExam.Program == nil { break @@ -3540,6 +3564,9 @@ type ExamWithRegsAndRooms { type ExternalExam { ancode: Int! program: String! + module: String! + mainExamer: String! + duration: Int! } type ConnectedExam { @@ -3549,6 +3576,16 @@ type ConnectedExam { errors: [String!]! } +# type ExamToPlan { +# ancode: Int! +# zpaExam: ZPAExam! +# primussExams: [PrimussExam!]! +# studentRegs: [StudentRegsPerAncodeAndProgram!]! +# conflicts: [ConflictsPerProgramAncode!]! +# connectErrors: [String!]! +# constraints: Constraints +# } + type Exam { ancode: Int! zpaExam: ZPAExam @@ -6616,6 +6653,12 @@ func (ec *executionContext) fieldContext_Exam_externalExam(ctx context.Context, return ec.fieldContext_ExternalExam_ancode(ctx, field) case "program": return ec.fieldContext_ExternalExam_program(ctx, field) + case "module": + return ec.fieldContext_ExternalExam_module(ctx, field) + case "mainExamer": + return ec.fieldContext_ExternalExam_mainExamer(ctx, field) + case "duration": + return ec.fieldContext_ExternalExam_duration(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type ExternalExam", field.Name) }, @@ -8984,6 +9027,138 @@ func (ec *executionContext) fieldContext_ExternalExam_program(ctx context.Contex return fc, nil } +func (ec *executionContext) _ExternalExam_module(ctx context.Context, field graphql.CollectedField, obj *model.ExternalExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ExternalExam_module(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Module, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ExternalExam_module(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ExternalExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _ExternalExam_mainExamer(ctx context.Context, field graphql.CollectedField, obj *model.ExternalExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ExternalExam_mainExamer(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.MainExamer, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ExternalExam_mainExamer(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ExternalExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _ExternalExam_duration(ctx context.Context, field graphql.CollectedField, obj *model.ExternalExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ExternalExam_duration(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Duration, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ExternalExam_duration(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ExternalExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _FK07Program_name(ctx context.Context, field graphql.CollectedField, obj *model.FK07Program) (ret graphql.Marshaler) { fc, err := ec.fieldContext_FK07Program_name(ctx, field) if err != nil { @@ -25532,6 +25707,21 @@ func (ec *executionContext) _ExternalExam(ctx context.Context, sel ast.Selection if out.Values[i] == graphql.Null { out.Invalids++ } + case "module": + out.Values[i] = ec._ExternalExam_module(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "mainExamer": + out.Values[i] = ec._ExternalExam_mainExamer(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "duration": + out.Values[i] = ec._ExternalExam_duration(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index ec1a5e4..5f6e170 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -138,8 +138,11 @@ type ExamerInPlan struct { } type ExternalExam struct { - Ancode int `json:"ancode"` - Program string `json:"program"` + Ancode int `json:"ancode"` + Program string `json:"program"` + Module string `json:"module"` + MainExamer string `json:"mainExamer"` + Duration int `json:"duration"` } type FK07Program struct { diff --git a/plexams/external_exam.go b/plexams/external_exam.go new file mode 100644 index 0000000..ddda869 --- /dev/null +++ b/plexams/external_exam.go @@ -0,0 +1,17 @@ +package plexams + +import ( + "context" + + "github.com/obcode/plexams.go/graph/model" +) + +func (p *Plexams) AddExternalExam(ctx context.Context, primussExam *model.PrimussExam, duration int) error { + return p.dbClient.AddExternalExam(ctx, &model.ExternalExam{ + Ancode: primussExam.AnCode, + Program: primussExam.Program, + Module: primussExam.Module, + MainExamer: primussExam.MainExamer, + Duration: duration, + }) +} From 1cd599fe709d30b8f59b87584d08f422e1b8dc69 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Fri, 17 Nov 2023 17:33:52 +0100 Subject: [PATCH 27/78] make linter happy --- cmd/prepare.go | 2 +- plexams/exam.go | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cmd/prepare.go b/cmd/prepare.go index 6a8eade..4655044 100644 --- a/cmd/prepare.go +++ b/cmd/prepare.go @@ -20,7 +20,7 @@ var ( add-external-exam program ancode duration --- add an external exam - exams-to-plan --- generate exams from connected-exams and primuss-data --- step 2 + exams-to-plan --- generate exams from connected-exams, external-exams and primuss-data --- step 2 # studentregs --- regs per exam & regs per student --- step 2 nta --- find NTAs for semester --- step 3 diff --git a/plexams/exam.go b/plexams/exam.go index 6faa0e5..8aacccd 100644 --- a/plexams/exam.go +++ b/plexams/exam.go @@ -8,10 +8,12 @@ import ( "github.com/rs/zerolog/log" ) +// Deprecated: rm me func (p *Plexams) AddAdditionalExam(ctx context.Context, exam model.AdditionalExamInput) (bool, error) { return p.dbClient.AddAdditionalExam(ctx, exam) } +// Deprecated: rm me func (p *Plexams) AdditionalExams(ctx context.Context) ([]*model.AdditionalExam, error) { return p.dbClient.AdditionalExams(ctx) } From 276ce30c12e1ad0d2ce3890420b68741aa9a43bb Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Fri, 17 Nov 2023 19:30:59 +0100 Subject: [PATCH 28/78] get external exams --- db/external_exam.go | 21 +++++ graph/exam.graphqls | 2 + graph/exam.resolvers.go | 5 ++ graph/generated/generated.go | 143 +++++++++++++++++++++++++++++++++++ plexams/external_exam.go | 4 + 5 files changed, 175 insertions(+) diff --git a/db/external_exam.go b/db/external_exam.go index 32ecd05..15d2168 100644 --- a/db/external_exam.go +++ b/db/external_exam.go @@ -5,6 +5,7 @@ import ( "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" + "go.mongodb.org/mongo-driver/bson" ) func (db *DB) AddExternalExam(ctx context.Context, exam *model.ExternalExam) error { @@ -17,3 +18,23 @@ func (db *DB) AddExternalExam(ctx context.Context, exam *model.ExternalExam) err return err } + +func (db *DB) ExternalExams(ctx context.Context) ([]*model.ExternalExam, error) { + collection := db.Client.Database(db.databaseName).Collection(collectionNameExternalExams) + + cur, err := collection.Find(ctx, bson.M{}) + if err != nil { + log.Error().Err(err).Msg("cannot get external exams") + return nil, err + } + defer cur.Close(ctx) + + var result []*model.ExternalExam + err = cur.All(ctx, &result) + if err != nil { + log.Error().Err(err).Msg("cannot decode external exams") + return nil, err + } + + return result, nil +} diff --git a/graph/exam.graphqls b/graph/exam.graphqls index 4cb5057..90f84a2 100644 --- a/graph/exam.graphqls +++ b/graph/exam.graphqls @@ -2,6 +2,8 @@ extend type Query { connectedExam(ancode: Int!): ConnectedExam connectedExams: [ConnectedExam!]! + externalExams: [ExternalExam!]! + exam(ancode: Int!): Exam exams: [Exam!]! } diff --git a/graph/exam.resolvers.go b/graph/exam.resolvers.go index 3d302bd..13ec3a1 100644 --- a/graph/exam.resolvers.go +++ b/graph/exam.resolvers.go @@ -20,6 +20,11 @@ func (r *queryResolver) ConnectedExams(ctx context.Context) ([]*model.ConnectedE return r.plexams.GetConnectedExams(ctx) } +// ExternalExams is the resolver for the externalExams field. +func (r *queryResolver) ExternalExams(ctx context.Context) ([]*model.ExternalExam, error) { + return r.plexams.ExternalExams(ctx) +} + // Exam is the resolver for the exam field. func (r *queryResolver) Exam(ctx context.Context, ancode int) (*model.Exam, error) { exam, err := r.plexams.CachedExam(ctx, ancode) diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 68b79e4..d92a7b1 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -362,6 +362,7 @@ type ComplexityRoot struct { ExamsInSlot func(childComplexity int, day int, time int) int ExamsInSlotWithRooms func(childComplexity int, day int, time int) int ExamsWithRegs func(childComplexity int) int + ExternalExams func(childComplexity int) int Fk07programs func(childComplexity int) int InvigilatorTodos func(childComplexity int) int Invigilators func(childComplexity int) int @@ -658,6 +659,7 @@ type QueryResolver interface { DayOkForInvigilator(ctx context.Context, day int, invigilatorID int) (*bool, error) ConnectedExam(ctx context.Context, ancode int) (*model.ConnectedExam, error) ConnectedExams(ctx context.Context) ([]*model.ConnectedExam, error) + ExternalExams(ctx context.Context) ([]*model.ExternalExam, error) Exam(ctx context.Context, ancode int) (*model.Exam, error) Exams(ctx context.Context) ([]*model.Exam, error) StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, error) @@ -2270,6 +2272,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.ExamsWithRegs(childComplexity), true + case "Query.externalExams": + if e.complexity.Query.ExternalExams == nil { + break + } + + return e.complexity.Query.ExternalExams(childComplexity), true + case "Query.fk07programs": if e.complexity.Query.Fk07programs == nil { break @@ -3478,6 +3487,8 @@ var sources = []*ast.Source{ connectedExam(ancode: Int!): ConnectedExam connectedExams: [ConnectedExam!]! + externalExams: [ExternalExam!]! + exam(ancode: Int!): Exam exams: [Exam!]! } @@ -16392,6 +16403,62 @@ func (ec *executionContext) fieldContext_Query_connectedExams(ctx context.Contex return fc, nil } +func (ec *executionContext) _Query_externalExams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_externalExams(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().ExternalExams(rctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.ExternalExam) + fc.Result = res + return ec.marshalNExternalExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExternalExamᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_externalExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "ancode": + return ec.fieldContext_ExternalExam_ancode(ctx, field) + case "program": + return ec.fieldContext_ExternalExam_program(ctx, field) + case "module": + return ec.fieldContext_ExternalExam_module(ctx, field) + case "mainExamer": + return ec.fieldContext_ExternalExam_mainExamer(ctx, field) + case "duration": + return ec.fieldContext_ExternalExam_duration(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ExternalExam", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _Query_exam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_exam(ctx, field) if err != nil { @@ -27791,6 +27858,28 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "externalExams": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_externalExams(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "exam": field := field @@ -30487,6 +30576,60 @@ func (ec *executionContext) marshalNExamerInPlan2ᚖgithubᚗcomᚋobcodeᚋplex return ec._ExamerInPlan(ctx, sel, v) } +func (ec *executionContext) marshalNExternalExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExternalExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExternalExam) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNExternalExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExternalExam(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNExternalExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExternalExam(ctx context.Context, sel ast.SelectionSet, v *model.ExternalExam) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._ExternalExam(ctx, sel, v) +} + func (ec *executionContext) marshalNFK07Program2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐFK07Programᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.FK07Program) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup diff --git a/plexams/external_exam.go b/plexams/external_exam.go index ddda869..77f7372 100644 --- a/plexams/external_exam.go +++ b/plexams/external_exam.go @@ -15,3 +15,7 @@ func (p *Plexams) AddExternalExam(ctx context.Context, primussExam *model.Primus Duration: duration, }) } + +func (p *Plexams) ExternalExams(ctx context.Context) ([]*model.ExternalExam, error) { + return p.dbClient.ExternalExams(ctx) +} From a095f7b2a531f49fde80d795cfe463262c307087 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Sat, 18 Nov 2023 15:13:49 +0100 Subject: [PATCH 29/78] generated exams --- .vscode/launch.json | 31 +- cmd/prepare.go | 12 +- db/collection.go | 3 +- db/generatedExams.go | 32 + graph/exam.graphqls | 24 +- graph/exam.resolvers.go | 6 + graph/generated/generated.go | 1784 ++++++++++++++++++++++++++++------ graph/model/models_gen.go | 26 + graph/primuss.graphqls | 12 +- graph/primuss.resolvers.go | 27 - plexams/constraints.go | 15 + plexams/generatedExams.go | 217 +++++ 12 files changed, 1828 insertions(+), 361 deletions(-) create mode 100644 db/generatedExams.go delete mode 100644 graph/primuss.resolvers.go create mode 100644 plexams/generatedExams.go diff --git a/.vscode/launch.json b/.vscode/launch.json index 0306fca..bfd858e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,17 +1,16 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Debug plexams.go", - "type": "go", - "request": "launch", - "mode": "debug", - "program": "main.go", - "args": ["validate", "all"] - } - - ] -} \ No newline at end of file + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Debug plexams.go", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "main.go", + "args": [] + } + ] +} diff --git a/cmd/prepare.go b/cmd/prepare.go index 4655044..d74c4f7 100644 --- a/cmd/prepare.go +++ b/cmd/prepare.go @@ -20,7 +20,7 @@ var ( add-external-exam program ancode duration --- add an external exam - exams-to-plan --- generate exams from connected-exams, external-exams and primuss-data --- step 2 + generated-exams --- generate exams from connected-exams, external-exams and primuss-data --- step 2 # studentregs --- regs per exam & regs per student --- step 2 nta --- find NTAs for semester --- step 3 @@ -126,11 +126,11 @@ var ( // os.Exit(1) // } - // case "exams-to-plan": - // err := plexams.PrepareExamsToPlan() - // if err != nil { - // os.Exit(1) - // } + case "generated-exams": + err := plexams.PrepareGeneratedExams() + if err != nil { + os.Exit(1) + } case "exam-groups": err := plexams.PrepareExamGroups() diff --git a/db/collection.go b/db/collection.go index a13076f..9dc34e5 100644 --- a/db/collection.go +++ b/db/collection.go @@ -33,7 +33,8 @@ const ( collectionExamsInPlan = "exams_in_plan" - collectionCachedExams = "cached_exams" + collectionCachedExams = "cached_exams" + collectionGeneratedExams = "generated_exams" collectionRooms = "rooms" collectionRoomsPlanned = "rooms_planned" diff --git a/db/generatedExams.go b/db/generatedExams.go new file mode 100644 index 0000000..53e95db --- /dev/null +++ b/db/generatedExams.go @@ -0,0 +1,32 @@ +package db + +import ( + "context" + + "github.com/obcode/plexams.go/graph/model" + "github.com/rs/zerolog/log" +) + +func (db *DB) CacheGeneratedExams(ctx context.Context, exams []*model.GeneratedExam) error { + collection := db.Client.Database(db.databaseName).Collection(collectionGeneratedExams) + + err := collection.Drop(ctx) + if err != nil { + log.Error().Err(err).Str("collection", collectionGeneratedExams).Msg("cannot drop collection") + return err + } + + examsIntf := make([]interface{}, 0, len(exams)) + for _, exam := range exams { + examsIntf = append(examsIntf, exam) + } + + res, err := collection.InsertMany(ctx, examsIntf) + if err != nil { + log.Error().Err(err).Str("collection", collectionGeneratedExams).Msg("cannot insert generated exams") + return err + } + + log.Debug().Int("count", len(res.InsertedIDs)).Msg("successfully inserted generated exams") + return nil +} diff --git a/graph/exam.graphqls b/graph/exam.graphqls index 90f84a2..fedf19e 100644 --- a/graph/exam.graphqls +++ b/graph/exam.graphqls @@ -4,6 +4,8 @@ extend type Query { externalExams: [ExternalExam!]! + generatedExams: [GeneratedExam!]! + exam(ancode: Int!): Exam exams: [Exam!]! } @@ -102,15 +104,19 @@ type ConnectedExam { errors: [String!]! } -# type ExamToPlan { -# ancode: Int! -# zpaExam: ZPAExam! -# primussExams: [PrimussExam!]! -# studentRegs: [StudentRegsPerAncodeAndProgram!]! -# conflicts: [ConflictsPerProgramAncode!]! -# connectErrors: [String!]! -# constraints: Constraints -# } +type GeneratedExam { + ancode: Int! + zpaExam: ZPAExam! + primussExams: [EnhancedPrimussExam!]! + constraints: Constraints + conflicts: [ZPAConflict!]! +} + +type ZPAConflict { + ancode: Int! + numberOfStuds: Int! + primussAncodes: [PrimussExamAncode!]! +} type Exam { ancode: Int! diff --git a/graph/exam.resolvers.go b/graph/exam.resolvers.go index 13ec3a1..2ca6ac0 100644 --- a/graph/exam.resolvers.go +++ b/graph/exam.resolvers.go @@ -6,6 +6,7 @@ package graph import ( "context" + "fmt" "github.com/obcode/plexams.go/graph/model" ) @@ -25,6 +26,11 @@ func (r *queryResolver) ExternalExams(ctx context.Context) ([]*model.ExternalExa return r.plexams.ExternalExams(ctx) } +// GeneratedExams is the resolver for the generatedExams field. +func (r *queryResolver) GeneratedExams(ctx context.Context) ([]*model.GeneratedExam, error) { + panic(fmt.Errorf("not implemented: GeneratedExams - generatedExams")) +} + // Exam is the resolver for the exam field. func (r *queryResolver) Exam(ctx context.Context, ancode int) (*model.Exam, error) { exam, err := r.plexams.CachedExam(ctx, ancode) diff --git a/graph/generated/generated.go b/graph/generated/generated.go index d92a7b1..d1d4c45 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -38,7 +38,6 @@ type Config struct { type ResolverRoot interface { Mutation() MutationResolver - PrimussExam() PrimussExamResolver Query() QueryResolver RoomForExam() RoomForExamResolver } @@ -103,6 +102,13 @@ type ComplexityRoot struct { SameSlot func(childComplexity int) int } + EnhancedPrimussExam struct { + Conflicts func(childComplexity int) int + Exam func(childComplexity int) int + Ntas func(childComplexity int) int + StudentRegs func(childComplexity int) int + } + Exam struct { Ancode func(childComplexity int) int Conflicts func(childComplexity int) int @@ -193,6 +199,14 @@ type ComplexityRoot struct { Name func(childComplexity int) int } + GeneratedExam struct { + Ancode func(childComplexity int) int + Conflicts func(childComplexity int) int + Constraints func(childComplexity int) int + PrimussExams func(childComplexity int) int + ZpaExam func(childComplexity int) int + } + Invigilation struct { Duration func(childComplexity int) int InvigilatorID func(childComplexity int) int @@ -323,14 +337,17 @@ type ComplexityRoot struct { } PrimussExam struct { - AnCode func(childComplexity int) int - Conflicts func(childComplexity int) int - ExamType func(childComplexity int) int - MainExamer func(childComplexity int) int - Module func(childComplexity int) int - Presence func(childComplexity int) int - Program func(childComplexity int) int - StudentRegs func(childComplexity int) int + AnCode func(childComplexity int) int + ExamType func(childComplexity int) int + MainExamer func(childComplexity int) int + Module func(childComplexity int) int + Presence func(childComplexity int) int + Program func(childComplexity int) int + } + + PrimussExamAncode struct { + Ancode func(childComplexity int) int + Program func(childComplexity int) int } PrimussExamByProgram struct { @@ -364,6 +381,7 @@ type ComplexityRoot struct { ExamsWithRegs func(childComplexity int) int ExternalExams func(childComplexity int) int Fk07programs func(childComplexity int) int + GeneratedExams func(childComplexity int) int InvigilatorTodos func(childComplexity int) int Invigilators func(childComplexity int) int InvigilatorsForDay func(childComplexity int, day int) int @@ -539,6 +557,12 @@ type ComplexityRoot struct { Shortname func(childComplexity int) int } + ZPAConflict struct { + Ancode func(childComplexity int) int + NumberOfStuds func(childComplexity int) int + PrimussAncodes func(childComplexity int) int + } + ZPAExam struct { AnCode func(childComplexity int) int Duration func(childComplexity int) int @@ -610,10 +634,6 @@ type MutationResolver interface { RmExamGroupFromSlot(ctx context.Context, examGroupCode int) (bool, error) AddRoomToExam(ctx context.Context, input model.RoomForExamInput) (bool, error) } -type PrimussExamResolver interface { - StudentRegs(ctx context.Context, obj *model.PrimussExam) ([]*model.StudentReg, error) - Conflicts(ctx context.Context, obj *model.PrimussExam) (*model.Conflicts, error) -} type QueryResolver interface { Workflow(ctx context.Context) ([]*model.Step, error) NextDeadline(ctx context.Context) (*model.Step, error) @@ -660,6 +680,7 @@ type QueryResolver interface { ConnectedExam(ctx context.Context, ancode int) (*model.ConnectedExam, error) ConnectedExams(ctx context.Context) ([]*model.ConnectedExam, error) ExternalExams(ctx context.Context) ([]*model.ExternalExam, error) + GeneratedExams(ctx context.Context) ([]*model.GeneratedExam, error) Exam(ctx context.Context, ancode int) (*model.Exam, error) Exams(ctx context.Context) ([]*model.Exam, error) StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, error) @@ -920,6 +941,34 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Constraints.SameSlot(childComplexity), true + case "EnhancedPrimussExam.conflicts": + if e.complexity.EnhancedPrimussExam.Conflicts == nil { + break + } + + return e.complexity.EnhancedPrimussExam.Conflicts(childComplexity), true + + case "EnhancedPrimussExam.exam": + if e.complexity.EnhancedPrimussExam.Exam == nil { + break + } + + return e.complexity.EnhancedPrimussExam.Exam(childComplexity), true + + case "EnhancedPrimussExam.ntas": + if e.complexity.EnhancedPrimussExam.Ntas == nil { + break + } + + return e.complexity.EnhancedPrimussExam.Ntas(childComplexity), true + + case "EnhancedPrimussExam.studentRegs": + if e.complexity.EnhancedPrimussExam.StudentRegs == nil { + break + } + + return e.complexity.EnhancedPrimussExam.StudentRegs(childComplexity), true + case "Exam.ancode": if e.complexity.Exam.Ancode == nil { break @@ -1298,6 +1347,41 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.FK07Program.Name(childComplexity), true + case "GeneratedExam.ancode": + if e.complexity.GeneratedExam.Ancode == nil { + break + } + + return e.complexity.GeneratedExam.Ancode(childComplexity), true + + case "GeneratedExam.conflicts": + if e.complexity.GeneratedExam.Conflicts == nil { + break + } + + return e.complexity.GeneratedExam.Conflicts(childComplexity), true + + case "GeneratedExam.constraints": + if e.complexity.GeneratedExam.Constraints == nil { + break + } + + return e.complexity.GeneratedExam.Constraints(childComplexity), true + + case "GeneratedExam.primussExams": + if e.complexity.GeneratedExam.PrimussExams == nil { + break + } + + return e.complexity.GeneratedExam.PrimussExams(childComplexity), true + + case "GeneratedExam.zpaExam": + if e.complexity.GeneratedExam.ZpaExam == nil { + break + } + + return e.complexity.GeneratedExam.ZpaExam(childComplexity), true + case "Invigilation.duration": if e.complexity.Invigilation.Duration == nil { break @@ -1988,13 +2072,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PrimussExam.AnCode(childComplexity), true - case "PrimussExam.conflicts": - if e.complexity.PrimussExam.Conflicts == nil { - break - } - - return e.complexity.PrimussExam.Conflicts(childComplexity), true - case "PrimussExam.examType": if e.complexity.PrimussExam.ExamType == nil { break @@ -2030,12 +2107,19 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PrimussExam.Program(childComplexity), true - case "PrimussExam.studentRegs": - if e.complexity.PrimussExam.StudentRegs == nil { + case "PrimussExamAncode.ancode": + if e.complexity.PrimussExamAncode.Ancode == nil { break } - return e.complexity.PrimussExam.StudentRegs(childComplexity), true + return e.complexity.PrimussExamAncode.Ancode(childComplexity), true + + case "PrimussExamAncode.program": + if e.complexity.PrimussExamAncode.Program == nil { + break + } + + return e.complexity.PrimussExamAncode.Program(childComplexity), true case "PrimussExamByProgram.exams": if e.complexity.PrimussExamByProgram.Exams == nil { @@ -2286,6 +2370,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.Fk07programs(childComplexity), true + case "Query.generatedExams": + if e.complexity.Query.GeneratedExams == nil { + break + } + + return e.complexity.Query.GeneratedExams(childComplexity), true + case "Query.invigilatorTodos": if e.complexity.Query.InvigilatorTodos == nil { break @@ -3178,6 +3269,27 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Teacher.Shortname(childComplexity), true + case "ZPAConflict.ancode": + if e.complexity.ZPAConflict.Ancode == nil { + break + } + + return e.complexity.ZPAConflict.Ancode(childComplexity), true + + case "ZPAConflict.numberOfStuds": + if e.complexity.ZPAConflict.NumberOfStuds == nil { + break + } + + return e.complexity.ZPAConflict.NumberOfStuds(childComplexity), true + + case "ZPAConflict.primussAncodes": + if e.complexity.ZPAConflict.PrimussAncodes == nil { + break + } + + return e.complexity.ZPAConflict.PrimussAncodes(childComplexity), true + case "ZPAExam.ancode": if e.complexity.ZPAExam.AnCode == nil { break @@ -3489,6 +3601,8 @@ var sources = []*ast.Source{ externalExams: [ExternalExam!]! + generatedExams: [GeneratedExam!]! + exam(ancode: Int!): Exam exams: [Exam!]! } @@ -3587,15 +3701,19 @@ type ConnectedExam { errors: [String!]! } -# type ExamToPlan { -# ancode: Int! -# zpaExam: ZPAExam! -# primussExams: [PrimussExam!]! -# studentRegs: [StudentRegsPerAncodeAndProgram!]! -# conflicts: [ConflictsPerProgramAncode!]! -# connectErrors: [String!]! -# constraints: Constraints -# } +type GeneratedExam { + ancode: Int! + zpaExam: ZPAExam! + primussExams: [EnhancedPrimussExam!]! + constraints: Constraints + conflicts: [ZPAConflict!]! +} + +type ZPAConflict { + ancode: Int! + numberOfStuds: Int! + primussAncodes: [PrimussExamAncode!]! +} type Exam { ancode: Int! @@ -3832,8 +3950,18 @@ type ExamerInPlan { program: String! examType: String! presence: String! +} + +type EnhancedPrimussExam { + exam: PrimussExam! studentRegs: [StudentReg!]! - conflicts: Conflicts! + conflicts: [Conflict!]! + ntas: [NTA!]! +} + +type PrimussExamAncode { + ancode: Int! + program: String! } input PrimussExamInput { @@ -6008,10 +6136,6 @@ func (ec *executionContext) fieldContext_ConnectedExam_primussExams(ctx context. return ec.fieldContext_PrimussExam_examType(ctx, field) case "presence": return ec.fieldContext_PrimussExam_presence(ctx, field) - case "studentRegs": - return ec.fieldContext_PrimussExam_studentRegs(ctx, field) - case "conflicts": - return ec.fieldContext_PrimussExam_conflicts(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type PrimussExam", field.Name) }, @@ -6070,10 +6194,6 @@ func (ec *executionContext) fieldContext_ConnectedExam_otherPrimussExams(ctx con return ec.fieldContext_PrimussExam_examType(ctx, field) case "presence": return ec.fieldContext_PrimussExam_presence(ctx, field) - case "studentRegs": - return ec.fieldContext_PrimussExam_studentRegs(ctx, field) - case "conflicts": - return ec.fieldContext_PrimussExam_conflicts(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type PrimussExam", field.Name) }, @@ -6513,8 +6633,8 @@ func (ec *executionContext) fieldContext_Constraints_roomConstraints(ctx context return fc, nil } -func (ec *executionContext) _Exam_ancode(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Exam_ancode(ctx, field) +func (ec *executionContext) _EnhancedPrimussExam_exam(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPrimussExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_EnhancedPrimussExam_exam(ctx, field) if err != nil { return graphql.Null } @@ -6527,7 +6647,7 @@ func (ec *executionContext) _Exam_ancode(ctx context.Context, field graphql.Coll }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Ancode, nil + return obj.Exam, nil }) if err != nil { ec.Error(ctx, err) @@ -6539,26 +6659,40 @@ func (ec *executionContext) _Exam_ancode(ctx context.Context, field graphql.Coll } return graphql.Null } - res := resTmp.(int) + res := resTmp.(*model.PrimussExam) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Exam_ancode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EnhancedPrimussExam_exam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Exam", + Object: "EnhancedPrimussExam", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") + switch field.Name { + case "ancode": + return ec.fieldContext_PrimussExam_ancode(ctx, field) + case "module": + return ec.fieldContext_PrimussExam_module(ctx, field) + case "mainExamer": + return ec.fieldContext_PrimussExam_mainExamer(ctx, field) + case "program": + return ec.fieldContext_PrimussExam_program(ctx, field) + case "examType": + return ec.fieldContext_PrimussExam_examType(ctx, field) + case "presence": + return ec.fieldContext_PrimussExam_presence(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type PrimussExam", field.Name) }, } return fc, nil } -func (ec *executionContext) _Exam_zpaExam(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Exam_zpaExam(ctx, field) +func (ec *executionContext) _EnhancedPrimussExam_studentRegs(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPrimussExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_EnhancedPrimussExam_studentRegs(ctx, field) if err != nil { return graphql.Null } @@ -6571,61 +6705,52 @@ func (ec *executionContext) _Exam_zpaExam(ctx context.Context, field graphql.Col }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.ZpaExam, nil + return obj.StudentRegs, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*model.ZPAExam) + res := resTmp.([]*model.StudentReg) fc.Result = res - return ec.marshalOZPAExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExam(ctx, field.Selections, res) + return ec.marshalNStudentReg2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentRegᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Exam_zpaExam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EnhancedPrimussExam_studentRegs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Exam", + Object: "EnhancedPrimussExam", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "zpaID": - return ec.fieldContext_ZPAExam_zpaID(ctx, field) - case "semester": - return ec.fieldContext_ZPAExam_semester(ctx, field) + case "mtknr": + return ec.fieldContext_StudentReg_mtknr(ctx, field) case "ancode": - return ec.fieldContext_ZPAExam_ancode(ctx, field) - case "module": - return ec.fieldContext_ZPAExam_module(ctx, field) - case "mainExamer": - return ec.fieldContext_ZPAExam_mainExamer(ctx, field) - case "mainExamerID": - return ec.fieldContext_ZPAExam_mainExamerID(ctx, field) - case "examType": - return ec.fieldContext_ZPAExam_examType(ctx, field) - case "examTypeFull": - return ec.fieldContext_ZPAExam_examTypeFull(ctx, field) - case "duration": - return ec.fieldContext_ZPAExam_duration(ctx, field) - case "isRepeaterExam": - return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) - case "groups": - return ec.fieldContext_ZPAExam_groups(ctx, field) - case "primussAncodes": - return ec.fieldContext_ZPAExam_primussAncodes(ctx, field) + return ec.fieldContext_StudentReg_ancode(ctx, field) + case "program": + return ec.fieldContext_StudentReg_program(ctx, field) + case "group": + return ec.fieldContext_StudentReg_group(ctx, field) + case "name": + return ec.fieldContext_StudentReg_name(ctx, field) + case "presence": + return ec.fieldContext_StudentReg_presence(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) + return nil, fmt.Errorf("no field named %q was found under type StudentReg", field.Name) }, } return fc, nil } -func (ec *executionContext) _Exam_externalExam(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Exam_externalExam(ctx, field) +func (ec *executionContext) _EnhancedPrimussExam_conflicts(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPrimussExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_EnhancedPrimussExam_conflicts(ctx, field) if err != nil { return graphql.Null } @@ -6638,47 +6763,44 @@ func (ec *executionContext) _Exam_externalExam(ctx context.Context, field graphq }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.ExternalExam, nil + return obj.Conflicts, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*model.ExternalExam) + res := resTmp.([]*model.Conflict) fc.Result = res - return ec.marshalOExternalExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExternalExam(ctx, field.Selections, res) + return ec.marshalNConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Exam_externalExam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EnhancedPrimussExam_conflicts(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Exam", + Object: "EnhancedPrimussExam", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { case "ancode": - return ec.fieldContext_ExternalExam_ancode(ctx, field) - case "program": - return ec.fieldContext_ExternalExam_program(ctx, field) - case "module": - return ec.fieldContext_ExternalExam_module(ctx, field) - case "mainExamer": - return ec.fieldContext_ExternalExam_mainExamer(ctx, field) - case "duration": - return ec.fieldContext_ExternalExam_duration(ctx, field) + return ec.fieldContext_Conflict_ancode(ctx, field) + case "numberOfStuds": + return ec.fieldContext_Conflict_numberOfStuds(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ExternalExam", field.Name) + return nil, fmt.Errorf("no field named %q was found under type Conflict", field.Name) }, } return fc, nil } -func (ec *executionContext) _Exam_primussExams(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Exam_primussExams(ctx, field) +func (ec *executionContext) _EnhancedPrimussExam_ntas(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPrimussExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_EnhancedPrimussExam_ntas(ctx, field) if err != nil { return graphql.Null } @@ -6691,7 +6813,7 @@ func (ec *executionContext) _Exam_primussExams(ctx context.Context, field graphq }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.PrimussExams, nil + return obj.Ntas, nil }) if err != nil { ec.Error(ctx, err) @@ -6703,44 +6825,48 @@ func (ec *executionContext) _Exam_primussExams(ctx context.Context, field graphq } return graphql.Null } - res := resTmp.([]*model.PrimussExam) + res := resTmp.([]*model.NTA) fc.Result = res - return ec.marshalNPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamᚄ(ctx, field.Selections, res) + return ec.marshalNNTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Exam_primussExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EnhancedPrimussExam_ntas(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Exam", + Object: "EnhancedPrimussExam", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "ancode": - return ec.fieldContext_PrimussExam_ancode(ctx, field) - case "module": - return ec.fieldContext_PrimussExam_module(ctx, field) - case "mainExamer": - return ec.fieldContext_PrimussExam_mainExamer(ctx, field) + case "name": + return ec.fieldContext_NTA_name(ctx, field) + case "mtknr": + return ec.fieldContext_NTA_mtknr(ctx, field) + case "compensation": + return ec.fieldContext_NTA_compensation(ctx, field) + case "deltaDurationPercent": + return ec.fieldContext_NTA_deltaDurationPercent(ctx, field) + case "needsRoomAlone": + return ec.fieldContext_NTA_needsRoomAlone(ctx, field) case "program": - return ec.fieldContext_PrimussExam_program(ctx, field) - case "examType": - return ec.fieldContext_PrimussExam_examType(ctx, field) - case "presence": - return ec.fieldContext_PrimussExam_presence(ctx, field) - case "studentRegs": - return ec.fieldContext_PrimussExam_studentRegs(ctx, field) - case "conflicts": - return ec.fieldContext_PrimussExam_conflicts(ctx, field) + return ec.fieldContext_NTA_program(ctx, field) + case "from": + return ec.fieldContext_NTA_from(ctx, field) + case "until": + return ec.fieldContext_NTA_until(ctx, field) + case "lastSemester": + return ec.fieldContext_NTA_lastSemester(ctx, field) + case "exams": + return ec.fieldContext_NTA_exams(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type PrimussExam", field.Name) + return nil, fmt.Errorf("no field named %q was found under type NTA", field.Name) }, } return fc, nil } -func (ec *executionContext) _Exam_studentRegs(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Exam_studentRegs(ctx, field) +func (ec *executionContext) _Exam_ancode(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Exam_ancode(ctx, field) if err != nil { return graphql.Null } @@ -6753,7 +6879,7 @@ func (ec *executionContext) _Exam_studentRegs(ctx context.Context, field graphql }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.StudentRegs, nil + return obj.Ancode, nil }) if err != nil { ec.Error(ctx, err) @@ -6765,7 +6891,229 @@ func (ec *executionContext) _Exam_studentRegs(ctx context.Context, field graphql } return graphql.Null } - res := resTmp.([]*model.StudentRegsPerAncodeAndProgram) + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Exam_ancode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Exam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Exam_zpaExam(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Exam_zpaExam(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ZpaExam, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.ZPAExam) + fc.Result = res + return ec.marshalOZPAExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExam(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Exam_zpaExam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Exam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "zpaID": + return ec.fieldContext_ZPAExam_zpaID(ctx, field) + case "semester": + return ec.fieldContext_ZPAExam_semester(ctx, field) + case "ancode": + return ec.fieldContext_ZPAExam_ancode(ctx, field) + case "module": + return ec.fieldContext_ZPAExam_module(ctx, field) + case "mainExamer": + return ec.fieldContext_ZPAExam_mainExamer(ctx, field) + case "mainExamerID": + return ec.fieldContext_ZPAExam_mainExamerID(ctx, field) + case "examType": + return ec.fieldContext_ZPAExam_examType(ctx, field) + case "examTypeFull": + return ec.fieldContext_ZPAExam_examTypeFull(ctx, field) + case "duration": + return ec.fieldContext_ZPAExam_duration(ctx, field) + case "isRepeaterExam": + return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) + case "groups": + return ec.fieldContext_ZPAExam_groups(ctx, field) + case "primussAncodes": + return ec.fieldContext_ZPAExam_primussAncodes(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Exam_externalExam(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Exam_externalExam(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ExternalExam, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.ExternalExam) + fc.Result = res + return ec.marshalOExternalExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExternalExam(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Exam_externalExam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Exam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "ancode": + return ec.fieldContext_ExternalExam_ancode(ctx, field) + case "program": + return ec.fieldContext_ExternalExam_program(ctx, field) + case "module": + return ec.fieldContext_ExternalExam_module(ctx, field) + case "mainExamer": + return ec.fieldContext_ExternalExam_mainExamer(ctx, field) + case "duration": + return ec.fieldContext_ExternalExam_duration(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ExternalExam", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Exam_primussExams(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Exam_primussExams(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PrimussExams, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.PrimussExam) + fc.Result = res + return ec.marshalNPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Exam_primussExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Exam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "ancode": + return ec.fieldContext_PrimussExam_ancode(ctx, field) + case "module": + return ec.fieldContext_PrimussExam_module(ctx, field) + case "mainExamer": + return ec.fieldContext_PrimussExam_mainExamer(ctx, field) + case "program": + return ec.fieldContext_PrimussExam_program(ctx, field) + case "examType": + return ec.fieldContext_PrimussExam_examType(ctx, field) + case "presence": + return ec.fieldContext_PrimussExam_presence(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type PrimussExam", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Exam_studentRegs(ctx context.Context, field graphql.CollectedField, obj *model.Exam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Exam_studentRegs(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.StudentRegs, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.StudentRegsPerAncodeAndProgram) fc.Result = res return ec.marshalNStudentRegsPerAncodeAndProgram2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentRegsPerAncodeAndProgramᚄ(ctx, field.Selections, res) } @@ -8483,10 +8831,6 @@ func (ec *executionContext) fieldContext_ExamWithRegs_primussExams(ctx context.C return ec.fieldContext_PrimussExam_examType(ctx, field) case "presence": return ec.fieldContext_PrimussExam_presence(ctx, field) - case "studentRegs": - return ec.fieldContext_PrimussExam_studentRegs(ctx, field) - case "conflicts": - return ec.fieldContext_PrimussExam_conflicts(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type PrimussExam", field.Name) }, @@ -9214,6 +9558,287 @@ func (ec *executionContext) fieldContext_FK07Program_name(ctx context.Context, f return fc, nil } +func (ec *executionContext) _GeneratedExam_ancode(ctx context.Context, field graphql.CollectedField, obj *model.GeneratedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_GeneratedExam_ancode(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Ancode, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_GeneratedExam_ancode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "GeneratedExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _GeneratedExam_zpaExam(ctx context.Context, field graphql.CollectedField, obj *model.GeneratedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_GeneratedExam_zpaExam(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ZpaExam, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.ZPAExam) + fc.Result = res + return ec.marshalNZPAExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExam(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_GeneratedExam_zpaExam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "GeneratedExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "zpaID": + return ec.fieldContext_ZPAExam_zpaID(ctx, field) + case "semester": + return ec.fieldContext_ZPAExam_semester(ctx, field) + case "ancode": + return ec.fieldContext_ZPAExam_ancode(ctx, field) + case "module": + return ec.fieldContext_ZPAExam_module(ctx, field) + case "mainExamer": + return ec.fieldContext_ZPAExam_mainExamer(ctx, field) + case "mainExamerID": + return ec.fieldContext_ZPAExam_mainExamerID(ctx, field) + case "examType": + return ec.fieldContext_ZPAExam_examType(ctx, field) + case "examTypeFull": + return ec.fieldContext_ZPAExam_examTypeFull(ctx, field) + case "duration": + return ec.fieldContext_ZPAExam_duration(ctx, field) + case "isRepeaterExam": + return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) + case "groups": + return ec.fieldContext_ZPAExam_groups(ctx, field) + case "primussAncodes": + return ec.fieldContext_ZPAExam_primussAncodes(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _GeneratedExam_primussExams(ctx context.Context, field graphql.CollectedField, obj *model.GeneratedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_GeneratedExam_primussExams(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PrimussExams, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.EnhancedPrimussExam) + fc.Result = res + return ec.marshalNEnhancedPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPrimussExamᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_GeneratedExam_primussExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "GeneratedExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "exam": + return ec.fieldContext_EnhancedPrimussExam_exam(ctx, field) + case "studentRegs": + return ec.fieldContext_EnhancedPrimussExam_studentRegs(ctx, field) + case "conflicts": + return ec.fieldContext_EnhancedPrimussExam_conflicts(ctx, field) + case "ntas": + return ec.fieldContext_EnhancedPrimussExam_ntas(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type EnhancedPrimussExam", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _GeneratedExam_constraints(ctx context.Context, field graphql.CollectedField, obj *model.GeneratedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_GeneratedExam_constraints(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Constraints, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.Constraints) + fc.Result = res + return ec.marshalOConstraints2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConstraints(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_GeneratedExam_constraints(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "GeneratedExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "ancode": + return ec.fieldContext_Constraints_ancode(ctx, field) + case "notPlannedByMe": + return ec.fieldContext_Constraints_notPlannedByMe(ctx, field) + case "excludeDays": + return ec.fieldContext_Constraints_excludeDays(ctx, field) + case "possibleDays": + return ec.fieldContext_Constraints_possibleDays(ctx, field) + case "fixedDay": + return ec.fieldContext_Constraints_fixedDay(ctx, field) + case "fixedTime": + return ec.fieldContext_Constraints_fixedTime(ctx, field) + case "sameSlot": + return ec.fieldContext_Constraints_sameSlot(ctx, field) + case "online": + return ec.fieldContext_Constraints_online(ctx, field) + case "roomConstraints": + return ec.fieldContext_Constraints_roomConstraints(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Constraints", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _GeneratedExam_conflicts(ctx context.Context, field graphql.CollectedField, obj *model.GeneratedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_GeneratedExam_conflicts(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Conflicts, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.ZPAConflict) + fc.Result = res + return ec.marshalNZPAConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAConflictᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_GeneratedExam_conflicts(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "GeneratedExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "ancode": + return ec.fieldContext_ZPAConflict_ancode(ctx, field) + case "numberOfStuds": + return ec.fieldContext_ZPAConflict_numberOfStuds(ctx, field) + case "primussAncodes": + return ec.fieldContext_ZPAConflict_primussAncodes(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ZPAConflict", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _Invigilation_roomName(ctx context.Context, field graphql.CollectedField, obj *model.Invigilation) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Invigilation_roomName(ctx, field) if err != nil { @@ -13701,8 +14326,8 @@ func (ec *executionContext) fieldContext_PrimussExam_presence(ctx context.Contex return fc, nil } -func (ec *executionContext) _PrimussExam_studentRegs(ctx context.Context, field graphql.CollectedField, obj *model.PrimussExam) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_PrimussExam_studentRegs(ctx, field) +func (ec *executionContext) _PrimussExamAncode_ancode(ctx context.Context, field graphql.CollectedField, obj *model.PrimussExamAncode) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PrimussExamAncode_ancode(ctx, field) if err != nil { return graphql.Null } @@ -13715,7 +14340,7 @@ func (ec *executionContext) _PrimussExam_studentRegs(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.PrimussExam().StudentRegs(rctx, obj) + return obj.Ancode, nil }) if err != nil { ec.Error(ctx, err) @@ -13725,42 +14350,28 @@ func (ec *executionContext) _PrimussExam_studentRegs(ctx context.Context, field if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } - return graphql.Null - } - res := resTmp.([]*model.StudentReg) - fc.Result = res - return ec.marshalNStudentReg2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentRegᚄ(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_PrimussExam_studentRegs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "PrimussExam", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "mtknr": - return ec.fieldContext_StudentReg_mtknr(ctx, field) - case "ancode": - return ec.fieldContext_StudentReg_ancode(ctx, field) - case "program": - return ec.fieldContext_StudentReg_program(ctx, field) - case "group": - return ec.fieldContext_StudentReg_group(ctx, field) - case "name": - return ec.fieldContext_StudentReg_name(ctx, field) - case "presence": - return ec.fieldContext_StudentReg_presence(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type StudentReg", field.Name) + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PrimussExamAncode_ancode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PrimussExamAncode", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") }, } return fc, nil } -func (ec *executionContext) _PrimussExam_conflicts(ctx context.Context, field graphql.CollectedField, obj *model.PrimussExam) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_PrimussExam_conflicts(ctx, field) +func (ec *executionContext) _PrimussExamAncode_program(ctx context.Context, field graphql.CollectedField, obj *model.PrimussExamAncode) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PrimussExamAncode_program(ctx, field) if err != nil { return graphql.Null } @@ -13773,7 +14384,7 @@ func (ec *executionContext) _PrimussExam_conflicts(ctx context.Context, field gr }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.PrimussExam().Conflicts(rctx, obj) + return obj.Program, nil }) if err != nil { ec.Error(ctx, err) @@ -13785,29 +14396,19 @@ func (ec *executionContext) _PrimussExam_conflicts(ctx context.Context, field gr } return graphql.Null } - res := resTmp.(*model.Conflicts) + res := resTmp.(string) fc.Result = res - return ec.marshalNConflicts2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflicts(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_PrimussExam_conflicts(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_PrimussExamAncode_program(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "PrimussExam", + Object: "PrimussExamAncode", Field: field, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "ancode": - return ec.fieldContext_Conflicts_ancode(ctx, field) - case "module": - return ec.fieldContext_Conflicts_module(ctx, field) - case "mainExamer": - return ec.fieldContext_Conflicts_mainExamer(ctx, field) - case "conflicts": - return ec.fieldContext_Conflicts_conflicts(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type Conflicts", field.Name) + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil @@ -13908,10 +14509,6 @@ func (ec *executionContext) fieldContext_PrimussExamByProgram_exams(ctx context. return ec.fieldContext_PrimussExam_examType(ctx, field) case "presence": return ec.fieldContext_PrimussExam_presence(ctx, field) - case "studentRegs": - return ec.fieldContext_PrimussExam_studentRegs(ctx, field) - case "conflicts": - return ec.fieldContext_PrimussExam_conflicts(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type PrimussExam", field.Name) }, @@ -14332,10 +14929,6 @@ func (ec *executionContext) fieldContext_Query_primussExam(ctx context.Context, return ec.fieldContext_PrimussExam_examType(ctx, field) case "presence": return ec.fieldContext_PrimussExam_presence(ctx, field) - case "studentRegs": - return ec.fieldContext_PrimussExam_studentRegs(ctx, field) - case "conflicts": - return ec.fieldContext_PrimussExam_conflicts(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type PrimussExam", field.Name) }, @@ -14402,10 +14995,6 @@ func (ec *executionContext) fieldContext_Query_primussExamsForAnCode(ctx context return ec.fieldContext_PrimussExam_examType(ctx, field) case "presence": return ec.fieldContext_PrimussExam_presence(ctx, field) - case "studentRegs": - return ec.fieldContext_PrimussExam_studentRegs(ctx, field) - case "conflicts": - return ec.fieldContext_PrimussExam_conflicts(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type PrimussExam", field.Name) }, @@ -16459,6 +17048,62 @@ func (ec *executionContext) fieldContext_Query_externalExams(ctx context.Context return fc, nil } +func (ec *executionContext) _Query_generatedExams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_generatedExams(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().GeneratedExams(rctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.GeneratedExam) + fc.Result = res + return ec.marshalNGeneratedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExamᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_generatedExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "ancode": + return ec.fieldContext_GeneratedExam_ancode(ctx, field) + case "zpaExam": + return ec.fieldContext_GeneratedExam_zpaExam(ctx, field) + case "primussExams": + return ec.fieldContext_GeneratedExam_primussExams(ctx, field) + case "constraints": + return ec.fieldContext_GeneratedExam_constraints(ctx, field) + case "conflicts": + return ec.fieldContext_GeneratedExam_conflicts(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type GeneratedExam", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _Query_exam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_exam(ctx, field) if err != nil { @@ -21413,6 +22058,144 @@ func (ec *executionContext) fieldContext_Teacher_email(ctx context.Context, fiel return fc, nil } +func (ec *executionContext) _ZPAConflict_ancode(ctx context.Context, field graphql.CollectedField, obj *model.ZPAConflict) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ZPAConflict_ancode(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Ancode, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ZPAConflict_ancode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ZPAConflict", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _ZPAConflict_numberOfStuds(ctx context.Context, field graphql.CollectedField, obj *model.ZPAConflict) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ZPAConflict_numberOfStuds(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.NumberOfStuds, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ZPAConflict_numberOfStuds(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ZPAConflict", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _ZPAConflict_primussAncodes(ctx context.Context, field graphql.CollectedField, obj *model.ZPAConflict) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ZPAConflict_primussAncodes(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PrimussAncodes, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.PrimussExamAncode) + fc.Result = res + return ec.marshalNPrimussExamAncode2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncodeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ZPAConflict_primussAncodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ZPAConflict", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "ancode": + return ec.fieldContext_PrimussExamAncode_ancode(ctx, field) + case "program": + return ec.fieldContext_PrimussExamAncode_program(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type PrimussExamAncode", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _ZPAExam_zpaID(ctx context.Context, field graphql.CollectedField, obj *model.ZPAExam) (ret graphql.Marshaler) { fc, err := ec.fieldContext_ZPAExam_zpaID(ctx, field) if err != nil { @@ -25169,44 +25952,98 @@ func (ec *executionContext) _ConnectedExam(ctx context.Context, sel ast.Selectio return out } -var constraintsImplementors = []string{"Constraints"} +var constraintsImplementors = []string{"Constraints"} + +func (ec *executionContext) _Constraints(ctx context.Context, sel ast.SelectionSet, obj *model.Constraints) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, constraintsImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Constraints") + case "ancode": + out.Values[i] = ec._Constraints_ancode(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "notPlannedByMe": + out.Values[i] = ec._Constraints_notPlannedByMe(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "excludeDays": + out.Values[i] = ec._Constraints_excludeDays(ctx, field, obj) + case "possibleDays": + out.Values[i] = ec._Constraints_possibleDays(ctx, field, obj) + case "fixedDay": + out.Values[i] = ec._Constraints_fixedDay(ctx, field, obj) + case "fixedTime": + out.Values[i] = ec._Constraints_fixedTime(ctx, field, obj) + case "sameSlot": + out.Values[i] = ec._Constraints_sameSlot(ctx, field, obj) + case "online": + out.Values[i] = ec._Constraints_online(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "roomConstraints": + out.Values[i] = ec._Constraints_roomConstraints(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var enhancedPrimussExamImplementors = []string{"EnhancedPrimussExam"} -func (ec *executionContext) _Constraints(ctx context.Context, sel ast.SelectionSet, obj *model.Constraints) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, constraintsImplementors) +func (ec *executionContext) _EnhancedPrimussExam(ctx context.Context, sel ast.SelectionSet, obj *model.EnhancedPrimussExam) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, enhancedPrimussExamImplementors) out := graphql.NewFieldSet(fields) deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("Constraints") - case "ancode": - out.Values[i] = ec._Constraints_ancode(ctx, field, obj) + out.Values[i] = graphql.MarshalString("EnhancedPrimussExam") + case "exam": + out.Values[i] = ec._EnhancedPrimussExam_exam(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "notPlannedByMe": - out.Values[i] = ec._Constraints_notPlannedByMe(ctx, field, obj) + case "studentRegs": + out.Values[i] = ec._EnhancedPrimussExam_studentRegs(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "excludeDays": - out.Values[i] = ec._Constraints_excludeDays(ctx, field, obj) - case "possibleDays": - out.Values[i] = ec._Constraints_possibleDays(ctx, field, obj) - case "fixedDay": - out.Values[i] = ec._Constraints_fixedDay(ctx, field, obj) - case "fixedTime": - out.Values[i] = ec._Constraints_fixedTime(ctx, field, obj) - case "sameSlot": - out.Values[i] = ec._Constraints_sameSlot(ctx, field, obj) - case "online": - out.Values[i] = ec._Constraints_online(ctx, field, obj) + case "conflicts": + out.Values[i] = ec._EnhancedPrimussExam_conflicts(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "ntas": + out.Values[i] = ec._EnhancedPrimussExam_ntas(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "roomConstraints": - out.Values[i] = ec._Constraints_roomConstraints(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -25851,6 +26688,62 @@ func (ec *executionContext) _FK07Program(ctx context.Context, sel ast.SelectionS return out } +var generatedExamImplementors = []string{"GeneratedExam"} + +func (ec *executionContext) _GeneratedExam(ctx context.Context, sel ast.SelectionSet, obj *model.GeneratedExam) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, generatedExamImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("GeneratedExam") + case "ancode": + out.Values[i] = ec._GeneratedExam_ancode(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "zpaExam": + out.Values[i] = ec._GeneratedExam_zpaExam(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "primussExams": + out.Values[i] = ec._GeneratedExam_primussExams(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "constraints": + out.Values[i] = ec._GeneratedExam_constraints(ctx, field, obj) + case "conflicts": + out.Values[i] = ec._GeneratedExam_conflicts(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var invigilationImplementors = []string{"Invigilation"} func (ec *executionContext) _Invigilation(ctx context.Context, sel ast.SelectionSet, obj *model.Invigilation) graphql.Marshaler { @@ -26799,105 +27692,77 @@ func (ec *executionContext) _PrimussExam(ctx context.Context, sel ast.SelectionS case "ancode": out.Values[i] = ec._PrimussExam_ancode(ctx, field, obj) if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) + out.Invalids++ } case "module": out.Values[i] = ec._PrimussExam_module(ctx, field, obj) if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) + out.Invalids++ } case "mainExamer": out.Values[i] = ec._PrimussExam_mainExamer(ctx, field, obj) if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) + out.Invalids++ } case "program": out.Values[i] = ec._PrimussExam_program(ctx, field, obj) if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) + out.Invalids++ } case "examType": out.Values[i] = ec._PrimussExam_examType(ctx, field, obj) if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) + out.Invalids++ } case "presence": out.Values[i] = ec._PrimussExam_presence(ctx, field, obj) if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) - } - case "studentRegs": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._PrimussExam_studentRegs(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } - return res + out.Invalids++ } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } - if field.Deferrable != nil { - dfs, ok := deferred[field.Deferrable.Label] - di := 0 - if ok { - dfs.AddField(field) - di = len(dfs.Values) - 1 - } else { - dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) - deferred[field.Deferrable.Label] = dfs - } - dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { - return innerFunc(ctx, dfs) - }) + atomic.AddInt32(&ec.deferred, int32(len(deferred))) - // don't run the out.Concurrently() call below - out.Values[i] = graphql.Null - continue - } + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - case "conflicts": - field := field + return out +} - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._PrimussExam_conflicts(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } - return res - } +var primussExamAncodeImplementors = []string{"PrimussExamAncode"} - if field.Deferrable != nil { - dfs, ok := deferred[field.Deferrable.Label] - di := 0 - if ok { - dfs.AddField(field) - di = len(dfs.Values) - 1 - } else { - dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) - deferred[field.Deferrable.Label] = dfs - } - dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { - return innerFunc(ctx, dfs) - }) +func (ec *executionContext) _PrimussExamAncode(ctx context.Context, sel ast.SelectionSet, obj *model.PrimussExamAncode) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, primussExamAncodeImplementors) - // don't run the out.Concurrently() call below - out.Values[i] = graphql.Null - continue + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("PrimussExamAncode") + case "ancode": + out.Values[i] = ec._PrimussExamAncode_ancode(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "program": + out.Values[i] = ec._PrimussExamAncode_program(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ } - - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -27880,6 +28745,28 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "generatedExams": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_generatedExams(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "exam": field := field @@ -29272,13 +30159,62 @@ func (ec *executionContext) _Teacher(ctx context.Context, sel ast.SelectionSet, if out.Values[i] == graphql.Null { out.Invalids++ } - case "id": - out.Values[i] = ec._Teacher_id(ctx, field, obj) + case "id": + out.Values[i] = ec._Teacher_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "email": + out.Values[i] = ec._Teacher_email(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var zPAConflictImplementors = []string{"ZPAConflict"} + +func (ec *executionContext) _ZPAConflict(ctx context.Context, sel ast.SelectionSet, obj *model.ZPAConflict) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, zPAConflictImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("ZPAConflict") + case "ancode": + out.Values[i] = ec._ZPAConflict_ancode(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "numberOfStuds": + out.Values[i] = ec._ZPAConflict_numberOfStuds(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "email": - out.Values[i] = ec._Teacher_email(ctx, field, obj) + case "primussAncodes": + out.Values[i] = ec._ZPAConflict_primussAncodes(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } @@ -30188,21 +31124,61 @@ func (ec *executionContext) marshalNConflictPerProgram2ᚖgithubᚗcomᚋobcode return ec._ConflictPerProgram(ctx, sel, v) } -func (ec *executionContext) marshalNConflicts2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflicts(ctx context.Context, sel ast.SelectionSet, v model.Conflicts) graphql.Marshaler { - return ec._Conflicts(ctx, sel, &v) +func (ec *executionContext) marshalNConflictsPerProgramAncode2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictsPerProgramAncodeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ConflictsPerProgramAncode) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNConflictsPerProgramAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictsPerProgramAncode(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret } -func (ec *executionContext) marshalNConflicts2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflicts(ctx context.Context, sel ast.SelectionSet, v *model.Conflicts) graphql.Marshaler { +func (ec *executionContext) marshalNConflictsPerProgramAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictsPerProgramAncode(ctx context.Context, sel ast.SelectionSet, v *model.ConflictsPerProgramAncode) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._Conflicts(ctx, sel, v) + return ec._ConflictsPerProgramAncode(ctx, sel, v) } -func (ec *executionContext) marshalNConflictsPerProgramAncode2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictsPerProgramAncodeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ConflictsPerProgramAncode) graphql.Marshaler { +func (ec *executionContext) marshalNConnectedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ConnectedExam) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -30226,7 +31202,7 @@ func (ec *executionContext) marshalNConflictsPerProgramAncode2ᚕᚖgithubᚗcom if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNConflictsPerProgramAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictsPerProgramAncode(ctx, sel, v[i]) + ret[i] = ec.marshalNConnectedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExam(ctx, sel, v[i]) } if isLen1 { f(i) @@ -30246,17 +31222,17 @@ func (ec *executionContext) marshalNConflictsPerProgramAncode2ᚕᚖgithubᚗcom return ret } -func (ec *executionContext) marshalNConflictsPerProgramAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictsPerProgramAncode(ctx context.Context, sel ast.SelectionSet, v *model.ConflictsPerProgramAncode) graphql.Marshaler { +func (ec *executionContext) marshalNConnectedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExam(ctx context.Context, sel ast.SelectionSet, v *model.ConnectedExam) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._ConflictsPerProgramAncode(ctx, sel, v) + return ec._ConnectedExam(ctx, sel, v) } -func (ec *executionContext) marshalNConnectedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ConnectedExam) graphql.Marshaler { +func (ec *executionContext) marshalNEnhancedPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPrimussExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.EnhancedPrimussExam) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -30280,7 +31256,7 @@ func (ec *executionContext) marshalNConnectedExam2ᚕᚖgithubᚗcomᚋobcodeᚋ if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNConnectedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExam(ctx, sel, v[i]) + ret[i] = ec.marshalNEnhancedPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPrimussExam(ctx, sel, v[i]) } if isLen1 { f(i) @@ -30300,14 +31276,14 @@ func (ec *executionContext) marshalNConnectedExam2ᚕᚖgithubᚗcomᚋobcodeᚋ return ret } -func (ec *executionContext) marshalNConnectedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExam(ctx context.Context, sel ast.SelectionSet, v *model.ConnectedExam) graphql.Marshaler { +func (ec *executionContext) marshalNEnhancedPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPrimussExam(ctx context.Context, sel ast.SelectionSet, v *model.EnhancedPrimussExam) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._ConnectedExam(ctx, sel, v) + return ec._EnhancedPrimussExam(ctx, sel, v) } func (ec *executionContext) marshalNExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Exam) graphql.Marshaler { @@ -30699,6 +31675,60 @@ func (ec *executionContext) marshalNFloat2float64(ctx context.Context, sel ast.S return graphql.WrapContextMarshaler(ctx, res) } +func (ec *executionContext) marshalNGeneratedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.GeneratedExam) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNGeneratedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExam(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNGeneratedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExam(ctx context.Context, sel ast.SelectionSet, v *model.GeneratedExam) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._GeneratedExam(ctx, sel, v) +} + func (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) { res, err := graphql.UnmarshalInt(v) return res, graphql.ErrorOnPath(ctx, err) @@ -30814,6 +31844,50 @@ func (ec *executionContext) marshalNNTA2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋg return ec._NTA(ctx, sel, &v) } +func (ec *executionContext) marshalNNTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.NTA) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNNTA2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTA(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + func (ec *executionContext) marshalNNTA2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTA(ctx context.Context, sel ast.SelectionSet, v *model.NTA) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -31025,6 +32099,60 @@ func (ec *executionContext) marshalNPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexa return ec._PrimussExam(ctx, sel, v) } +func (ec *executionContext) marshalNPrimussExamAncode2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncodeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PrimussExamAncode) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNPrimussExamAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncode(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNPrimussExamAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncode(ctx context.Context, sel ast.SelectionSet, v *model.PrimussExamAncode) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._PrimussExamAncode(ctx, sel, v) +} + func (ec *executionContext) marshalNRegWithError2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRegWithErrorᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.RegWithError) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup @@ -31821,6 +32949,60 @@ func (ec *executionContext) marshalNTime2ᚖtimeᚐTime(ctx context.Context, sel return res } +func (ec *executionContext) marshalNZPAConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAConflictᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ZPAConflict) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNZPAConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAConflict(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNZPAConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAConflict(ctx context.Context, sel ast.SelectionSet, v *model.ZPAConflict) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._ZPAConflict(ctx, sel, v) +} + func (ec *executionContext) marshalNZPAExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ZPAExam) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index 5f6e170..f688e5e 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -59,6 +59,13 @@ type Constraints struct { RoomConstraints *RoomConstraints `json:"roomConstraints,omitempty"` } +type EnhancedPrimussExam struct { + Exam *PrimussExam `json:"exam"` + StudentRegs []*StudentReg `json:"studentRegs"` + Conflicts []*Conflict `json:"conflicts"` + Ntas []*NTA `json:"ntas"` +} + type Exam struct { Ancode int `json:"ancode"` ZpaExam *ZPAExam `json:"zpaExam,omitempty"` @@ -149,6 +156,14 @@ type FK07Program struct { Name string `json:"name"` } +type GeneratedExam struct { + Ancode int `json:"ancode"` + ZpaExam *ZPAExam `json:"zpaExam"` + PrimussExams []*EnhancedPrimussExam `json:"primussExams"` + Constraints *Constraints `json:"constraints,omitempty"` + Conflicts []*ZPAConflict `json:"conflicts"` +} + type Invigilation struct { RoomName *string `json:"roomName,omitempty"` Duration int `json:"duration"` @@ -247,6 +262,11 @@ type PlannedExamWithNta struct { Nta []*NTAWithRegs `json:"nta,omitempty"` } +type PrimussExamAncode struct { + Ancode int `json:"ancode"` + Program string `json:"program"` +} + type PrimussExamByProgram struct { Program string `json:"program"` Exams []*PrimussExam `json:"exams"` @@ -361,6 +381,12 @@ type StudentRegsPerStudent struct { Ancodes []int `json:"ancodes"` } +type ZPAConflict struct { + Ancode int `json:"ancode"` + NumberOfStuds int `json:"numberOfStuds"` + PrimussAncodes []*PrimussExamAncode `json:"primussAncodes"` +} + type ZPAExamWithConstraints struct { ZpaExam *ZPAExam `json:"zpaExam"` Constraints *Constraints `json:"constraints,omitempty"` diff --git a/graph/primuss.graphqls b/graph/primuss.graphqls index fe33885..c0c5011 100644 --- a/graph/primuss.graphqls +++ b/graph/primuss.graphqls @@ -5,8 +5,18 @@ type PrimussExam { program: String! examType: String! presence: String! +} + +type EnhancedPrimussExam { + exam: PrimussExam! studentRegs: [StudentReg!]! - conflicts: Conflicts! + conflicts: [Conflict!]! + ntas: [NTA!]! +} + +type PrimussExamAncode { + ancode: Int! + program: String! } input PrimussExamInput { diff --git a/graph/primuss.resolvers.go b/graph/primuss.resolvers.go deleted file mode 100644 index c80de9f..0000000 --- a/graph/primuss.resolvers.go +++ /dev/null @@ -1,27 +0,0 @@ -package graph - -// This file will be automatically regenerated based on the schema, any resolver implementations -// will be copied through when generating and any unknown code will be moved to the end. -// Code generated by github.com/99designs/gqlgen version v0.17.34 - -import ( - "context" - - "github.com/obcode/plexams.go/graph/generated" - "github.com/obcode/plexams.go/graph/model" -) - -// StudentRegs is the resolver for the studentRegs field. -func (r *primussExamResolver) StudentRegs(ctx context.Context, obj *model.PrimussExam) ([]*model.StudentReg, error) { - return r.plexams.GetStudentRegs(ctx, obj) -} - -// Conflicts is the resolver for the conflicts field. -func (r *primussExamResolver) Conflicts(ctx context.Context, obj *model.PrimussExam) (*model.Conflicts, error) { - return r.plexams.GetConflicts(ctx, obj) -} - -// PrimussExam returns generated.PrimussExamResolver implementation. -func (r *Resolver) PrimussExam() generated.PrimussExamResolver { return &primussExamResolver{r} } - -type primussExamResolver struct{ *Resolver } diff --git a/plexams/constraints.go b/plexams/constraints.go index 959da78..19c87ca 100644 --- a/plexams/constraints.go +++ b/plexams/constraints.go @@ -94,6 +94,21 @@ func (p *Plexams) Constraints(ctx context.Context) ([]*model.Constraints, error) return p.dbClient.GetConstraints(ctx) } +func (p *Plexams) ConstraintsMap(ctx context.Context) (map[int]*model.Constraints, error) { + constraints, err := p.dbClient.GetConstraints(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get constraints") + return nil, err + } + + constraintsMap := make(map[int]*model.Constraints) + for _, constraintsForAncode := range constraints { + constraintsMap[constraintsForAncode.Ancode] = constraintsForAncode + } + + return constraintsMap, nil +} + func (p *Plexams) ZpaExamsToPlanWithConstraints(ctx context.Context) ([]*model.ZPAExamWithConstraints, error) { exams, err := p.GetZpaExamsToPlan(ctx) if err != nil { diff --git a/plexams/generatedExams.go b/plexams/generatedExams.go new file mode 100644 index 0000000..b0cac83 --- /dev/null +++ b/plexams/generatedExams.go @@ -0,0 +1,217 @@ +package plexams + +import ( + "context" + "fmt" + "sort" + + "github.com/obcode/plexams.go/graph/model" + "github.com/rs/zerolog/log" +) + +func (p *Plexams) PrepareGeneratedExams() error { + ctx := context.Background() + // from connected exams to exam generated + connectedExams, err := p.GetConnectedExams(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get connected exams") + return err + } + + constraints, err := p.ConstraintsMap(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get connected exams") + return err + } + + ntas, err := p.Ntas(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get ntas") + return err + } + + fmt.Printf("%d NTAs = %v\n", len(ntas), ntas) + + ntaMap := make(map[string]*model.NTA) + for _, nta := range ntas { + ntaMap[nta.Mtknr] = nta + } + + externalExams, err := p.ExternalExams(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get external exams") + return err + } + + ancodesMap := primussAncodesToZpaAncodes(connectedExams, externalExams) + + exams := make([]*model.GeneratedExam, 0, len(connectedExams)) + + for _, connectedExam := range connectedExams { + // TODO: remove me + if connectedExam.ZpaExam.AnCode != 390 { + continue + } + + // cfg := yacspin.Config{ + // Frequency: 100 * time.Millisecond, + // CharSet: yacspin.CharSets[69], + // Suffix: aurora.Sprintf(aurora.Cyan(" generating exam %d. %s (%s)"), + // aurora.Yellow(connectedExam.ZpaExam.AnCode), + // aurora.Magenta(connectedExam.ZpaExam.Module), + // aurora.Magenta(connectedExam.ZpaExam.MainExamer), + // ), + // SuffixAutoColon: true, + // StopCharacter: "✓", + // StopColors: []string{"fgGreen"}, + // StopFailMessage: "error", + // StopFailCharacter: "✗", + // StopFailColors: []string{"fgRed"}, + // } + + // spinner, err := yacspin.New(cfg) + // if err != nil { + // log.Debug().Err(err).Msg("cannot create spinner") + // } + // err = spinner.Start() + // if err != nil { + // log.Debug().Err(err).Msg("cannot start spinner") + // } + + // spinner.Message("getting primuss exams") + + enhancedPrimussExams := make([]*model.EnhancedPrimussExam, 0, len(connectedExam.PrimussExams)) + for _, primussExam := range connectedExam.PrimussExams { + enhanced, err := p.primussToEnhanced(ctx, primussExam, ntaMap) + if err != nil { + log.Error().Err(err).Str("program", primussExam.Program).Int("ancode", primussExam.AnCode). + Msg("cannot enhance primuss exam") + return err + } + + enhancedPrimussExams = append(enhancedPrimussExams, enhanced) + } + + // spinner.Message("recalculating conflicts") + + conflictsMap := make(map[int]*model.ZPAConflict) + for _, enhanced := range enhancedPrimussExams { + for _, primussConflict := range enhanced.Conflicts { + zpaAncode, ok := ancodesMap[PrimussAncode{ + Program: enhanced.Exam.Program, + Ancode: primussConflict.AnCode, + }] + if ok { + zpaConflict, ok := conflictsMap[zpaAncode] + if ok { + conflictsMap[zpaAncode] = &model.ZPAConflict{ + Ancode: zpaAncode, + NumberOfStuds: zpaConflict.NumberOfStuds + primussConflict.NumberOfStuds, + PrimussAncodes: append(zpaConflict.PrimussAncodes, &model.PrimussExamAncode{ + Ancode: primussConflict.AnCode, + Program: enhanced.Exam.Program, + }), + } + } else { + conflictsMap[zpaAncode] = &model.ZPAConflict{ + Ancode: zpaAncode, + NumberOfStuds: primussConflict.NumberOfStuds, + PrimussAncodes: []*model.PrimussExamAncode{{ + Ancode: primussConflict.AnCode, + Program: enhanced.Exam.Program, + }}, + } + } + } + } + } + + keys := make([]int, 0, len(conflictsMap)) + for key := range conflictsMap { + keys = append(keys, key) + } + sort.Ints(keys) + + conflicts := make([]*model.ZPAConflict, 0, len(conflictsMap)) + for _, key := range keys { + conflicts = append(conflicts, conflictsMap[key]) + } + + exams = append(exams, &model.GeneratedExam{ + Ancode: connectedExam.ZpaExam.AnCode, + ZpaExam: connectedExam.ZpaExam, + PrimussExams: enhancedPrimussExams, + Constraints: constraints[connectedExam.ZpaExam.AnCode], + Conflicts: conflicts, + }) + + // err = spinner.Stop() + // if err != nil { + // log.Debug().Err(err).Msg("cannot stop spinner") + // } + } + + // TODO: External Exams with student regs, ... + // automatically set notPlannedByMe constraint + + return p.dbClient.CacheGeneratedExams(ctx, exams) +} + +// func (p *Plexams) generateFromConnectedExam(ctx context.Context, connectedExam *model.ConnectedExam) (*model.GeneratedExam, error) { + +// return generatedExam, nil +// } + +func (p *Plexams) primussToEnhanced(ctx context.Context, exam *model.PrimussExam, ntaMap map[string]*model.NTA) (*model.EnhancedPrimussExam, error) { + studentRegs, err := p.GetStudentRegs(ctx, exam) + if err != nil { + log.Error().Err(err).Str("program", exam.Program).Int("ancode", exam.AnCode). + Msg("cannot get student regs for primuss exam") + return nil, err + } + + conflicts, err := p.GetConflicts(ctx, exam) + if err != nil { + log.Error().Err(err).Str("program", exam.Program).Int("ancode", exam.AnCode). + Msg("cannot get student regs for primuss exam") + return nil, err + } + + ntas := make([]*model.NTA, 0) + + for _, studentReg := range studentRegs { + nta, ok := ntaMap[studentReg.Mtknr] + if ok { + ntas = append(ntas, nta) + } + } + + return &model.EnhancedPrimussExam{ + Exam: exam, + StudentRegs: studentRegs, + Conflicts: conflicts.Conflicts, + Ntas: ntas, + }, nil +} + +type PrimussAncode struct { + Program string + Ancode int +} + +func primussAncodesToZpaAncodes(exams []*model.ConnectedExam, externalExams []*model.ExternalExam) map[PrimussAncode]int { + ancodesMap := make(map[PrimussAncode]int) + for _, exam := range exams { + zpaAncode := exam.ZpaExam.AnCode + for _, primussExam := range exam.PrimussExams { + ancodesMap[PrimussAncode{ + Program: primussExam.Program, + Ancode: primussExam.AnCode, + }] = zpaAncode + } + } + + // TODO: add external exams + + return ancodesMap +} From 152028c8f4a84ad3d1413f9204e75d5cfa6a1842 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Sat, 18 Nov 2023 21:59:36 +0100 Subject: [PATCH 30/78] send emails to all... --- cmd/email.go | 8 +- db/generatedExams.go | 22 +++++ db/primuss_studentregs.go | 4 +- plexams/email.go | 139 +++++++++++++++++++++++++++++++ plexams/generatedExams.go | 81 ++++++++++-------- tmpl/generatedExamEmail.tmpl | 48 +++++++++++ tmpl/generatedExamEmailHTML.tmpl | 75 +++++++++++++++++ 7 files changed, 338 insertions(+), 39 deletions(-) create mode 100644 tmpl/generatedExamEmail.tmpl create mode 100644 tmpl/generatedExamEmailHTML.tmpl diff --git a/cmd/email.go b/cmd/email.go index 4ae6ab1..e92e455 100644 --- a/cmd/email.go +++ b/cmd/email.go @@ -13,7 +13,8 @@ var ( Use: "email [subcommand]", Short: "send email", Long: `Send emails. -nta --- send emails to teachers about nta.`, +nta --- send emails to teachers about nta, +primuss-data --- send emails to teachers about primuss data and nta.`, Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { plexams := initPlexamsConfig() @@ -23,6 +24,11 @@ nta --- send emails to teachers about nta.`, if err != nil { log.Fatalf("got error: %v\n", err) } + case "primuss-data": + err := plexams.SendGeneratedExamMails(context.Background(), run) + if err != nil { + log.Fatalf("got error: %v\n", err) + } default: fmt.Println("email called with unknown sub command") } diff --git a/db/generatedExams.go b/db/generatedExams.go index 53e95db..9fe88d6 100644 --- a/db/generatedExams.go +++ b/db/generatedExams.go @@ -5,6 +5,7 @@ import ( "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" + "go.mongodb.org/mongo-driver/bson" ) func (db *DB) CacheGeneratedExams(ctx context.Context, exams []*model.GeneratedExam) error { @@ -30,3 +31,24 @@ func (db *DB) CacheGeneratedExams(ctx context.Context, exams []*model.GeneratedE log.Debug().Int("count", len(res.InsertedIDs)).Msg("successfully inserted generated exams") return nil } + +func (db *DB) GetGeneratedExams(ctx context.Context) ([]*model.GeneratedExam, error) { + collection := db.Client.Database(db.databaseName).Collection(collectionGeneratedExams) + + cur, err := collection.Find(ctx, bson.M{}) + if err != nil { + log.Error().Err(err).Msg("cannot get generated exams") + return nil, err + } + defer cur.Close(ctx) + + exams := make([]*model.GeneratedExam, 0) + + err = cur.All(ctx, &exams) + if err != nil { + log.Error().Err(err).Msg("cannot decode generated exams") + return nil, err + } + + return exams, nil +} diff --git a/db/primuss_studentregs.go b/db/primuss_studentregs.go index b58f256..ef62d9a 100644 --- a/db/primuss_studentregs.go +++ b/db/primuss_studentregs.go @@ -66,7 +66,7 @@ func (db *DB) GetPrimussStudentRegsPerAncode(ctx context.Context, program string } for k, v := range studentRegs { - if !db.checkStudentRegsCount(ctx, program, k, len(v)) { + if !db.CheckStudentRegsCount(ctx, program, k, len(v)) { return nil, fmt.Errorf("problem with studentregs, ancode = %d, #studentregs = %d", k, len(v)) } } @@ -183,7 +183,7 @@ type Count struct { Sum int `bson:"Sum"` } -func (db *DB) checkStudentRegsCount(ctx context.Context, program string, ancode, studentRegsCount int) bool { +func (db *DB) CheckStudentRegsCount(ctx context.Context, program string, ancode, studentRegsCount int) bool { // log.Debug().Str("collectionName", collectionName).Int("ancode", ancode).Int("studentRegsCount", studentRegsCount). // Msg("checking count") collection := db.getCollection(program, Counts) diff --git a/plexams/email.go b/plexams/email.go index fe79bbb..8211d89 100644 --- a/plexams/email.go +++ b/plexams/email.go @@ -8,10 +8,14 @@ import ( "html/template" "net/smtp" "net/textproto" + "time" // TODO: Ersetzen durch github.com/wneessen/go-mail "github.com/jordan-wright/email" + "github.com/logrusorgru/aurora" + "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" + "github.com/theckman/yacspin" ) type HandicapsEmail struct { @@ -50,6 +54,141 @@ func (p *Plexams) SendTestMail() error { }) } +func (p *Plexams) SendGeneratedExamMails(ctx context.Context, run bool) error { + generatedExams, err := p.GetGeneratedExams(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get generated exams") + return err + } + + notFromZPA := false + teachers, err := p.GetTeachers(ctx, ¬FromZPA) + if err != nil { + log.Error().Err(err).Msg("cannot get generated exams") + return err + } + + teachersMap := make(map[int]*model.Teacher) + for _, teacher := range teachers { + teachersMap[teacher.ID] = teacher + } + + for _, exam := range generatedExams { + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Cyan(" sending email about exam %d. %s (%s)"), + aurora.Yellow(exam.ZpaExam.AnCode), + aurora.Magenta(exam.ZpaExam.Module), + aurora.Magenta(exam.ZpaExam.MainExamer), + ), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "not planned by me", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + if exam.Constraints != nil && exam.Constraints.NotPlannedByMe { + err = spinner.StopFail() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + continue + } + teacher, ok := teachersMap[exam.ZpaExam.MainExamerID] + if !ok { + log.Debug().Int("ancode", exam.Ancode).Str("module", exam.ZpaExam.Module).Str("teacher", exam.ZpaExam.MainExamer). + Msg("no info about teacher in zpa") + continue + } + + var to string + if run { + to = teacher.Email + } else { + to = "galority@gmail.com" + } + + hasStudentRegs := false + + for _, primussExam := range exam.PrimussExams { + hasStudentRegs = hasStudentRegs || len(primussExam.StudentRegs) > 0 + } + + err = p.SendGeneratedExamMailToTeacher(ctx, to, &GeneratedExamMailData{ + Exam: exam, + Teacher: teacher, + PlanerName: p.planer.Name, + HasStudentRegs: hasStudentRegs, + }) + if err != nil { + log.Error().Err(err).Msg("cannot send email") + return err + } + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + } + + return nil +} + +type GeneratedExamMailData struct { + Exam *model.GeneratedExam + Teacher *model.Teacher + PlanerName string + HasStudentRegs bool +} + +func (p *Plexams) SendGeneratedExamMailToTeacher(ctx context.Context, to string, generatedExamMailData *GeneratedExamMailData) error { + log.Debug().Interface("to", to).Msg("sending email") + + tmpl, err := template.ParseFiles("tmpl/generatedExamEmail.tmpl") + if err != nil { + return err + } + bufText := new(bytes.Buffer) + err = tmpl.Execute(bufText, generatedExamMailData) + if err != nil { + return err + } + + tmpl, err = template.ParseFiles("tmpl/generatedExamEmailHTML.tmpl") + if err != nil { + return err + } + bufHTML := new(bytes.Buffer) + err = tmpl.Execute(bufHTML, generatedExamMailData) + if err != nil { + return err + } + + subject := fmt.Sprintf("[Prüfungsplanung %s] Vorliegende Planungsdaten für Ihre Prüfung %s", + p.semester, generatedExamMailData.Exam.ZpaExam.Module) + if !generatedExamMailData.HasStudentRegs { + subject = fmt.Sprintf("[Prüfungsplanung %s] Keine Anmeldungen für Ihre Prüfung %s", + p.semester, generatedExamMailData.Exam.ZpaExam.Module) + } + + return p.sendMail([]string{to}, + subject, + bufText.Bytes(), + bufHTML.Bytes(), + ) +} + func (p *Plexams) SendHandicapsMails(ctx context.Context, run bool) error { ntasByTeacher, err := p.NtasWithRegsByTeacher(ctx) if err != nil { diff --git a/plexams/generatedExams.go b/plexams/generatedExams.go index b0cac83..81c40b3 100644 --- a/plexams/generatedExams.go +++ b/plexams/generatedExams.go @@ -2,11 +2,13 @@ package plexams import ( "context" - "fmt" "sort" + "time" + "github.com/logrusorgru/aurora" "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" + "github.com/theckman/yacspin" ) func (p *Plexams) PrepareGeneratedExams() error { @@ -30,8 +32,6 @@ func (p *Plexams) PrepareGeneratedExams() error { return err } - fmt.Printf("%d NTAs = %v\n", len(ntas), ntas) - ntaMap := make(map[string]*model.NTA) for _, nta := range ntas { ntaMap[nta.Mtknr] = nta @@ -48,37 +48,37 @@ func (p *Plexams) PrepareGeneratedExams() error { exams := make([]*model.GeneratedExam, 0, len(connectedExams)) for _, connectedExam := range connectedExams { - // TODO: remove me - if connectedExam.ZpaExam.AnCode != 390 { - continue - } - - // cfg := yacspin.Config{ - // Frequency: 100 * time.Millisecond, - // CharSet: yacspin.CharSets[69], - // Suffix: aurora.Sprintf(aurora.Cyan(" generating exam %d. %s (%s)"), - // aurora.Yellow(connectedExam.ZpaExam.AnCode), - // aurora.Magenta(connectedExam.ZpaExam.Module), - // aurora.Magenta(connectedExam.ZpaExam.MainExamer), - // ), - // SuffixAutoColon: true, - // StopCharacter: "✓", - // StopColors: []string{"fgGreen"}, - // StopFailMessage: "error", - // StopFailCharacter: "✗", - // StopFailColors: []string{"fgRed"}, + // // TODO: remove me + // if connectedExam.ZpaExam.AnCode != 390 && connectedExam.ZpaExam.AnCode != 393 && connectedExam.ZpaExam.AnCode != 440 { + // continue // } - // spinner, err := yacspin.New(cfg) - // if err != nil { - // log.Debug().Err(err).Msg("cannot create spinner") - // } - // err = spinner.Start() - // if err != nil { - // log.Debug().Err(err).Msg("cannot start spinner") - // } + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Cyan(" generating exam %d. %s (%s)"), + aurora.Yellow(connectedExam.ZpaExam.AnCode), + aurora.Magenta(connectedExam.ZpaExam.Module), + aurora.Magenta(connectedExam.ZpaExam.MainExamer), + ), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } - // spinner.Message("getting primuss exams") + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + spinner.Message("getting primuss exams") enhancedPrimussExams := make([]*model.EnhancedPrimussExam, 0, len(connectedExam.PrimussExams)) for _, primussExam := range connectedExam.PrimussExams { @@ -92,7 +92,7 @@ func (p *Plexams) PrepareGeneratedExams() error { enhancedPrimussExams = append(enhancedPrimussExams, enhanced) } - // spinner.Message("recalculating conflicts") + spinner.Message("recalculating conflicts") conflictsMap := make(map[int]*model.ZPAConflict) for _, enhanced := range enhancedPrimussExams { @@ -145,10 +145,10 @@ func (p *Plexams) PrepareGeneratedExams() error { Conflicts: conflicts, }) - // err = spinner.Stop() - // if err != nil { - // log.Debug().Err(err).Msg("cannot stop spinner") - // } + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } } // TODO: External Exams with student regs, ... @@ -186,6 +186,11 @@ func (p *Plexams) primussToEnhanced(ctx context.Context, exam *model.PrimussExam } } + if len(studentRegs) > 0 && !p.dbClient.CheckStudentRegsCount(ctx, exam.Program, exam.AnCode, len(studentRegs)) { + log.Error().Err(err).Str("program", exam.Program).Int("ancode", exam.AnCode).Int("count", len(studentRegs)). + Msg("student reg count does not match") + } + return &model.EnhancedPrimussExam{ Exam: exam, StudentRegs: studentRegs, @@ -215,3 +220,7 @@ func primussAncodesToZpaAncodes(exams []*model.ConnectedExam, externalExams []*m return ancodesMap } + +func (p *Plexams) GetGeneratedExams(ctx context.Context) ([]*model.GeneratedExam, error) { + return p.dbClient.GetGeneratedExams(ctx) +} diff --git a/tmpl/generatedExamEmail.tmpl b/tmpl/generatedExamEmail.tmpl new file mode 100644 index 0000000..5fd93c1 --- /dev/null +++ b/tmpl/generatedExamEmail.tmpl @@ -0,0 +1,48 @@ +Sehr geehrte:r {{ .Teacher.Fullname }}, + +{{ if not .HasStudentRegs }} +Für Ihre Prüfung "{{ .Exam.ZpaExam.AnCode }}. {{ .Exam.ZpaExam.Module }}" liegen überhaupt keine Anmeldungen vor, daher werde ich sie nicht +planen. + +Falls die Prüfung dennoch eingeplant werden soll, teilen Sie mir das bitte unmittelbar mit. +{{ else }} +Ihre Prüfung "{{ .Exam.ZpaExam.AnCode }}. {{ .Exam.ZpaExam.Module }}" plane ich auf Grund folgender Daten. + +Sollten die Daten aus Ihrer Sicht fehlerhaft sein, nehmen Sie bitte umgehend mit +mir Kontakt auf; insbesondere dann, wenn die Anzahl der Anmeldungen stark von der +tatsächlichen Anzahl zu Prüfenden abweicht (z.B. auf Grund des Nichtbestehens einer +Zulassungsvoraussetzung). + +Sofern mir bekannt, sind Studierende mit Nachteilsausgleich unten angegeben. +Sollten Ihnen weitere Studierende mit Nachteilsausgleich bekannt sein oder bekannt werden, +geben Sie mir bitte sofort Bescheid, damit ich sie in der Planung berücksichtigen kann. + +{{ range .Exam.PrimussExams }} + {{ if ne (len .StudentRegs) 0 }} + - Studiengang {{ .Exam.Program }} + + Anmeldungen: + {{- range .StudentRegs }} + - {{ .Name }} + {{- end}} + + {{if ne (len .Ntas) 0 -}} + Studierende mit Nachteilsausgleich im Studiengang {{ .Exam.Program }} (auch in der Liste aller Anmeldungen enthalten) + {{ range .Ntas -}} + - {{.Name}}: {{.Compensation}} + {{- end -}} + {{- else -}} + Im Studiengang {{ .Exam.Program }} sind mir keine Nachteilsausgleiche für diese Prüfung bekannt. + {{- end -}} + {{- else -}} + - Studiengang {{ .Exam.Program }}: Keine Anmeldungen + {{ end -}} +{{ end }} +{{ end }} + +Mit freundlichen Grüßen +{{ .PlanerName }} + +-- +Diese E-Mail wurde generiert und gesendet von https://github.com/obcode/plexams.go + diff --git a/tmpl/generatedExamEmailHTML.tmpl b/tmpl/generatedExamEmailHTML.tmpl new file mode 100644 index 0000000..6eef415 --- /dev/null +++ b/tmpl/generatedExamEmailHTML.tmpl @@ -0,0 +1,75 @@ +

Sehr geehrte:r {{ .Teacher.Fullname }},

+ +{{ if not .HasStudentRegs }} +

Für Ihre Prüfung {{ .Exam.ZpaExam.AnCode }}. {{ .Exam.ZpaExam.Module }} liegen überhaupt keine Anmeldungen vor, daher werde ich sie nicht +planen. Falls die Prüfung dennoch eingeplant werden soll, teilen Sie mir das bitte unmittelbar +mit.

+ +{{ else }} + +

Ihre Prüfung {{ .Exam.ZpaExam.AnCode }}. {{ .Exam.ZpaExam.Module }} plane ich auf Grund folgender Daten.

+ +

Sollten die Daten aus Ihrer Sicht fehlerhaft sein, nehmen Sie bitte umgehend mit +mir Kontakt auf; insbesondere dann, wenn die Anzahl der Anmeldungen stark von der +tatsächlichen Anzahl zu Prüfenden abweicht (z.B. auf Grund des Nichtbestehens einer +Zulassungsvoraussetzung).

+ +

Sofern mir bekannt, sind Studierende mit Nachteilsausgleich unten angegeben. +Sollten Ihnen weitere Studierende mit Nachteilsausgleich bekannt sein oder bekannt werden, +geben Sie mir bitte sofort Bescheid, damit ich sie in der Planung berücksichtigen kann.

+ +
    +{{ range .Exam.PrimussExams -}} + + {{ if ne (len .StudentRegs) 0 }} +
  • Studiengang {{ .Exam.Program }} +

    + Anmeldungen: +

    + +
      + {{ range .StudentRegs }} +
    1. + {{ .Name }} +
    2. + {{end}} +
    + + {{ if ne (len .Ntas) 0 }} +

    + Studierende mit Nachteilsausgleich im Studiengang {{ .Exam.Program }} (auch in der Liste aller Anmeldungen enthalten) +

    + +
      + {{ range .Ntas }} +
    1. + {{.Name}}: {{.Compensation}} +
    2. + {{end}} +
    +

    + + {{ else }} + +

    + Im Studiengang {{ .Exam.Program }} sind mir keine Nachteilsausgleiche für diese Prüfung bekannt. +

    + + {{ end }} +
  • + {{ else }} +
  • Studiengang {{ .Exam.Program }}: Keine Anmeldungen

  • + {{ end }} + +{{ end }} +
+ +{{ end }} + +

Mit freundlichen Grüßen
+{{ .PlanerName }}

+ +
+-- 
+Diese E-Mail wurde generiert und gesendet von https://github.com/obcode/plexams.go
+
From 5fd64e24cf7d55306405788b2b4283ac67f4202d Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Mon, 20 Nov 2023 16:09:45 +0100 Subject: [PATCH 31/78] generated exams --- db/generatedExams.go | 20 ++++ graph/exam.graphqls | 1 + graph/exam.resolvers.go | 8 +- graph/generated/generated.go | 184 ++++++++++++++++++++++++++++++++++- graph/model/models_gen.go | 5 +- graph/primuss.graphqls | 1 + plexams/email.go | 2 +- plexams/generatedExams.go | 22 +++-- 8 files changed, 226 insertions(+), 17 deletions(-) diff --git a/db/generatedExams.go b/db/generatedExams.go index 9fe88d6..1991dbf 100644 --- a/db/generatedExams.go +++ b/db/generatedExams.go @@ -52,3 +52,23 @@ func (db *DB) GetGeneratedExams(ctx context.Context) ([]*model.GeneratedExam, er return exams, nil } + +func (db *DB) GetGeneratedExam(ctx context.Context, ancode int) (*model.GeneratedExam, error) { + collection := db.Client.Database(db.databaseName).Collection(collectionGeneratedExams) + + res := collection.FindOne(ctx, bson.D{{Key: "ancode", Value: ancode}}) + if res.Err() != nil { + log.Error().Err(res.Err()).Int("ancode", ancode).Msg("cannot get generated exam") + return nil, res.Err() + } + + var exam *model.GeneratedExam + + err := res.Decode(&exam) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("cannot get generated exam") + return nil, err + } + + return exam, nil +} diff --git a/graph/exam.graphqls b/graph/exam.graphqls index fedf19e..a2f9e75 100644 --- a/graph/exam.graphqls +++ b/graph/exam.graphqls @@ -5,6 +5,7 @@ extend type Query { externalExams: [ExternalExam!]! generatedExams: [GeneratedExam!]! + generatedExam(ancode: Int!): GeneratedExam exam(ancode: Int!): Exam exams: [Exam!]! diff --git a/graph/exam.resolvers.go b/graph/exam.resolvers.go index 2ca6ac0..d93b7d0 100644 --- a/graph/exam.resolvers.go +++ b/graph/exam.resolvers.go @@ -6,7 +6,6 @@ package graph import ( "context" - "fmt" "github.com/obcode/plexams.go/graph/model" ) @@ -28,7 +27,12 @@ func (r *queryResolver) ExternalExams(ctx context.Context) ([]*model.ExternalExa // GeneratedExams is the resolver for the generatedExams field. func (r *queryResolver) GeneratedExams(ctx context.Context) ([]*model.GeneratedExam, error) { - panic(fmt.Errorf("not implemented: GeneratedExams - generatedExams")) + return r.plexams.GeneratedExams(ctx) +} + +// GeneratedExam is the resolver for the generatedExam field. +func (r *queryResolver) GeneratedExam(ctx context.Context, ancode int) (*model.GeneratedExam, error) { + return r.plexams.GeneratedExam(ctx, ancode) } // Exam is the resolver for the exam field. diff --git a/graph/generated/generated.go b/graph/generated/generated.go index d1d4c45..b9c48be 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -346,8 +346,9 @@ type ComplexityRoot struct { } PrimussExamAncode struct { - Ancode func(childComplexity int) int - Program func(childComplexity int) int + Ancode func(childComplexity int) int + NumberOfStuds func(childComplexity int) int + Program func(childComplexity int) int } PrimussExamByProgram struct { @@ -381,6 +382,7 @@ type ComplexityRoot struct { ExamsWithRegs func(childComplexity int) int ExternalExams func(childComplexity int) int Fk07programs func(childComplexity int) int + GeneratedExam func(childComplexity int, ancode int) int GeneratedExams func(childComplexity int) int InvigilatorTodos func(childComplexity int) int Invigilators func(childComplexity int) int @@ -681,6 +683,7 @@ type QueryResolver interface { ConnectedExams(ctx context.Context) ([]*model.ConnectedExam, error) ExternalExams(ctx context.Context) ([]*model.ExternalExam, error) GeneratedExams(ctx context.Context) ([]*model.GeneratedExam, error) + GeneratedExam(ctx context.Context, ancode int) (*model.GeneratedExam, error) Exam(ctx context.Context, ancode int) (*model.Exam, error) Exams(ctx context.Context) ([]*model.Exam, error) StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, error) @@ -2114,6 +2117,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PrimussExamAncode.Ancode(childComplexity), true + case "PrimussExamAncode.numberOfStuds": + if e.complexity.PrimussExamAncode.NumberOfStuds == nil { + break + } + + return e.complexity.PrimussExamAncode.NumberOfStuds(childComplexity), true + case "PrimussExamAncode.program": if e.complexity.PrimussExamAncode.Program == nil { break @@ -2370,6 +2380,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.Fk07programs(childComplexity), true + case "Query.generatedExam": + if e.complexity.Query.GeneratedExam == nil { + break + } + + args, err := ec.field_Query_generatedExam_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.GeneratedExam(childComplexity, args["ancode"].(int)), true + case "Query.generatedExams": if e.complexity.Query.GeneratedExams == nil { break @@ -3602,6 +3624,7 @@ var sources = []*ast.Source{ externalExams: [ExternalExam!]! generatedExams: [GeneratedExam!]! + generatedExam(ancode: Int!): GeneratedExam exam(ancode: Int!): Exam exams: [Exam!]! @@ -3962,6 +3985,7 @@ type EnhancedPrimussExam { type PrimussExamAncode { ancode: Int! program: String! + numberOfStuds: Int! } input PrimussExamInput { @@ -4810,6 +4834,21 @@ func (ec *executionContext) field_Query_examsInSlot_args(ctx context.Context, ra return args, nil } +func (ec *executionContext) field_Query_generatedExam_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 int + if tmp, ok := rawArgs["ancode"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("ancode")) + arg0, err = ec.unmarshalNInt2int(ctx, tmp) + if err != nil { + return nil, err + } + } + args["ancode"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query_invigilatorsForDay_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -14414,6 +14453,50 @@ func (ec *executionContext) fieldContext_PrimussExamAncode_program(ctx context.C return fc, nil } +func (ec *executionContext) _PrimussExamAncode_numberOfStuds(ctx context.Context, field graphql.CollectedField, obj *model.PrimussExamAncode) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PrimussExamAncode_numberOfStuds(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.NumberOfStuds, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PrimussExamAncode_numberOfStuds(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PrimussExamAncode", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _PrimussExamByProgram_program(ctx context.Context, field graphql.CollectedField, obj *model.PrimussExamByProgram) (ret graphql.Marshaler) { fc, err := ec.fieldContext_PrimussExamByProgram_program(ctx, field) if err != nil { @@ -17104,6 +17187,70 @@ func (ec *executionContext) fieldContext_Query_generatedExams(ctx context.Contex return fc, nil } +func (ec *executionContext) _Query_generatedExam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_generatedExam(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().GeneratedExam(rctx, fc.Args["ancode"].(int)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.GeneratedExam) + fc.Result = res + return ec.marshalOGeneratedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExam(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_generatedExam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "ancode": + return ec.fieldContext_GeneratedExam_ancode(ctx, field) + case "zpaExam": + return ec.fieldContext_GeneratedExam_zpaExam(ctx, field) + case "primussExams": + return ec.fieldContext_GeneratedExam_primussExams(ctx, field) + case "constraints": + return ec.fieldContext_GeneratedExam_constraints(ctx, field) + case "conflicts": + return ec.fieldContext_GeneratedExam_conflicts(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type GeneratedExam", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_generatedExam_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Query_exam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_exam(ctx, field) if err != nil { @@ -22189,6 +22336,8 @@ func (ec *executionContext) fieldContext_ZPAConflict_primussAncodes(ctx context. return ec.fieldContext_PrimussExamAncode_ancode(ctx, field) case "program": return ec.fieldContext_PrimussExamAncode_program(ctx, field) + case "numberOfStuds": + return ec.fieldContext_PrimussExamAncode_numberOfStuds(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type PrimussExamAncode", field.Name) }, @@ -27763,6 +27912,11 @@ func (ec *executionContext) _PrimussExamAncode(ctx context.Context, sel ast.Sele if out.Values[i] == graphql.Null { out.Invalids++ } + case "numberOfStuds": + out.Values[i] = ec._PrimussExamAncode_numberOfStuds(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -28767,6 +28921,25 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "generatedExam": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_generatedExam(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "exam": field := field @@ -34041,6 +34214,13 @@ func (ec *executionContext) marshalOExternalExam2ᚖgithubᚗcomᚋobcodeᚋplex return ec._ExternalExam(ctx, sel, v) } +func (ec *executionContext) marshalOGeneratedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExam(ctx context.Context, sel ast.SelectionSet, v *model.GeneratedExam) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._GeneratedExam(ctx, sel, v) +} + func (ec *executionContext) unmarshalOInt2ᚕintᚄ(ctx context.Context, v interface{}) ([]int, error) { if v == nil { return nil, nil diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index f688e5e..a46d803 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -263,8 +263,9 @@ type PlannedExamWithNta struct { } type PrimussExamAncode struct { - Ancode int `json:"ancode"` - Program string `json:"program"` + Ancode int `json:"ancode"` + Program string `json:"program"` + NumberOfStuds int `json:"numberOfStuds"` } type PrimussExamByProgram struct { diff --git a/graph/primuss.graphqls b/graph/primuss.graphqls index c0c5011..1845a49 100644 --- a/graph/primuss.graphqls +++ b/graph/primuss.graphqls @@ -17,6 +17,7 @@ type EnhancedPrimussExam { type PrimussExamAncode { ancode: Int! program: String! + numberOfStuds: Int! } input PrimussExamInput { diff --git a/plexams/email.go b/plexams/email.go index 8211d89..1a681b4 100644 --- a/plexams/email.go +++ b/plexams/email.go @@ -55,7 +55,7 @@ func (p *Plexams) SendTestMail() error { } func (p *Plexams) SendGeneratedExamMails(ctx context.Context, run bool) error { - generatedExams, err := p.GetGeneratedExams(ctx) + generatedExams, err := p.GeneratedExams(ctx) if err != nil { log.Error().Err(err).Msg("cannot get generated exams") return err diff --git a/plexams/generatedExams.go b/plexams/generatedExams.go index 81c40b3..32cf339 100644 --- a/plexams/generatedExams.go +++ b/plexams/generatedExams.go @@ -108,8 +108,9 @@ func (p *Plexams) PrepareGeneratedExams() error { Ancode: zpaAncode, NumberOfStuds: zpaConflict.NumberOfStuds + primussConflict.NumberOfStuds, PrimussAncodes: append(zpaConflict.PrimussAncodes, &model.PrimussExamAncode{ - Ancode: primussConflict.AnCode, - Program: enhanced.Exam.Program, + Ancode: primussConflict.AnCode, + Program: enhanced.Exam.Program, + NumberOfStuds: primussConflict.NumberOfStuds, }), } } else { @@ -117,8 +118,9 @@ func (p *Plexams) PrepareGeneratedExams() error { Ancode: zpaAncode, NumberOfStuds: primussConflict.NumberOfStuds, PrimussAncodes: []*model.PrimussExamAncode{{ - Ancode: primussConflict.AnCode, - Program: enhanced.Exam.Program, + Ancode: primussConflict.AnCode, + Program: enhanced.Exam.Program, + NumberOfStuds: primussConflict.NumberOfStuds, }}, } } @@ -157,11 +159,6 @@ func (p *Plexams) PrepareGeneratedExams() error { return p.dbClient.CacheGeneratedExams(ctx, exams) } -// func (p *Plexams) generateFromConnectedExam(ctx context.Context, connectedExam *model.ConnectedExam) (*model.GeneratedExam, error) { - -// return generatedExam, nil -// } - func (p *Plexams) primussToEnhanced(ctx context.Context, exam *model.PrimussExam, ntaMap map[string]*model.NTA) (*model.EnhancedPrimussExam, error) { studentRegs, err := p.GetStudentRegs(ctx, exam) if err != nil { @@ -221,6 +218,11 @@ func primussAncodesToZpaAncodes(exams []*model.ConnectedExam, externalExams []*m return ancodesMap } -func (p *Plexams) GetGeneratedExams(ctx context.Context) ([]*model.GeneratedExam, error) { +func (p *Plexams) GeneratedExams(ctx context.Context) ([]*model.GeneratedExam, error) { return p.dbClient.GetGeneratedExams(ctx) } + +// GeneratedExam is the resolver for the generatedExam field. +func (p *Plexams) GeneratedExam(ctx context.Context, ancode int) (*model.GeneratedExam, error) { + return p.dbClient.GetGeneratedExam(ctx, ancode) +} From 15786903c9f3787533a23e115e30b9db0e0fcb3b Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Fri, 24 Nov 2023 22:22:07 +0100 Subject: [PATCH 32/78] from examGroups to exams --- cmd/prepare.go | 23 +- db/plan.go | 20 ++ graph/exam.graphqls | 1 + graph/generated/generated.go | 373 +++++++++++++++++++++++++++++- graph/model/models_gen.go | 11 +- graph/model/plan.go | 7 +- graph/plan.graphqls | 9 + graph/plan.resolvers.go | 27 +++ graph/query.graphqls | 1 + plexams/generatedExams.go | 14 +- plexams/plan.go | 416 +++------------------------------- plexams/plan_examgroups.go | 423 +++++++++++++++++++++++++++++++++++ plexams/prepare_groups.go | 13 ++ 13 files changed, 920 insertions(+), 418 deletions(-) create mode 100644 graph/plan.resolvers.go create mode 100644 plexams/plan_examgroups.go diff --git a/cmd/prepare.go b/cmd/prepare.go index d74c4f7..ed2f4bc 100644 --- a/cmd/prepare.go +++ b/cmd/prepare.go @@ -22,8 +22,9 @@ var ( generated-exams --- generate exams from connected-exams, external-exams and primuss-data --- step 2 - # studentregs --- regs per exam & regs per student --- step 2 + studentregs --- regs per exam & regs per student --- step 2 nta --- find NTAs for semester --- step 3 + # exams-with-regs --- exams from connected-exams and studentregs --- step 4 exam-groups --- group of exams in the same slot --- step 5 -- according to constraints? # partition --- generate partition of groups --- step 6 @@ -114,11 +115,11 @@ var ( os.Exit(1) } - // case "studentregs": // Deprecated: no longer needed - // err := plexams.PrepareStudentRegs() - // if err != nil { - // os.Exit(1) - // } + case "studentregs": + err := plexams.PrepareStudentRegs() + if err != nil { + os.Exit(1) + } // case "exams-with-regs": // Deprecated: no longer needed // err := plexams.PrepareExamsWithRegs() @@ -132,12 +133,18 @@ var ( os.Exit(1) } - case "exam-groups": - err := plexams.PrepareExamGroups() + case "exam-group-numbers": + err := plexams.PrepareExamGroupNumbers() if err != nil { os.Exit(1) } + // case "exam-groups": + // err := plexams.PrepareExamGroups() + // if err != nil { + // os.Exit(1) + // } + case "exam-group": if len(args) < 2 { log.Fatal("need ancode(s)") diff --git a/db/plan.go b/db/plan.go index 28a4ec4..56c18d6 100644 --- a/db/plan.go +++ b/db/plan.go @@ -105,6 +105,7 @@ func (db *DB) ExamGroupsInSlot(ctx context.Context, day int, time int) ([]*model return examGroups, nil } +// Deprecated: rm me func (db *DB) PlanEntries(ctx context.Context) ([]*model.PlanEntry, error) { collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) @@ -132,6 +133,25 @@ func (db *DB) PlanEntries(ctx context.Context) ([]*model.PlanEntry, error) { return planEntries, nil } +func (db *DB) PlannedAncodes(ctx context.Context) ([]*model.PlanAncodeEntry, error) { + collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) + cur, err := collection.Find(ctx, bson.M{}) + if err != nil { + log.Error().Err(err).Str("collection", collectionNamePlan).Msg("cannot get plan ancode entries") + return nil, err + } + defer cur.Close(ctx) + + planEntries := make([]*model.PlanAncodeEntry, 0) + err = cur.All(ctx, &planEntries) + if err != nil { + log.Error().Err(err).Str("collection", collectionNamePlan).Msg("cannot decode plan ancode entries") + return nil, err + } + + return planEntries, nil +} + func (db *DB) PlanEntryForExamGroup(ctx context.Context, examGroupCode int) (*model.PlanEntry, error) { collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) diff --git a/graph/exam.graphqls b/graph/exam.graphqls index a2f9e75..00c7e98 100644 --- a/graph/exam.graphqls +++ b/graph/exam.graphqls @@ -111,6 +111,7 @@ type GeneratedExam { primussExams: [EnhancedPrimussExam!]! constraints: Constraints conflicts: [ZPAConflict!]! + studentRegsCount: Int! } type ZPAConflict { diff --git a/graph/generated/generated.go b/graph/generated/generated.go index b9c48be..40fe377 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -200,11 +200,12 @@ type ComplexityRoot struct { } GeneratedExam struct { - Ancode func(childComplexity int) int - Conflicts func(childComplexity int) int - Constraints func(childComplexity int) int - PrimussExams func(childComplexity int) int - ZpaExam func(childComplexity int) int + Ancode func(childComplexity int) int + Conflicts func(childComplexity int) int + Constraints func(childComplexity int) int + PrimussExams func(childComplexity int) int + StudentRegsCount func(childComplexity int) int + ZpaExam func(childComplexity int) int } Invigilation struct { @@ -271,6 +272,7 @@ type ComplexityRoot struct { Mutation struct { AddAdditionalExam func(childComplexity int, exam model.AdditionalExamInput) int AddExamGroupToSlot func(childComplexity int, day int, time int, examGroupCode int) int + AddExamToSlot func(childComplexity int, day int, time int, ancode int) int AddNta func(childComplexity int, input model.NTAInput) int AddRoomToExam func(childComplexity int, input model.RoomForExamInput) int AddZpaExamToPlan func(childComplexity int, ancode int) int @@ -282,6 +284,7 @@ type ComplexityRoot struct { PlacesWithSockets func(childComplexity int, ancode int) int PossibleDays func(childComplexity int, ancode int, days []string) int RemovePrimussExam func(childComplexity int, input *model.PrimussExamInput) int + RmExamFromSlot func(childComplexity int, ancode int) int RmExamGroupFromSlot func(childComplexity int, examGroupCode int) int RmZpaExamFromPlan func(childComplexity int, ancode int) int SameSlot func(childComplexity int, ancode int, ancodes []int) int @@ -380,6 +383,7 @@ type ComplexityRoot struct { ExamsInSlot func(childComplexity int, day int, time int) int ExamsInSlotWithRooms func(childComplexity int, day int, time int) int ExamsWithRegs func(childComplexity int) int + ExamsWithoutSlot func(childComplexity int) int ExternalExams func(childComplexity int) int Fk07programs func(childComplexity int) int GeneratedExam func(childComplexity int, ancode int) int @@ -635,6 +639,8 @@ type MutationResolver interface { AddExamGroupToSlot(ctx context.Context, day int, time int, examGroupCode int) (bool, error) RmExamGroupFromSlot(ctx context.Context, examGroupCode int) (bool, error) AddRoomToExam(ctx context.Context, input model.RoomForExamInput) (bool, error) + AddExamToSlot(ctx context.Context, day int, time int, ancode int) (bool, error) + RmExamFromSlot(ctx context.Context, ancode int) (bool, error) } type QueryResolver interface { Workflow(ctx context.Context) ([]*model.Step, error) @@ -686,6 +692,7 @@ type QueryResolver interface { GeneratedExam(ctx context.Context, ancode int) (*model.GeneratedExam, error) Exam(ctx context.Context, ancode int) (*model.Exam, error) Exams(ctx context.Context) ([]*model.Exam, error) + ExamsWithoutSlot(ctx context.Context) ([]*model.GeneratedExam, error) StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, error) StudentsByName(ctx context.Context, regex string) ([]*model.Student, error) Teacher(ctx context.Context, id int) (*model.Teacher, error) @@ -1378,6 +1385,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.GeneratedExam.PrimussExams(childComplexity), true + case "GeneratedExam.studentRegsCount": + if e.complexity.GeneratedExam.StudentRegsCount == nil { + break + } + + return e.complexity.GeneratedExam.StudentRegsCount(childComplexity), true + case "GeneratedExam.zpaExam": if e.complexity.GeneratedExam.ZpaExam == nil { break @@ -1689,6 +1703,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.AddExamGroupToSlot(childComplexity, args["day"].(int), args["time"].(int), args["examGroupCode"].(int)), true + case "Mutation.addExamToSlot": + if e.complexity.Mutation.AddExamToSlot == nil { + break + } + + args, err := ec.field_Mutation_addExamToSlot_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.AddExamToSlot(childComplexity, args["day"].(int), args["time"].(int), args["ancode"].(int)), true + case "Mutation.addNTA": if e.complexity.Mutation.AddNta == nil { break @@ -1821,6 +1847,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.RemovePrimussExam(childComplexity, args["input"].(*model.PrimussExamInput)), true + case "Mutation.rmExamFromSlot": + if e.complexity.Mutation.RmExamFromSlot == nil { + break + } + + args, err := ec.field_Mutation_rmExamFromSlot_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.RmExamFromSlot(childComplexity, args["ancode"].(int)), true + case "Mutation.rmExamGroupFromSlot": if e.complexity.Mutation.RmExamGroupFromSlot == nil { break @@ -2366,6 +2404,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.ExamsWithRegs(childComplexity), true + case "Query.examsWithoutSlot": + if e.complexity.Query.ExamsWithoutSlot == nil { + break + } + + return e.complexity.Query.ExamsWithoutSlot(childComplexity), true + case "Query.externalExams": if e.complexity.Query.ExternalExams == nil { break @@ -3730,6 +3775,7 @@ type GeneratedExam { primussExams: [EnhancedPrimussExam!]! constraints: Constraints conflicts: [ZPAConflict!]! + studentRegsCount: Int! } type ZPAConflict { @@ -3902,7 +3948,16 @@ type NTAWithRegsByExam { ntas: [NTAWithRegs!] } `, BuiltIn: false}, - {Name: "../plan.graphqls", Input: `type SemesterConfig { + {Name: "../plan.graphqls", Input: `extend type Query { + examsWithoutSlot: [GeneratedExam!]! +} + +extend type Mutation { + addExamToSlot(day: Int!, time: Int!, ancode: Int!): Boolean! + rmExamFromSlot(ancode: Int!): Boolean! +} + +type SemesterConfig { days: [ExamDay!]! starttimes: [Starttime!]! slots: [Slot!]! @@ -4059,6 +4114,7 @@ type ConflictsPerProgramAncode { ntasWithRegs: [NTAWithRegs!] ntasWithRegsByTeacher: [NTAWithRegsByExamAndTeacher!] nta(mtknr: String!): NTAWithRegs + # Plan allowedSlots(examGroupCode: Int!): [Slot!] awkwardSlots(examGroupCode: Int!): [Slot!]! # slots before or after a conflict @@ -4321,6 +4377,39 @@ func (ec *executionContext) field_Mutation_addExamGroupToSlot_args(ctx context.C return args, nil } +func (ec *executionContext) field_Mutation_addExamToSlot_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 int + if tmp, ok := rawArgs["day"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("day")) + arg0, err = ec.unmarshalNInt2int(ctx, tmp) + if err != nil { + return nil, err + } + } + args["day"] = arg0 + var arg1 int + if tmp, ok := rawArgs["time"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("time")) + arg1, err = ec.unmarshalNInt2int(ctx, tmp) + if err != nil { + return nil, err + } + } + args["time"] = arg1 + var arg2 int + if tmp, ok := rawArgs["ancode"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("ancode")) + arg2, err = ec.unmarshalNInt2int(ctx, tmp) + if err != nil { + return nil, err + } + } + args["ancode"] = arg2 + return args, nil +} + func (ec *executionContext) field_Mutation_addNTA_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -4504,6 +4593,21 @@ func (ec *executionContext) field_Mutation_removePrimussExam_args(ctx context.Co return args, nil } +func (ec *executionContext) field_Mutation_rmExamFromSlot_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 int + if tmp, ok := rawArgs["ancode"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("ancode")) + arg0, err = ec.unmarshalNInt2int(ctx, tmp) + if err != nil { + return nil, err + } + } + args["ancode"] = arg0 + return args, nil +} + func (ec *executionContext) field_Mutation_rmExamGroupFromSlot_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -9878,6 +9982,50 @@ func (ec *executionContext) fieldContext_GeneratedExam_conflicts(ctx context.Con return fc, nil } +func (ec *executionContext) _GeneratedExam_studentRegsCount(ctx context.Context, field graphql.CollectedField, obj *model.GeneratedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_GeneratedExam_studentRegsCount(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.StudentRegsCount, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_GeneratedExam_studentRegsCount(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "GeneratedExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _Invigilation_roomName(ctx context.Context, field graphql.CollectedField, obj *model.Invigilation) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Invigilation_roomName(ctx, field) if err != nil { @@ -12869,6 +13017,116 @@ func (ec *executionContext) fieldContext_Mutation_addRoomToExam(ctx context.Cont return fc, nil } +func (ec *executionContext) _Mutation_addExamToSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_addExamToSlot(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().AddExamToSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int), fc.Args["ancode"].(int)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_addExamToSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_addExamToSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Mutation_rmExamFromSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_rmExamFromSlot(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().RmExamFromSlot(rctx, fc.Args["ancode"].(int)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_rmExamFromSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_rmExamFromSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _NTA_name(ctx context.Context, field graphql.CollectedField, obj *model.NTA) (ret graphql.Marshaler) { fc, err := ec.fieldContext_NTA_name(ctx, field) if err != nil { @@ -17180,6 +17438,8 @@ func (ec *executionContext) fieldContext_Query_generatedExams(ctx context.Contex return ec.fieldContext_GeneratedExam_constraints(ctx, field) case "conflicts": return ec.fieldContext_GeneratedExam_conflicts(ctx, field) + case "studentRegsCount": + return ec.fieldContext_GeneratedExam_studentRegsCount(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type GeneratedExam", field.Name) }, @@ -17233,6 +17493,8 @@ func (ec *executionContext) fieldContext_Query_generatedExam(ctx context.Context return ec.fieldContext_GeneratedExam_constraints(ctx, field) case "conflicts": return ec.fieldContext_GeneratedExam_conflicts(ctx, field) + case "studentRegsCount": + return ec.fieldContext_GeneratedExam_studentRegsCount(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type GeneratedExam", field.Name) }, @@ -17399,6 +17661,64 @@ func (ec *executionContext) fieldContext_Query_exams(ctx context.Context, field return fc, nil } +func (ec *executionContext) _Query_examsWithoutSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_examsWithoutSlot(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().ExamsWithoutSlot(rctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.GeneratedExam) + fc.Result = res + return ec.marshalNGeneratedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExamᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_examsWithoutSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "ancode": + return ec.fieldContext_GeneratedExam_ancode(ctx, field) + case "zpaExam": + return ec.fieldContext_GeneratedExam_zpaExam(ctx, field) + case "primussExams": + return ec.fieldContext_GeneratedExam_primussExams(ctx, field) + case "constraints": + return ec.fieldContext_GeneratedExam_constraints(ctx, field) + case "conflicts": + return ec.fieldContext_GeneratedExam_conflicts(ctx, field) + case "studentRegsCount": + return ec.fieldContext_GeneratedExam_studentRegsCount(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type GeneratedExam", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _Query_studentByMtknr(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_studentByMtknr(ctx, field) if err != nil { @@ -26870,6 +27190,11 @@ func (ec *executionContext) _GeneratedExam(ctx context.Context, sel ast.Selectio if out.Values[i] == graphql.Null { out.Invalids++ } + case "studentRegsCount": + out.Values[i] = ec._GeneratedExam_studentRegsCount(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -27465,6 +27790,20 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) if out.Values[i] == graphql.Null { out.Invalids++ } + case "addExamToSlot": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_addExamToSlot(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "rmExamFromSlot": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_rmExamFromSlot(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -28981,6 +29320,28 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "examsWithoutSlot": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_examsWithoutSlot(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "studentByMtknr": field := field diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index a46d803..b2c464e 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -157,11 +157,12 @@ type FK07Program struct { } type GeneratedExam struct { - Ancode int `json:"ancode"` - ZpaExam *ZPAExam `json:"zpaExam"` - PrimussExams []*EnhancedPrimussExam `json:"primussExams"` - Constraints *Constraints `json:"constraints,omitempty"` - Conflicts []*ZPAConflict `json:"conflicts"` + Ancode int `json:"ancode"` + ZpaExam *ZPAExam `json:"zpaExam"` + PrimussExams []*EnhancedPrimussExam `json:"primussExams"` + Constraints *Constraints `json:"constraints,omitempty"` + Conflicts []*ZPAConflict `json:"conflicts"` + StudentRegsCount int `json:"studentRegsCount"` } type Invigilation struct { diff --git a/graph/model/plan.go b/graph/model/plan.go index d1b32ff..57e91bd 100644 --- a/graph/model/plan.go +++ b/graph/model/plan.go @@ -10,9 +10,10 @@ type PlanEntry struct { } type PlanAncodeEntry struct { - DayNumber int `json:"dayNumber"` - SlotNumber int `json:"slotNumber"` - Ancode int `json:"ancode"` + DayNumber int `json:"dayNumber"` + SlotNumber int `json:"slotNumber"` + Ancode int `json:"ancode"` + Locked bool `json:"locked"` } type PlannedExam struct { diff --git a/graph/plan.graphqls b/graph/plan.graphqls index 608080c..451405e 100644 --- a/graph/plan.graphqls +++ b/graph/plan.graphqls @@ -1,3 +1,12 @@ +extend type Query { + examsWithoutSlot: [GeneratedExam!]! +} + +extend type Mutation { + addExamToSlot(day: Int!, time: Int!, ancode: Int!): Boolean! + rmExamFromSlot(ancode: Int!): Boolean! +} + type SemesterConfig { days: [ExamDay!]! starttimes: [Starttime!]! diff --git a/graph/plan.resolvers.go b/graph/plan.resolvers.go new file mode 100644 index 0000000..338de6d --- /dev/null +++ b/graph/plan.resolvers.go @@ -0,0 +1,27 @@ +package graph + +// This file will be automatically regenerated based on the schema, any resolver implementations +// will be copied through when generating and any unknown code will be moved to the end. +// Code generated by github.com/99designs/gqlgen version v0.17.34 + +import ( + "context" + "fmt" + + "github.com/obcode/plexams.go/graph/model" +) + +// AddExamToSlot is the resolver for the addExamToSlot field. +func (r *mutationResolver) AddExamToSlot(ctx context.Context, day int, time int, ancode int) (bool, error) { + panic(fmt.Errorf("not implemented: AddExamToSlot - addExamToSlot")) +} + +// RmExamFromSlot is the resolver for the rmExamFromSlot field. +func (r *mutationResolver) RmExamFromSlot(ctx context.Context, ancode int) (bool, error) { + panic(fmt.Errorf("not implemented: RmExamFromSlot - rmExamFromSlot")) +} + +// ExamsWithoutSlot is the resolver for the examsWithoutSlot field. +func (r *queryResolver) ExamsWithoutSlot(ctx context.Context) ([]*model.GeneratedExam, error) { + return r.plexams.ExamsWithoutSlot(ctx) +} diff --git a/graph/query.graphqls b/graph/query.graphqls index 1665bd3..5a4fa24 100644 --- a/graph/query.graphqls +++ b/graph/query.graphqls @@ -27,6 +27,7 @@ type Query { ntasWithRegs: [NTAWithRegs!] ntasWithRegsByTeacher: [NTAWithRegsByExamAndTeacher!] nta(mtknr: String!): NTAWithRegs + # Plan allowedSlots(examGroupCode: Int!): [Slot!] awkwardSlots(examGroupCode: Int!): [Slot!]! # slots before or after a conflict diff --git a/plexams/generatedExams.go b/plexams/generatedExams.go index 32cf339..e8bec21 100644 --- a/plexams/generatedExams.go +++ b/plexams/generatedExams.go @@ -79,7 +79,7 @@ func (p *Plexams) PrepareGeneratedExams() error { } spinner.Message("getting primuss exams") - + studentRegsCount := 0 enhancedPrimussExams := make([]*model.EnhancedPrimussExam, 0, len(connectedExam.PrimussExams)) for _, primussExam := range connectedExam.PrimussExams { enhanced, err := p.primussToEnhanced(ctx, primussExam, ntaMap) @@ -89,6 +89,7 @@ func (p *Plexams) PrepareGeneratedExams() error { return err } + studentRegsCount += len(enhanced.StudentRegs) enhancedPrimussExams = append(enhancedPrimussExams, enhanced) } @@ -140,11 +141,12 @@ func (p *Plexams) PrepareGeneratedExams() error { } exams = append(exams, &model.GeneratedExam{ - Ancode: connectedExam.ZpaExam.AnCode, - ZpaExam: connectedExam.ZpaExam, - PrimussExams: enhancedPrimussExams, - Constraints: constraints[connectedExam.ZpaExam.AnCode], - Conflicts: conflicts, + Ancode: connectedExam.ZpaExam.AnCode, + ZpaExam: connectedExam.ZpaExam, + PrimussExams: enhancedPrimussExams, + Constraints: constraints[connectedExam.ZpaExam.AnCode], + Conflicts: conflicts, + StudentRegsCount: studentRegsCount, }) err = spinner.Stop() diff --git a/plexams/plan.go b/plexams/plan.go index e2d5d85..3b97dc3 100644 --- a/plexams/plan.go +++ b/plexams/plan.go @@ -2,422 +2,58 @@ package plexams import ( "context" - "fmt" "sort" - "time" - set "github.com/deckarep/golang-set/v2" - "github.com/gookit/color" - "github.com/obcode/plexams.go/db" "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" - "github.com/spf13/viper" ) -func (p *Plexams) AddExamToSlot(ctx context.Context, ancode int, dayNumber int, timeNumber int) (bool, error) { - examGroup, err := p.GetExamGroupForAncode(ctx, ancode) +func (p *Plexams) ExamsWithoutSlot(ctx context.Context) ([]*model.GeneratedExam, error) { + exams, err := p.dbClient.GetGeneratedExams(ctx) if err != nil { - log.Error().Err(err).Int("ancode", ancode).Msg("cannot get exam group for ancode") - } - - return p.AddExamGroupToSlot(ctx, dayNumber, timeNumber, examGroup.ExamGroupCode) -} - -func (p *Plexams) GetExamGroupForAncode(ctx context.Context, ancode int) (*model.ExamGroup, error) { - return p.dbClient.GetExamGroupForAncode(ctx, ancode) -} - -func (p *Plexams) AddExamGroupToSlot(ctx context.Context, dayNumber int, timeNumber int, examGroupCode int) (bool, error) { - // check if slot exists - ok := false - for _, day := range p.semesterConfig.Days { - if day.Number == dayNumber { - ok = true - break - } - } - if !ok { - log.Error().Int("day", dayNumber).Msg("day does not exists") - return false, fmt.Errorf("day %d does not exist", dayNumber) - } - ok = false - for _, time := range p.semesterConfig.Starttimes { - if time.Number == timeNumber { - ok = true - break - } - } - if !ok { - log.Error().Int("time", timeNumber).Msg("time does not exists") - return false, fmt.Errorf("time %d does not exist", timeNumber) - } - - // check if examGroup exists - _, err := p.ExamGroup(ctx, examGroupCode) - if err != nil { - log.Error().Err(err).Int("examGroupCode", examGroupCode).Msg("exam group does not exist") - } - - // check if slot is allowed - allowedSlots, err := p.AllowedSlots(ctx, examGroupCode) - if err != nil { - log.Error().Err(err).Int("examGroupCode", examGroupCode).Msg("cannot get allowed slots") - } - slotIsAllowed := false - - for _, slot := range allowedSlots { - if slot.DayNumber == dayNumber && slot.SlotNumber == timeNumber { - slotIsAllowed = true - break - } - } - if !slotIsAllowed { - log.Debug().Int("day", dayNumber).Int("time", timeNumber).Int("examGroupCode", examGroupCode). - Msg("slot is not allowed") - return false, fmt.Errorf("slot (%d,%d) is not allowed for exam group %d", - dayNumber, timeNumber, examGroupCode) - } - - return p.dbClient.AddExamGroupToSlot(ctx, dayNumber, timeNumber, examGroupCode) -} - -func (p *Plexams) RmExamGroupFromSlot(ctx context.Context, examGroupCode int) (bool, error) { - return p.dbClient.RmExamGroupFromSlot(ctx, examGroupCode) -} - -func (p *Plexams) ExamGroupsInSlot(ctx context.Context, day int, time int) ([]*model.ExamGroup, error) { - return p.dbClient.ExamGroupsInSlot(ctx, day, time) -} - -func (p *Plexams) AllowedSlots(ctx context.Context, examGroupCode int) ([]*model.Slot, error) { - if p.dbClient.ExamGroupIsLocked(ctx, examGroupCode) { - return []*model.Slot{}, nil - } - examGroup, err := p.ExamGroup(ctx, examGroupCode) - if err != nil { - log.Error().Err(err).Int("examGroupCode", examGroupCode).Msg("exam group does not exist") - } - - allowedSlots := make([]*model.Slot, 0) -OUTER: - for _, slot := range examGroup.ExamGroupInfo.PossibleSlots { - // get ExamGroups for slot and check Conflicts - examGroups, err := p.ExamGroupsInSlot(ctx, slot.DayNumber, slot.SlotNumber) - if err != nil { - log.Error().Err(err).Int("day", slot.DayNumber).Int("time", slot.SlotNumber). - Msg("cannot get exam groups in slot") - return nil, err - } - for _, otherExamGroup := range examGroups { - for _, conflict := range examGroup.ExamGroupInfo.Conflicts { - if otherExamGroup.ExamGroupCode == conflict.ExamGroupCode { - continue OUTER - } - } - } - - allowedSlots = append(allowedSlots, &model.Slot{ - DayNumber: slot.DayNumber, - SlotNumber: slot.SlotNumber, - Starttime: p.getSlotTime(slot.DayNumber, slot.SlotNumber), - }) - } - - return allowedSlots, nil -} - -func (p *Plexams) AwkwardSlots(ctx context.Context, examGroupCode int) ([]*model.Slot, error) { - if p.dbClient.ExamGroupIsLocked(ctx, examGroupCode) { - return []*model.Slot{}, nil - } - examGroup, err := p.ExamGroup(ctx, examGroupCode) - if err != nil { - log.Error().Err(err).Int("examGroupCode", examGroupCode).Msg("exam group does not exist") - } - - awkwardSlots := make([]*model.Slot, 0) - for _, conflict := range examGroup.ExamGroupInfo.Conflicts { - planEntry, err := p.dbClient.PlanEntryForExamGroup(ctx, conflict.ExamGroupCode) - if err != nil { - log.Error().Err(err).Int("examGroupCode", conflict.ExamGroupCode).Msg("error while trying to get plan entry") - continue - } - - if planEntry != nil { - awkwardSlots = append(awkwardSlots, - &model.Slot{ - DayNumber: planEntry.DayNumber, - SlotNumber: planEntry.SlotNumber - 1, - Starttime: time.Time{}, - }, - &model.Slot{ - DayNumber: planEntry.DayNumber, - SlotNumber: planEntry.SlotNumber + 1, - Starttime: time.Time{}, - }, - ) - } + log.Error().Err(err).Msg("cannot get generated exams") + return nil, err } - return awkwardSlots, nil -} - -func (p *Plexams) ExamGroupsWithoutSlot(ctx context.Context) ([]*model.ExamGroup, error) { - examGroupsWithoutSlots := make([]*model.ExamGroup, 0) - - examGroups, err := p.ExamGroups(ctx) + planEntries, err := p.dbClient.PlannedAncodes(ctx) if err != nil { - log.Error().Err(err).Msg("cannot get exam groups") + log.Error().Err(err).Msg("cannot get planned ancodes") + return nil, err } - planEntries, err := p.dbClient.PlanEntries(ctx) - if err != nil { - log.Error().Err(err).Msg("cannot get plan entries") - } + examsWithotSlots := make([]*model.GeneratedExam, 0) OUTER: - for _, examGroup := range examGroups { + for _, exam := range exams { for _, planEntry := range planEntries { - if examGroup.ExamGroupCode == planEntry.ExamGroupCode { + if exam.Ancode == planEntry.Ancode { continue OUTER } } - examGroupsWithoutSlots = append(examGroupsWithoutSlots, examGroup) - } - - return examGroupsWithoutSlots, nil -} - -func (p *Plexams) AllProgramsInPlan(ctx context.Context) ([]string, error) { - examGroups, err := p.ExamGroups(ctx) - if err != nil { - log.Error().Err(err).Msg("cannot get exam groups") - } - - programSet := set.NewSet[string]() - - for _, group := range examGroups { - for _, program := range group.ExamGroupInfo.Programs { - programSet.Add(program) - } - } - - allPrograms := programSet.ToSlice() - sort.Strings(allPrograms) - - return allPrograms, nil -} - -func (p *Plexams) AncodesInPlan(ctx context.Context) ([]int, error) { - return p.dbClient.AncodesInPlan(ctx) -} - -func (p *Plexams) ExamerInPlan(ctx context.Context) ([]*model.ExamerInPlan, error) { - return p.dbClient.ExamerInPlan(ctx) -} - -func (p *Plexams) SlotForAncode(ctx context.Context, ancode int) (*model.Slot, error) { - examGroup, err := p.GetExamGroupForAncode(ctx, ancode) - if err != nil { - log.Error().Err(err).Int("ancode", ancode).Msg("cannot get exam group for ancode") - } - - if examGroup == nil { - return nil, nil - } - - return p.SlotForExamGroup(ctx, examGroup.ExamGroupCode) -} - -func (p *Plexams) SlotForExamGroup(ctx context.Context, examGroupCode int) (*model.Slot, error) { - planEntry, err := p.dbClient.PlanEntryForExamGroup(ctx, examGroupCode) - if err != nil { - log.Error().Err(err).Int("exam group code", examGroupCode).Msg("cannot get plan entry for exam group") - } - if planEntry == nil { - return nil, nil - } - - for _, slot := range p.semesterConfig.Slots { - if planEntry.DayNumber == slot.DayNumber && planEntry.SlotNumber == slot.SlotNumber { - return slot, nil - } - } - - return nil, fmt.Errorf("slot for exam group #%d not found", examGroupCode) -} - -func (p *Plexams) PlannedExamsInSlot(ctx context.Context, day int, time int) ([]*model.PlannedExamWithNta, error) { - examGroups, err := p.ExamGroupsInSlot(ctx, day, time) - if err != nil { - log.Error().Err(err).Int("day number", day).Int("slot number", time).Msg("cannot get exam group for slot") - } - if examGroups == nil { - return nil, nil - } - - ntasWithRegsByTeacher, err := p.NtasWithRegsByTeacher(ctx) - if err != nil { - log.Error().Err(err).Msg("cannot get ntas with regs") - return nil, err - } - - ancodeNTAMap := make(map[int][]*model.NTAWithRegs) - for _, ntaWithRegByTeacher := range ntasWithRegsByTeacher { - for _, ntaWithRegsByExam := range ntaWithRegByTeacher.Exams { - ancodeNTAMap[ntaWithRegsByExam.Exam.AnCode] = ntaWithRegsByExam.Ntas - } - } - - plannedExams := make([]*model.PlannedExamWithNta, 0) - for _, examGroup := range examGroups { - for _, exam := range examGroup.Exams { - ntas, ok := ancodeNTAMap[exam.Exam.Ancode] - if !ok { - ntas = nil - } - plannedExams = append(plannedExams, &model.PlannedExamWithNta{ - Exam: exam.Exam, - Constraints: exam.Constraints, - Nta: ntas, - }) - } - } - return plannedExams, nil -} - -func (p *Plexams) LockExamGroup(ctx context.Context, examGroupCode int) (*model.PlanEntry, *model.ExamGroup, error) { - planEntry, err := p.dbClient.LockExamGroup(ctx, examGroupCode) - if err != nil { - return nil, nil, err - } - examGroup, err := p.dbClient.ExamGroup(ctx, examGroupCode) - if err != nil { - return planEntry, nil, err - } - return planEntry, examGroup, nil -} - -func (p *Plexams) UnlockExamGroup(ctx context.Context, examGroupCode int) (*model.PlanEntry, *model.ExamGroup, error) { - planEntry, err := p.dbClient.UnlockExamGroup(ctx, examGroupCode) - if err != nil { - return nil, nil, err - } - examGroup, err := p.dbClient.ExamGroup(ctx, examGroupCode) - if err != nil { - return planEntry, nil, err - } - return planEntry, examGroup, nil -} - -func (p *Plexams) RemoveUnlockedExamGroupsFromPlan(ctx context.Context) (int, error) { - return p.dbClient.RemoveUnlockedExamGroupsFromPlan(ctx) -} - -func (p *Plexams) LockPlan(ctx context.Context) error { - return p.dbClient.LockPlan(ctx) -} - -func (p *Plexams) PreparePlannedExams() error { - ctx := context.Background() - examGroups, err := p.ExamGroups(ctx) - if err != nil { - log.Error().Err(err).Msg("cannot get exam groups") - return err - } - - ntas, err := p.NtasWithRegsByTeacher(ctx) - if err != nil { - log.Error().Err(err).Msg("cannot get ntas") - return err - } - - ntasMap := make(map[int][]*model.NTAWithRegs) - for _, ntaWithRegByTeacher := range ntas { - for _, ntantaWithRegByExam := range ntaWithRegByTeacher.Exams { - ntasMap[ntantaWithRegByExam.Exam.AnCode] = ntantaWithRegByExam.Ntas - } - } - - doNotPublish := viper.GetIntSlice("donotpublish") - for _, ancodeNotToPublish := range doNotPublish { - color.Yellow.Printf("do not publish: %d\n", ancodeNotToPublish) + examsWithotSlots = append(examsWithotSlots, exam) } - exams := make([]*model.ExamInPlan, 0) -OUTER: - for _, examGroup := range examGroups { - for _, exam := range examGroup.Exams { - // do not include exams not planned by me - if exam.Constraints != nil && exam.Constraints.NotPlannedByMe { - continue - } - // import from other departments will sometimes be only published there - for _, ancodeNotToPublish := range doNotPublish { - if exam.Exam.Ancode == ancodeNotToPublish { - continue OUTER - } - } - // - slot, err := p.SlotForAncode(ctx, exam.Exam.Ancode) - if err != nil { - log.Error().Err(err).Int("ancode", exam.Exam.Ancode).Msg("cannot get slot for ancode") - } - slot.Starttime = p.getSlotTime(slot.DayNumber, slot.SlotNumber) - - exams = append(exams, &model.ExamInPlan{ - Exam: exam.Exam, - Constraints: exam.Constraints, - Nta: ntasMap[exam.Exam.Ancode], - Slot: slot, - }) + // sort by student regs + examsMap := make(map[int][]*model.GeneratedExam) + for _, exam := range examsWithotSlots { + exams, ok := examsMap[exam.StudentRegsCount] + if !ok { + exams = make([]*model.GeneratedExam, 0, 1) } + examsMap[exam.StudentRegsCount] = append(exams, exam) } - examsInterface := make([]interface{}, 0, len(exams)) - for _, exam := range exams { - examsInterface = append(examsInterface, exam) - } - - err = p.dbClient.DropAndSave(context.WithValue(ctx, db.CollectionName("collectionName"), "exams_in_plan"), examsInterface) - if err != nil { - log.Error().Err(err).Msg("cannot save exams in plan") + keys := make([]int, 0, len(examsMap)) + for key := range examsMap { + keys = append(keys, key) } - color.Green.Printf("inserted %d exams\n", len(exams)) - - return nil -} - -func (p *Plexams) ExamsInPlan(ctx context.Context) ([]*model.ExamInPlan, error) { - return p.dbClient.ExamsInPlan(ctx) -} - -func (p *Plexams) ExamsInSlotWithRooms(ctx context.Context, day int, time int) ([]*model.ExamWithRegsAndRooms, error) { - examsInSlot, err := p.ExamsInSlot(ctx, day, time) - if err != nil { - log.Error().Err(err).Int("day", day).Int("time", time). - Msg("cannot get exams in slot") - return nil, err - } - - examsInSlotWithRooms := make([]*model.ExamWithRegsAndRooms, 0, len(examsInSlot)) - for _, exam := range examsInSlot { - rooms, err := p.dbClient.RoomsForAncode(ctx, exam.Exam.Ancode) - if err != nil { - log.Error().Err(err).Int("day", day).Int("time", time).Int("ancode", exam.Exam.Ancode). - Msg("cannot get rooms for ancode") - return nil, err - } - - examsInSlotWithRooms = append(examsInSlotWithRooms, &model.ExamWithRegsAndRooms{ - Exam: exam, - NormalRegs: []*model.StudentReg{}, - NtaRegs: []*model.NTAWithRegs{}, - Rooms: rooms, - }) + sort.Sort(sort.Reverse(sort.IntSlice(keys))) + examsWithotSlotsSorted := make([]*model.GeneratedExam, 0, len(examsWithotSlots)) + for _, key := range keys { + examsWithotSlotsSorted = append(examsWithotSlotsSorted, examsMap[key]...) } - return examsInSlotWithRooms, nil + return examsWithotSlotsSorted, nil } diff --git a/plexams/plan_examgroups.go b/plexams/plan_examgroups.go new file mode 100644 index 0000000..e2d5d85 --- /dev/null +++ b/plexams/plan_examgroups.go @@ -0,0 +1,423 @@ +package plexams + +import ( + "context" + "fmt" + "sort" + "time" + + set "github.com/deckarep/golang-set/v2" + "github.com/gookit/color" + "github.com/obcode/plexams.go/db" + "github.com/obcode/plexams.go/graph/model" + "github.com/rs/zerolog/log" + "github.com/spf13/viper" +) + +func (p *Plexams) AddExamToSlot(ctx context.Context, ancode int, dayNumber int, timeNumber int) (bool, error) { + examGroup, err := p.GetExamGroupForAncode(ctx, ancode) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("cannot get exam group for ancode") + } + + return p.AddExamGroupToSlot(ctx, dayNumber, timeNumber, examGroup.ExamGroupCode) +} + +func (p *Plexams) GetExamGroupForAncode(ctx context.Context, ancode int) (*model.ExamGroup, error) { + return p.dbClient.GetExamGroupForAncode(ctx, ancode) +} + +func (p *Plexams) AddExamGroupToSlot(ctx context.Context, dayNumber int, timeNumber int, examGroupCode int) (bool, error) { + // check if slot exists + ok := false + for _, day := range p.semesterConfig.Days { + if day.Number == dayNumber { + ok = true + break + } + } + if !ok { + log.Error().Int("day", dayNumber).Msg("day does not exists") + return false, fmt.Errorf("day %d does not exist", dayNumber) + } + ok = false + for _, time := range p.semesterConfig.Starttimes { + if time.Number == timeNumber { + ok = true + break + } + } + if !ok { + log.Error().Int("time", timeNumber).Msg("time does not exists") + return false, fmt.Errorf("time %d does not exist", timeNumber) + } + + // check if examGroup exists + _, err := p.ExamGroup(ctx, examGroupCode) + if err != nil { + log.Error().Err(err).Int("examGroupCode", examGroupCode).Msg("exam group does not exist") + } + + // check if slot is allowed + allowedSlots, err := p.AllowedSlots(ctx, examGroupCode) + if err != nil { + log.Error().Err(err).Int("examGroupCode", examGroupCode).Msg("cannot get allowed slots") + } + slotIsAllowed := false + + for _, slot := range allowedSlots { + if slot.DayNumber == dayNumber && slot.SlotNumber == timeNumber { + slotIsAllowed = true + break + } + } + if !slotIsAllowed { + log.Debug().Int("day", dayNumber).Int("time", timeNumber).Int("examGroupCode", examGroupCode). + Msg("slot is not allowed") + return false, fmt.Errorf("slot (%d,%d) is not allowed for exam group %d", + dayNumber, timeNumber, examGroupCode) + } + + return p.dbClient.AddExamGroupToSlot(ctx, dayNumber, timeNumber, examGroupCode) +} + +func (p *Plexams) RmExamGroupFromSlot(ctx context.Context, examGroupCode int) (bool, error) { + return p.dbClient.RmExamGroupFromSlot(ctx, examGroupCode) +} + +func (p *Plexams) ExamGroupsInSlot(ctx context.Context, day int, time int) ([]*model.ExamGroup, error) { + return p.dbClient.ExamGroupsInSlot(ctx, day, time) +} + +func (p *Plexams) AllowedSlots(ctx context.Context, examGroupCode int) ([]*model.Slot, error) { + if p.dbClient.ExamGroupIsLocked(ctx, examGroupCode) { + return []*model.Slot{}, nil + } + examGroup, err := p.ExamGroup(ctx, examGroupCode) + if err != nil { + log.Error().Err(err).Int("examGroupCode", examGroupCode).Msg("exam group does not exist") + } + + allowedSlots := make([]*model.Slot, 0) +OUTER: + for _, slot := range examGroup.ExamGroupInfo.PossibleSlots { + // get ExamGroups for slot and check Conflicts + examGroups, err := p.ExamGroupsInSlot(ctx, slot.DayNumber, slot.SlotNumber) + if err != nil { + log.Error().Err(err).Int("day", slot.DayNumber).Int("time", slot.SlotNumber). + Msg("cannot get exam groups in slot") + return nil, err + } + for _, otherExamGroup := range examGroups { + for _, conflict := range examGroup.ExamGroupInfo.Conflicts { + if otherExamGroup.ExamGroupCode == conflict.ExamGroupCode { + continue OUTER + } + } + } + + allowedSlots = append(allowedSlots, &model.Slot{ + DayNumber: slot.DayNumber, + SlotNumber: slot.SlotNumber, + Starttime: p.getSlotTime(slot.DayNumber, slot.SlotNumber), + }) + } + + return allowedSlots, nil +} + +func (p *Plexams) AwkwardSlots(ctx context.Context, examGroupCode int) ([]*model.Slot, error) { + if p.dbClient.ExamGroupIsLocked(ctx, examGroupCode) { + return []*model.Slot{}, nil + } + examGroup, err := p.ExamGroup(ctx, examGroupCode) + if err != nil { + log.Error().Err(err).Int("examGroupCode", examGroupCode).Msg("exam group does not exist") + } + + awkwardSlots := make([]*model.Slot, 0) + for _, conflict := range examGroup.ExamGroupInfo.Conflicts { + planEntry, err := p.dbClient.PlanEntryForExamGroup(ctx, conflict.ExamGroupCode) + if err != nil { + log.Error().Err(err).Int("examGroupCode", conflict.ExamGroupCode).Msg("error while trying to get plan entry") + continue + } + + if planEntry != nil { + awkwardSlots = append(awkwardSlots, + &model.Slot{ + DayNumber: planEntry.DayNumber, + SlotNumber: planEntry.SlotNumber - 1, + Starttime: time.Time{}, + }, + &model.Slot{ + DayNumber: planEntry.DayNumber, + SlotNumber: planEntry.SlotNumber + 1, + Starttime: time.Time{}, + }, + ) + } + } + + return awkwardSlots, nil +} + +func (p *Plexams) ExamGroupsWithoutSlot(ctx context.Context) ([]*model.ExamGroup, error) { + examGroupsWithoutSlots := make([]*model.ExamGroup, 0) + + examGroups, err := p.ExamGroups(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get exam groups") + } + + planEntries, err := p.dbClient.PlanEntries(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get plan entries") + } + +OUTER: + for _, examGroup := range examGroups { + for _, planEntry := range planEntries { + if examGroup.ExamGroupCode == planEntry.ExamGroupCode { + continue OUTER + } + } + examGroupsWithoutSlots = append(examGroupsWithoutSlots, examGroup) + } + + return examGroupsWithoutSlots, nil +} + +func (p *Plexams) AllProgramsInPlan(ctx context.Context) ([]string, error) { + examGroups, err := p.ExamGroups(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get exam groups") + } + + programSet := set.NewSet[string]() + + for _, group := range examGroups { + for _, program := range group.ExamGroupInfo.Programs { + programSet.Add(program) + } + } + + allPrograms := programSet.ToSlice() + sort.Strings(allPrograms) + + return allPrograms, nil +} + +func (p *Plexams) AncodesInPlan(ctx context.Context) ([]int, error) { + return p.dbClient.AncodesInPlan(ctx) +} + +func (p *Plexams) ExamerInPlan(ctx context.Context) ([]*model.ExamerInPlan, error) { + return p.dbClient.ExamerInPlan(ctx) +} + +func (p *Plexams) SlotForAncode(ctx context.Context, ancode int) (*model.Slot, error) { + examGroup, err := p.GetExamGroupForAncode(ctx, ancode) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("cannot get exam group for ancode") + } + + if examGroup == nil { + return nil, nil + } + + return p.SlotForExamGroup(ctx, examGroup.ExamGroupCode) +} + +func (p *Plexams) SlotForExamGroup(ctx context.Context, examGroupCode int) (*model.Slot, error) { + planEntry, err := p.dbClient.PlanEntryForExamGroup(ctx, examGroupCode) + if err != nil { + log.Error().Err(err).Int("exam group code", examGroupCode).Msg("cannot get plan entry for exam group") + } + if planEntry == nil { + return nil, nil + } + + for _, slot := range p.semesterConfig.Slots { + if planEntry.DayNumber == slot.DayNumber && planEntry.SlotNumber == slot.SlotNumber { + return slot, nil + } + } + + return nil, fmt.Errorf("slot for exam group #%d not found", examGroupCode) +} + +func (p *Plexams) PlannedExamsInSlot(ctx context.Context, day int, time int) ([]*model.PlannedExamWithNta, error) { + examGroups, err := p.ExamGroupsInSlot(ctx, day, time) + if err != nil { + log.Error().Err(err).Int("day number", day).Int("slot number", time).Msg("cannot get exam group for slot") + } + if examGroups == nil { + return nil, nil + } + + ntasWithRegsByTeacher, err := p.NtasWithRegsByTeacher(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get ntas with regs") + return nil, err + } + + ancodeNTAMap := make(map[int][]*model.NTAWithRegs) + for _, ntaWithRegByTeacher := range ntasWithRegsByTeacher { + for _, ntaWithRegsByExam := range ntaWithRegByTeacher.Exams { + ancodeNTAMap[ntaWithRegsByExam.Exam.AnCode] = ntaWithRegsByExam.Ntas + } + } + + plannedExams := make([]*model.PlannedExamWithNta, 0) + for _, examGroup := range examGroups { + for _, exam := range examGroup.Exams { + ntas, ok := ancodeNTAMap[exam.Exam.Ancode] + if !ok { + ntas = nil + } + plannedExams = append(plannedExams, &model.PlannedExamWithNta{ + Exam: exam.Exam, + Constraints: exam.Constraints, + Nta: ntas, + }) + } + } + return plannedExams, nil +} + +func (p *Plexams) LockExamGroup(ctx context.Context, examGroupCode int) (*model.PlanEntry, *model.ExamGroup, error) { + planEntry, err := p.dbClient.LockExamGroup(ctx, examGroupCode) + if err != nil { + return nil, nil, err + } + examGroup, err := p.dbClient.ExamGroup(ctx, examGroupCode) + if err != nil { + return planEntry, nil, err + } + return planEntry, examGroup, nil +} + +func (p *Plexams) UnlockExamGroup(ctx context.Context, examGroupCode int) (*model.PlanEntry, *model.ExamGroup, error) { + planEntry, err := p.dbClient.UnlockExamGroup(ctx, examGroupCode) + if err != nil { + return nil, nil, err + } + examGroup, err := p.dbClient.ExamGroup(ctx, examGroupCode) + if err != nil { + return planEntry, nil, err + } + return planEntry, examGroup, nil +} + +func (p *Plexams) RemoveUnlockedExamGroupsFromPlan(ctx context.Context) (int, error) { + return p.dbClient.RemoveUnlockedExamGroupsFromPlan(ctx) +} + +func (p *Plexams) LockPlan(ctx context.Context) error { + return p.dbClient.LockPlan(ctx) +} + +func (p *Plexams) PreparePlannedExams() error { + ctx := context.Background() + examGroups, err := p.ExamGroups(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get exam groups") + return err + } + + ntas, err := p.NtasWithRegsByTeacher(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get ntas") + return err + } + + ntasMap := make(map[int][]*model.NTAWithRegs) + for _, ntaWithRegByTeacher := range ntas { + for _, ntantaWithRegByExam := range ntaWithRegByTeacher.Exams { + ntasMap[ntantaWithRegByExam.Exam.AnCode] = ntantaWithRegByExam.Ntas + } + } + + doNotPublish := viper.GetIntSlice("donotpublish") + for _, ancodeNotToPublish := range doNotPublish { + color.Yellow.Printf("do not publish: %d\n", ancodeNotToPublish) + } + + exams := make([]*model.ExamInPlan, 0) +OUTER: + for _, examGroup := range examGroups { + for _, exam := range examGroup.Exams { + // do not include exams not planned by me + if exam.Constraints != nil && exam.Constraints.NotPlannedByMe { + continue + } + // import from other departments will sometimes be only published there + for _, ancodeNotToPublish := range doNotPublish { + if exam.Exam.Ancode == ancodeNotToPublish { + continue OUTER + } + } + // + slot, err := p.SlotForAncode(ctx, exam.Exam.Ancode) + if err != nil { + log.Error().Err(err).Int("ancode", exam.Exam.Ancode).Msg("cannot get slot for ancode") + } + slot.Starttime = p.getSlotTime(slot.DayNumber, slot.SlotNumber) + + exams = append(exams, &model.ExamInPlan{ + Exam: exam.Exam, + Constraints: exam.Constraints, + Nta: ntasMap[exam.Exam.Ancode], + Slot: slot, + }) + } + } + + examsInterface := make([]interface{}, 0, len(exams)) + for _, exam := range exams { + examsInterface = append(examsInterface, exam) + } + + err = p.dbClient.DropAndSave(context.WithValue(ctx, db.CollectionName("collectionName"), "exams_in_plan"), examsInterface) + if err != nil { + log.Error().Err(err).Msg("cannot save exams in plan") + } + + color.Green.Printf("inserted %d exams\n", len(exams)) + + return nil +} + +func (p *Plexams) ExamsInPlan(ctx context.Context) ([]*model.ExamInPlan, error) { + return p.dbClient.ExamsInPlan(ctx) +} + +func (p *Plexams) ExamsInSlotWithRooms(ctx context.Context, day int, time int) ([]*model.ExamWithRegsAndRooms, error) { + examsInSlot, err := p.ExamsInSlot(ctx, day, time) + if err != nil { + log.Error().Err(err).Int("day", day).Int("time", time). + Msg("cannot get exams in slot") + return nil, err + } + + examsInSlotWithRooms := make([]*model.ExamWithRegsAndRooms, 0, len(examsInSlot)) + for _, exam := range examsInSlot { + rooms, err := p.dbClient.RoomsForAncode(ctx, exam.Exam.Ancode) + if err != nil { + log.Error().Err(err).Int("day", day).Int("time", time).Int("ancode", exam.Exam.Ancode). + Msg("cannot get rooms for ancode") + return nil, err + } + + examsInSlotWithRooms = append(examsInSlotWithRooms, &model.ExamWithRegsAndRooms{ + Exam: exam, + NormalRegs: []*model.StudentReg{}, + NtaRegs: []*model.NTAWithRegs{}, + Rooms: rooms, + }) + + } + + return examsInSlotWithRooms, nil +} diff --git a/plexams/prepare_groups.go b/plexams/prepare_groups.go index 71caaf0..d09277e 100644 --- a/plexams/prepare_groups.go +++ b/plexams/prepare_groups.go @@ -47,6 +47,19 @@ func (p *Plexams) initPrepareExamGroups(ctx context.Context) (ancodesToPlan []in return } +// Group with one ancode => group number == ancoce +// Group with more ancodes => group number == smallest ancode number +func (p *Plexams) PrepareExamGroupNumbers() error { + // ctx := context.Background() + // generatedExams, err := p.dbClient.GetGeneratedExams(ctx) + // if err != nil { + // log.Error().Err(err).Msg("cannot get generated exams") + // return err + // } + + return nil +} + func (p *Plexams) PrepareExamGroups() error { ctx := context.Background() ancodes, examsWithRegs, constraints, err := p.initPrepareExamGroups(ctx) From 929658371110090241612781fa42cbfad46d9e4a Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Fri, 24 Nov 2023 22:24:10 +0100 Subject: [PATCH 33/78] make linter happy --- plexams/plan_examgroups.go | 1 + 1 file changed, 1 insertion(+) diff --git a/plexams/plan_examgroups.go b/plexams/plan_examgroups.go index e2d5d85..32c1839 100644 --- a/plexams/plan_examgroups.go +++ b/plexams/plan_examgroups.go @@ -162,6 +162,7 @@ func (p *Plexams) AwkwardSlots(ctx context.Context, examGroupCode int) ([]*model return awkwardSlots, nil } +// Deprecated: rm me func (p *Plexams) ExamGroupsWithoutSlot(ctx context.Context) ([]*model.ExamGroup, error) { examGroupsWithoutSlots := make([]*model.ExamGroup, 0) From 6137d6c4266c516075242f2f2d0783a6d5b51fb5 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Mon, 27 Nov 2023 20:13:45 +0100 Subject: [PATCH 34/78] more on exams --- cmd/plan.go | 5 +- cmd/prepare.go | 8 +- db/plan.go | 81 ++-- graph/exam.graphqls | 2 + graph/exam.resolvers.go | 5 + graph/generated/generated.go | 666 +++++++++++++++--------------- graph/model/plan.go | 8 +- graph/plan.graphqls | 3 + graph/plan.resolvers.go | 15 + graph/query.graphqls | 5 +- graph/query.resolvers.go | 20 - plexams/generate.go | 4 +- plexams/generatedExams.go | 120 +++++- plexams/generateplan/algorithm.go | 2 +- plexams/plan.go | 99 +++++ plexams/plan_examgroups.go | 104 +++-- plexams/prepare_groups.go | 14 +- 17 files changed, 671 insertions(+), 490 deletions(-) diff --git a/cmd/plan.go b/cmd/plan.go index 3dc5654..728d40e 100644 --- a/cmd/plan.go +++ b/cmd/plan.go @@ -43,6 +43,7 @@ var ( } success, err := plexams.AddExamToSlot(context.Background(), ancode, day, slot) if err != nil { + fmt.Printf("error: %v\n", err) os.Exit(1) } if success { @@ -82,7 +83,7 @@ var ( } if planEntry != nil { fmt.Printf("successfully locked exam group %d to slot (%d,%d)\n", - planEntry.ExamGroupCode, planEntry.DayNumber, planEntry.SlotNumber) + planEntry.Ancode, planEntry.DayNumber, planEntry.SlotNumber) } if examGroup != nil { for _, exam := range examGroup.Exams { @@ -105,7 +106,7 @@ var ( } if planEntry != nil { fmt.Printf("successfully unlocked exam group %d to slot (%d,%d)\n", - planEntry.ExamGroupCode, planEntry.DayNumber, planEntry.SlotNumber) + planEntry.Ancode, planEntry.DayNumber, planEntry.SlotNumber) } if examGroup != nil { for _, exam := range examGroup.Exams { diff --git a/cmd/prepare.go b/cmd/prepare.go index ed2f4bc..1927b95 100644 --- a/cmd/prepare.go +++ b/cmd/prepare.go @@ -26,7 +26,7 @@ var ( nta --- find NTAs for semester --- step 3 # exams-with-regs --- exams from connected-exams and studentregs --- step 4 - exam-groups --- group of exams in the same slot --- step 5 -- according to constraints? + # exam-groups --- group of exams in the same slot --- step 5 -- according to constraints? # partition --- generate partition of groups --- step 6 Add exam after planning has started: @@ -133,12 +133,6 @@ var ( os.Exit(1) } - case "exam-group-numbers": - err := plexams.PrepareExamGroupNumbers() - if err != nil { - os.Exit(1) - } - // case "exam-groups": // err := plexams.PrepareExamGroups() // if err != nil { diff --git a/db/plan.go b/db/plan.go index 56c18d6..b0ec068 100644 --- a/db/plan.go +++ b/db/plan.go @@ -11,46 +11,46 @@ import ( "go.mongodb.org/mongo-driver/mongo" ) -func (db *DB) AddExamGroupToSlot(ctx context.Context, dayNumber int, timeNumber int, examGroupCode int) (bool, error) { - if db.ExamGroupIsLocked(ctx, examGroupCode) { - return false, fmt.Errorf("exam group %d is locked", examGroupCode) +func (db *DB) AddExamToSlot(ctx context.Context, dayNumber int, timeNumber int, ancode int) (bool, error) { + if db.ExamGroupIsLocked(ctx, ancode) { + return false, fmt.Errorf("exam %d is locked", ancode) } collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) - _, err := collection.DeleteMany(ctx, bson.D{{Key: "examgroupcode", Value: examGroupCode}}) + _, err := collection.DeleteMany(ctx, bson.D{{Key: "ancode", Value: ancode}}) if err != nil { - log.Error().Err(err).Int("day", dayNumber).Int("time", timeNumber).Int("examGroupCode", examGroupCode). - Msg("cannot rm exam group from plan") + log.Error().Err(err).Int("day", dayNumber).Int("time", timeNumber).Int("ancode", ancode). + Msg("cannot rm exam from plan") return false, err } _, err = collection.InsertOne(ctx, &model.PlanEntry{ - DayNumber: dayNumber, - SlotNumber: timeNumber, - ExamGroupCode: examGroupCode, + DayNumber: dayNumber, + SlotNumber: timeNumber, + Ancode: ancode, }) if err != nil { - log.Error().Err(err).Int("day", dayNumber).Int("time", timeNumber).Int("examGroupCode", examGroupCode). - Msg("cannot add exam group to slot") + log.Error().Err(err).Int("day", dayNumber).Int("time", timeNumber).Int("ancode", ancode). + Msg("cannot add exam to slot") return false, err } return true, nil } -func (db *DB) RmExamGroupFromSlot(ctx context.Context, examGroupCode int) (bool, error) { - if db.ExamGroupIsLocked(ctx, examGroupCode) { - return false, fmt.Errorf("exam group %d is locked", examGroupCode) +func (db *DB) RmExamGroupFromSlot(ctx context.Context, ancode int) (bool, error) { + if db.ExamGroupIsLocked(ctx, ancode) { + return false, fmt.Errorf("exam %d is locked", ancode) } collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) - _, err := collection.DeleteMany(ctx, bson.D{{Key: "examgroupcode", Value: examGroupCode}}) + _, err := collection.DeleteMany(ctx, bson.D{{Key: "ancode", Value: ancode}}) if err != nil { - log.Error().Err(err).Int("examGroupCode", examGroupCode). - Msg("cannot rm exam group from plan") + log.Error().Err(err).Int("ancode", ancode). + Msg("cannot rm exam from plan") return false, err } @@ -94,9 +94,9 @@ func (db *DB) ExamGroupsInSlot(ctx context.Context, day int, time int) ([]*model examGroups := make([]*model.ExamGroup, 0, len(planEntries)) for _, planEntry := range planEntries { - examGroup, err := db.ExamGroup(ctx, planEntry.ExamGroupCode) + examGroup, err := db.ExamGroup(ctx, planEntry.Ancode) if err != nil { - log.Error().Err(err).Int("examGroupCode", planEntry.ExamGroupCode).Msg("cannot get exam group") + log.Error().Err(err).Int("examGroupCode", planEntry.Ancode).Msg("cannot get exam group") return examGroups, err } examGroups = append(examGroups, examGroup) @@ -176,17 +176,15 @@ func (db *DB) PlanEntryForExamGroup(ctx context.Context, examGroupCode int) (*mo } func (db *DB) AncodesInPlan(ctx context.Context) ([]int, error) { - examGroups, err := db.ExamGroups(ctx) + exams, err := db.GetGeneratedExams(ctx) if err != nil { - log.Error().Err(err).Msg("cannot get exam groups") + log.Error().Err(err).Msg("cannot get exams") } - ancodes := make([]int, 0) + ancodes := make([]int, 0, len(exams)) - for _, group := range examGroups { - for _, exam := range group.Exams { - ancodes = append(ancodes, exam.Exam.Ancode) - } + for _, exam := range exams { + ancodes = append(ancodes, exam.Ancode) } sort.Ints(ancodes) @@ -194,27 +192,26 @@ func (db *DB) AncodesInPlan(ctx context.Context) ([]int, error) { } func (db *DB) ExamerInPlan(ctx context.Context) ([]*model.ExamerInPlan, error) { - examGroups, err := db.ExamGroups(ctx) + exams, err := db.GetGeneratedExams(ctx) if err != nil { log.Error().Err(err).Msg("cannot get exam groups") } examerMap := make(map[string][]int) - for _, group := range examGroups { - EXAMLOOP: - for _, exam := range group.Exams { - examer, ok := examerMap[exam.Exam.ZpaExam.MainExamer] - if !ok { - examerMap[exam.Exam.ZpaExam.MainExamer] = []int{exam.Exam.ZpaExam.MainExamerID} - } else { - for _, examerID := range examer { - if examerID == exam.Exam.ZpaExam.MainExamerID { - continue EXAMLOOP - } + +EXAMLOOP: + for _, exam := range exams { + examer, ok := examerMap[exam.ZpaExam.MainExamer] + if !ok { + examerMap[exam.ZpaExam.MainExamer] = []int{exam.ZpaExam.MainExamerID} + } else { + for _, examerID := range examer { + if examerID == exam.ZpaExam.MainExamerID { + continue EXAMLOOP } - examer = append(examer, exam.Exam.ZpaExam.MainExamerID) - examerMap[exam.Exam.ZpaExam.MainExamer] = examer } + examer = append(examer, exam.ZpaExam.MainExamerID) + examerMap[exam.ZpaExam.MainExamer] = examer } } @@ -256,9 +253,9 @@ func (db *DB) PlanAncodeEntries(ctx context.Context) ([]*model.PlanAncodeEntry, planAncodeEntries := make([]*model.PlanAncodeEntry, 0) for _, planEntry := range planEntries { - examGroup, ok := examGroupMap[planEntry.ExamGroupCode] + examGroup, ok := examGroupMap[planEntry.Ancode] if !ok { - log.Error().Int("exam group code", planEntry.ExamGroupCode).Msg("exam group not found") + log.Error().Int("exam group code", planEntry.Ancode).Msg("exam group not found") } for _, exam := range examGroup.Exams { planAncodeEntries = append(planAncodeEntries, &model.PlanAncodeEntry{ diff --git a/graph/exam.graphqls b/graph/exam.graphqls index 00c7e98..c06e026 100644 --- a/graph/exam.graphqls +++ b/graph/exam.graphqls @@ -7,6 +7,8 @@ extend type Query { generatedExams: [GeneratedExam!]! generatedExam(ancode: Int!): GeneratedExam + conflictingAncodes(ancode: Int!): [Conflict!] + exam(ancode: Int!): Exam exams: [Exam!]! } diff --git a/graph/exam.resolvers.go b/graph/exam.resolvers.go index d93b7d0..c55bb58 100644 --- a/graph/exam.resolvers.go +++ b/graph/exam.resolvers.go @@ -35,6 +35,11 @@ func (r *queryResolver) GeneratedExam(ctx context.Context, ancode int) (*model.G return r.plexams.GeneratedExam(ctx, ancode) } +// ConflictingAncodes is the resolver for the conflictingAncodes field. +func (r *queryResolver) ConflictingAncodes(ctx context.Context, ancode int) ([]*model.Conflict, error) { + return r.plexams.ConflictingAncodes(ctx, ancode) +} + // Exam is the resolver for the exam field. func (r *queryResolver) Exam(ctx context.Context, ancode int) (*model.Exam, error) { exam, err := r.plexams.CachedExam(ctx, ancode) diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 40fe377..895fb9d 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -366,7 +366,7 @@ type ComplexityRoot struct { AllowedSlots func(childComplexity int, examGroupCode int) int AncodesInPlan func(childComplexity int) int AwkwardSlots func(childComplexity int, examGroupCode int) int - ConflictingGroupCodes func(childComplexity int, examGroupCode int) int + ConflictingAncodes func(childComplexity int, ancode int) int ConnectedExam func(childComplexity int, ancode int) int ConnectedExams func(childComplexity int) int ConstraintForAncode func(childComplexity int, ancode int) int @@ -659,7 +659,6 @@ type QueryResolver interface { ZpaExamsToPlanWithConstraints(ctx context.Context) ([]*model.ZPAExamWithConstraints, error) ExamGroups(ctx context.Context) ([]*model.ExamGroup, error) ExamGroup(ctx context.Context, examGroupCode int) (*model.ExamGroup, error) - ConflictingGroupCodes(ctx context.Context, examGroupCode int) ([]*model.ExamGroupConflict, error) Ntas(ctx context.Context) ([]*model.NTA, error) NtasWithRegs(ctx context.Context) ([]*model.NTAWithRegs, error) NtasWithRegsByTeacher(ctx context.Context) ([]*model.NTAWithRegsByExamAndTeacher, error) @@ -668,9 +667,6 @@ type QueryResolver interface { AwkwardSlots(ctx context.Context, examGroupCode int) ([]*model.Slot, error) ExamGroupsInSlot(ctx context.Context, day int, time int) ([]*model.ExamGroup, error) ExamGroupsWithoutSlot(ctx context.Context) ([]*model.ExamGroup, error) - AllProgramsInPlan(ctx context.Context) ([]string, error) - AncodesInPlan(ctx context.Context) ([]int, error) - ExamerInPlan(ctx context.Context) ([]*model.ExamerInPlan, error) PlannedExamsInSlot(ctx context.Context, day int, time int) ([]*model.PlannedExamWithNta, error) ExamsInPlan(ctx context.Context) ([]*model.ExamInPlan, error) ExamsInSlot(ctx context.Context, day int, time int) ([]*model.ExamInPlan, error) @@ -690,8 +686,12 @@ type QueryResolver interface { ExternalExams(ctx context.Context) ([]*model.ExternalExam, error) GeneratedExams(ctx context.Context) ([]*model.GeneratedExam, error) GeneratedExam(ctx context.Context, ancode int) (*model.GeneratedExam, error) + ConflictingAncodes(ctx context.Context, ancode int) ([]*model.Conflict, error) Exam(ctx context.Context, ancode int) (*model.Exam, error) Exams(ctx context.Context) ([]*model.Exam, error) + AllProgramsInPlan(ctx context.Context) ([]string, error) + AncodesInPlan(ctx context.Context) ([]int, error) + ExamerInPlan(ctx context.Context) ([]*model.ExamerInPlan, error) ExamsWithoutSlot(ctx context.Context) ([]*model.GeneratedExam, error) StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, error) StudentsByName(ctx context.Context, regex string) ([]*model.Student, error) @@ -2235,17 +2235,17 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.AwkwardSlots(childComplexity, args["examGroupCode"].(int)), true - case "Query.conflictingGroupCodes": - if e.complexity.Query.ConflictingGroupCodes == nil { + case "Query.conflictingAncodes": + if e.complexity.Query.ConflictingAncodes == nil { break } - args, err := ec.field_Query_conflictingGroupCodes_args(context.TODO(), rawArgs) + args, err := ec.field_Query_conflictingAncodes_args(context.TODO(), rawArgs) if err != nil { return 0, false } - return e.complexity.Query.ConflictingGroupCodes(childComplexity, args["examGroupCode"].(int)), true + return e.complexity.Query.ConflictingAncodes(childComplexity, args["ancode"].(int)), true case "Query.connectedExam": if e.complexity.Query.ConnectedExam == nil { @@ -3671,6 +3671,8 @@ var sources = []*ast.Source{ generatedExams: [GeneratedExam!]! generatedExam(ancode: Int!): GeneratedExam + conflictingAncodes(ancode: Int!): [Conflict!] + exam(ancode: Int!): Exam exams: [Exam!]! } @@ -3949,6 +3951,9 @@ type NTAWithRegsByExam { } `, BuiltIn: false}, {Name: "../plan.graphqls", Input: `extend type Query { + allProgramsInPlan: [String!] + ancodesInPlan: [Int!] + examerInPlan: [ExamerInPlan!] examsWithoutSlot: [GeneratedExam!]! } @@ -4108,7 +4113,6 @@ type ConflictsPerProgramAncode { # exam groups examGroups: [ExamGroup!]! examGroup(examGroupCode: Int!): ExamGroup - conflictingGroupCodes(examGroupCode: Int!): [ExamGroupConflict!] # NTAs ntas: [NTA!] ntasWithRegs: [NTAWithRegs!] @@ -4120,9 +4124,7 @@ type ConflictsPerProgramAncode { awkwardSlots(examGroupCode: Int!): [Slot!]! # slots before or after a conflict examGroupsInSlot(day: Int!, time: Int!): [ExamGroup!] examGroupsWithoutSlot: [ExamGroup!] - allProgramsInPlan: [String!] - ancodesInPlan: [Int!] - examerInPlan: [ExamerInPlan!] + # PlannedExamsWithNTA plannedExamsInSlot(day: Int!, time: Int!): [PlannedExamWithNTA!] examsInPlan: [ExamInPlan!] @@ -4752,18 +4754,18 @@ func (ec *executionContext) field_Query_awkwardSlots_args(ctx context.Context, r return args, nil } -func (ec *executionContext) field_Query_conflictingGroupCodes_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { +func (ec *executionContext) field_Query_conflictingAncodes_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} var arg0 int - if tmp, ok := rawArgs["examGroupCode"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("examGroupCode")) + if tmp, ok := rawArgs["ancode"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("ancode")) arg0, err = ec.unmarshalNInt2int(ctx, tmp) if err != nil { return nil, err } } - args["examGroupCode"] = arg0 + args["ancode"] = arg0 return args, nil } @@ -15775,64 +15777,6 @@ func (ec *executionContext) fieldContext_Query_examGroup(ctx context.Context, fi return fc, nil } -func (ec *executionContext) _Query_conflictingGroupCodes(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_conflictingGroupCodes(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ConflictingGroupCodes(rctx, fc.Args["examGroupCode"].(int)) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.([]*model.ExamGroupConflict) - fc.Result = res - return ec.marshalOExamGroupConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupConflictᚄ(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_conflictingGroupCodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "examGroupCode": - return ec.fieldContext_ExamGroupConflict_examGroupCode(ctx, field) - case "count": - return ec.fieldContext_ExamGroupConflict_count(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type ExamGroupConflict", field.Name) - }, - } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_conflictingGroupCodes_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } - return fc, nil -} - func (ec *executionContext) _Query_ntas(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_ntas(ctx, field) if err != nil { @@ -16280,135 +16224,6 @@ func (ec *executionContext) fieldContext_Query_examGroupsWithoutSlot(ctx context return fc, nil } -func (ec *executionContext) _Query_allProgramsInPlan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_allProgramsInPlan(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().AllProgramsInPlan(rctx) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.([]string) - fc.Result = res - return ec.marshalOString2ᚕstringᚄ(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_allProgramsInPlan(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") - }, - } - return fc, nil -} - -func (ec *executionContext) _Query_ancodesInPlan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_ancodesInPlan(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().AncodesInPlan(rctx) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.([]int) - fc.Result = res - return ec.marshalOInt2ᚕintᚄ(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_ancodesInPlan(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") - }, - } - return fc, nil -} - -func (ec *executionContext) _Query_examerInPlan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_examerInPlan(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ExamerInPlan(rctx) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.([]*model.ExamerInPlan) - fc.Result = res - return ec.marshalOExamerInPlan2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamerInPlanᚄ(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_examerInPlan(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "mainExamer": - return ec.fieldContext_ExamerInPlan_mainExamer(ctx, field) - case "mainExamerID": - return ec.fieldContext_ExamerInPlan_mainExamerID(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type ExamerInPlan", field.Name) - }, - } - return fc, nil -} - func (ec *executionContext) _Query_plannedExamsInSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_plannedExamsInSlot(ctx, field) if err != nil { @@ -17513,6 +17328,64 @@ func (ec *executionContext) fieldContext_Query_generatedExam(ctx context.Context return fc, nil } +func (ec *executionContext) _Query_conflictingAncodes(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_conflictingAncodes(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().ConflictingAncodes(rctx, fc.Args["ancode"].(int)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.Conflict) + fc.Result = res + return ec.marshalOConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_conflictingAncodes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "ancode": + return ec.fieldContext_Conflict_ancode(ctx, field) + case "numberOfStuds": + return ec.fieldContext_Conflict_numberOfStuds(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Conflict", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_conflictingAncodes_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Query_exam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_exam(ctx, field) if err != nil { @@ -17661,6 +17534,135 @@ func (ec *executionContext) fieldContext_Query_exams(ctx context.Context, field return fc, nil } +func (ec *executionContext) _Query_allProgramsInPlan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_allProgramsInPlan(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().AllProgramsInPlan(rctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]string) + fc.Result = res + return ec.marshalOString2ᚕstringᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_allProgramsInPlan(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Query_ancodesInPlan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_ancodesInPlan(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().AncodesInPlan(rctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]int) + fc.Result = res + return ec.marshalOInt2ᚕintᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_ancodesInPlan(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Query_examerInPlan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_examerInPlan(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().ExamerInPlan(rctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.ExamerInPlan) + fc.Result = res + return ec.marshalOExamerInPlan2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamerInPlanᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_examerInPlan(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "mainExamer": + return ec.fieldContext_ExamerInPlan_mainExamer(ctx, field) + case "mainExamerID": + return ec.fieldContext_ExamerInPlan_mainExamerID(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ExamerInPlan", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _Query_examsWithoutSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_examsWithoutSlot(ctx, field) if err != nil { @@ -28669,25 +28671,6 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "conflictingGroupCodes": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_conflictingGroupCodes(ctx, field) - return res - } - - rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, - func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "ntas": field := field @@ -28843,63 +28826,6 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "allProgramsInPlan": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_allProgramsInPlan(ctx, field) - return res - } - - rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, - func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - } - - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "ancodesInPlan": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_ancodesInPlan(ctx, field) - return res - } - - rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, - func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - } - - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "examerInPlan": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_examerInPlan(ctx, field) - return res - } - - rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, - func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "plannedExamsInSlot": field := field @@ -29279,6 +29205,25 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "conflictingAncodes": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_conflictingAncodes(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "exam": field := field @@ -29320,6 +29265,63 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "allProgramsInPlan": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_allProgramsInPlan(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "ancodesInPlan": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_ancodesInPlan(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "examerInPlan": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_examerInPlan(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "examsWithoutSlot": field := field @@ -31982,16 +31984,6 @@ func (ec *executionContext) marshalNExamGroup2ᚖgithubᚗcomᚋobcodeᚋplexams return ec._ExamGroup(ctx, sel, v) } -func (ec *executionContext) marshalNExamGroupConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupConflict(ctx context.Context, sel ast.SelectionSet, v *model.ExamGroupConflict) graphql.Marshaler { - if v == nil { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - return graphql.Null - } - return ec._ExamGroupConflict(ctx, sel, v) -} - func (ec *executionContext) marshalNExamInPlan2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamInPlan(ctx context.Context, sel ast.SelectionSet, v *model.ExamInPlan) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -34148,6 +34140,53 @@ func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast return res } +func (ec *executionContext) marshalOConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Conflict) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflict(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + func (ec *executionContext) marshalOConflicts2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflicts(ctx context.Context, sel ast.SelectionSet, v *model.Conflicts) graphql.Marshaler { if v == nil { return graphql.Null @@ -34312,53 +34351,6 @@ func (ec *executionContext) marshalOExamGroupConflict2ᚕᚖgithubᚗcomᚋobcod return ret } -func (ec *executionContext) marshalOExamGroupConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupConflictᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExamGroupConflict) graphql.Marshaler { - if v == nil { - return graphql.Null - } - ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } - for i := range v { - i := i - fc := &graphql.FieldContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithFieldContext(ctx, fc) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalNExamGroupConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupConflict(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - - } - wg.Wait() - - for _, e := range ret { - if e == graphql.Null { - return graphql.Null - } - } - - return ret -} - func (ec *executionContext) marshalOExamGroupConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupConflict(ctx context.Context, sel ast.SelectionSet, v *model.ExamGroupConflict) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/graph/model/plan.go b/graph/model/plan.go index 57e91bd..280c2d9 100644 --- a/graph/model/plan.go +++ b/graph/model/plan.go @@ -3,10 +3,10 @@ package model import "time" type PlanEntry struct { - DayNumber int `json:"dayNumber"` - SlotNumber int `json:"slotNumber"` - ExamGroupCode int `json:"examGroupCode"` - Locked bool `json:"locked"` + DayNumber int `json:"dayNumber"` + SlotNumber int `json:"slotNumber"` + Ancode int `json:"ancode"` + Locked bool `json:"locked"` } type PlanAncodeEntry struct { diff --git a/graph/plan.graphqls b/graph/plan.graphqls index 451405e..9f4d85c 100644 --- a/graph/plan.graphqls +++ b/graph/plan.graphqls @@ -1,4 +1,7 @@ extend type Query { + allProgramsInPlan: [String!] + ancodesInPlan: [Int!] + examerInPlan: [ExamerInPlan!] examsWithoutSlot: [GeneratedExam!]! } diff --git a/graph/plan.resolvers.go b/graph/plan.resolvers.go index 338de6d..aa5770a 100644 --- a/graph/plan.resolvers.go +++ b/graph/plan.resolvers.go @@ -21,6 +21,21 @@ func (r *mutationResolver) RmExamFromSlot(ctx context.Context, ancode int) (bool panic(fmt.Errorf("not implemented: RmExamFromSlot - rmExamFromSlot")) } +// AllProgramsInPlan is the resolver for the allProgramsInPlan field. +func (r *queryResolver) AllProgramsInPlan(ctx context.Context) ([]string, error) { + return r.plexams.AllProgramsInPlan(ctx) +} + +// AncodesInPlan is the resolver for the ancodesInPlan field. +func (r *queryResolver) AncodesInPlan(ctx context.Context) ([]int, error) { + return r.plexams.AncodesInPlan(ctx) +} + +// ExamerNamesInPlan is the resolver for the examerNamesInPlan field. +func (r *queryResolver) ExamerInPlan(ctx context.Context) ([]*model.ExamerInPlan, error) { + return r.plexams.ExamerInPlan(ctx) +} + // ExamsWithoutSlot is the resolver for the examsWithoutSlot field. func (r *queryResolver) ExamsWithoutSlot(ctx context.Context) ([]*model.GeneratedExam, error) { return r.plexams.ExamsWithoutSlot(ctx) diff --git a/graph/query.graphqls b/graph/query.graphqls index 5a4fa24..c2789ab 100644 --- a/graph/query.graphqls +++ b/graph/query.graphqls @@ -21,7 +21,6 @@ type Query { # exam groups examGroups: [ExamGroup!]! examGroup(examGroupCode: Int!): ExamGroup - conflictingGroupCodes(examGroupCode: Int!): [ExamGroupConflict!] # NTAs ntas: [NTA!] ntasWithRegs: [NTAWithRegs!] @@ -33,9 +32,7 @@ type Query { awkwardSlots(examGroupCode: Int!): [Slot!]! # slots before or after a conflict examGroupsInSlot(day: Int!, time: Int!): [ExamGroup!] examGroupsWithoutSlot: [ExamGroup!] - allProgramsInPlan: [String!] - ancodesInPlan: [Int!] - examerInPlan: [ExamerInPlan!] + # PlannedExamsWithNTA plannedExamsInSlot(day: Int!, time: Int!): [PlannedExamWithNTA!] examsInPlan: [ExamInPlan!] diff --git a/graph/query.resolvers.go b/graph/query.resolvers.go index 5fcdcb2..03cfc16 100644 --- a/graph/query.resolvers.go +++ b/graph/query.resolvers.go @@ -92,11 +92,6 @@ func (r *queryResolver) ExamGroup(ctx context.Context, examGroupCode int) (*mode return r.plexams.ExamGroup(ctx, examGroupCode) } -// ConflictingGroupCodes is the resolver for the conflictingGroupCodes field. -func (r *queryResolver) ConflictingGroupCodes(ctx context.Context, examGroupCode int) ([]*model.ExamGroupConflict, error) { - return r.plexams.ConflictingGroupCodes(ctx, examGroupCode) -} - // Ntas is the resolver for the ntas field. func (r *queryResolver) Ntas(ctx context.Context) ([]*model.NTA, error) { return r.plexams.Ntas(ctx) @@ -137,21 +132,6 @@ func (r *queryResolver) ExamGroupsWithoutSlot(ctx context.Context) ([]*model.Exa return r.plexams.ExamGroupsWithoutSlot(ctx) } -// AllProgramsInPlan is the resolver for the allProgramsInPlan field. -func (r *queryResolver) AllProgramsInPlan(ctx context.Context) ([]string, error) { - return r.plexams.AllProgramsInPlan(ctx) -} - -// AncodesInPlan is the resolver for the ancodesInPlan field. -func (r *queryResolver) AncodesInPlan(ctx context.Context) ([]int, error) { - return r.plexams.AncodesInPlan(ctx) -} - -// ExamerNamesInPlan is the resolver for the examerNamesInPlan field. -func (r *queryResolver) ExamerInPlan(ctx context.Context) ([]*model.ExamerInPlan, error) { - return r.plexams.ExamerInPlan(ctx) -} - // PlannedExamsInSlot is the resolver for the plannedExamsInSlot field. func (r *queryResolver) PlannedExamsInSlot(ctx context.Context, day int, time int) ([]*model.PlannedExamWithNta, error) { return r.plexams.PlannedExamsInSlot(ctx, day, time) diff --git a/plexams/generate.go b/plexams/generate.go index d294995..58fa455 100644 --- a/plexams/generate.go +++ b/plexams/generate.go @@ -66,9 +66,9 @@ func (p *Plexams) GeneratePlan(ctx context.Context) error { newPlanEntries := make([]*model.PlanEntry, 0) for _, entry := range plan { - planEntry, err := p.dbClient.PlanEntryForExamGroup(ctx, entry.ExamGroupCode) + planEntry, err := p.dbClient.PlanEntryForExamGroup(ctx, entry.Ancode) if err != nil { - log.Error().Err(err).Int("examgroupcode", entry.ExamGroupCode).Msg("cannot get plan entry for exam group code") + log.Error().Err(err).Int("examgroupcode", entry.Ancode).Msg("cannot get plan entry for exam group code") return err } // if entry is already in plan, day and slot should be the same diff --git a/plexams/generatedExams.go b/plexams/generatedExams.go index e8bec21..98a396c 100644 --- a/plexams/generatedExams.go +++ b/plexams/generatedExams.go @@ -2,6 +2,7 @@ package plexams import ( "context" + "fmt" "sort" "time" @@ -20,6 +21,8 @@ func (p *Plexams) PrepareGeneratedExams() error { return err } + // TODO: connectedExamsMap + constraints, err := p.ConstraintsMap(ctx) if err != nil { log.Error().Err(err).Msg("cannot get connected exams") @@ -49,7 +52,7 @@ func (p *Plexams) PrepareGeneratedExams() error { for _, connectedExam := range connectedExams { // // TODO: remove me - // if connectedExam.ZpaExam.AnCode != 390 && connectedExam.ZpaExam.AnCode != 393 && connectedExam.ZpaExam.AnCode != 440 { + // if connectedExam.ZpaExam.AnCode != 390 && connectedExam.ZpaExam.AnCode != 393 && connectedExam.ZpaExam.AnCode != 294 { // continue // } @@ -78,7 +81,7 @@ func (p *Plexams) PrepareGeneratedExams() error { log.Debug().Err(err).Msg("cannot start spinner") } - spinner.Message("getting primuss exams") + spinner.Message("adding primuss data") studentRegsCount := 0 enhancedPrimussExams := make([]*model.EnhancedPrimussExam, 0, len(connectedExam.PrimussExams)) for _, primussExam := range connectedExam.PrimussExams { @@ -93,8 +96,6 @@ func (p *Plexams) PrepareGeneratedExams() error { enhancedPrimussExams = append(enhancedPrimussExams, enhanced) } - spinner.Message("recalculating conflicts") - conflictsMap := make(map[int]*model.ZPAConflict) for _, enhanced := range enhancedPrimussExams { for _, primussConflict := range enhanced.Conflicts { @@ -158,6 +159,98 @@ func (p *Plexams) PrepareGeneratedExams() error { // TODO: External Exams with student regs, ... // automatically set notPlannedByMe constraint + // spinner.Message("recalculating conflicts") + // TODO: for recalculating the conflicts wee need also the exams which have to be in the same slot + // primussExamsForConflicts := make([]*model.EnhancedPrimussExam) + + conflictsPerAncode := make(map[int][]*model.ZPAConflict) + for _, exam := range exams { + conflictsPerAncode[exam.Ancode] = exam.Conflicts + } + + fmt.Println() + + for _, exam := range exams { + // // TODO: remove me + // if exam.ZpaExam.AnCode != 390 && exam.ZpaExam.AnCode != 393 && exam.ZpaExam.AnCode != 294 { + // continue + // } + + if exam.Constraints != nil && len(exam.Constraints.SameSlot) > 0 { + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Cyan(" recalculating conflicts for exam %d. %s (%s) with same slot constraints %v, was %2d"), + aurora.Yellow(exam.ZpaExam.AnCode), + aurora.Magenta(exam.ZpaExam.Module), + aurora.Magenta(exam.ZpaExam.MainExamer), + aurora.Red(exam.Constraints.SameSlot), + aurora.Red(len(exam.Conflicts)), + ), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + conflictsMap := make(map[int]*model.ZPAConflict) + for _, conflict := range exam.Conflicts { + conflictsMap[conflict.Ancode] = conflict + } + + for _, ancode := range exam.Constraints.SameSlot { + otherConflicts, ok := conflictsPerAncode[ancode] + if !ok { + spinner.Message("cannot get other conflicts") + } + + for _, otherConflict := range otherConflicts { + conflictEntry, ok := conflictsMap[otherConflict.Ancode] + if !ok { + conflictsMap[otherConflict.Ancode] = otherConflict + } else { + conflictsMap[otherConflict.Ancode] = &model.ZPAConflict{ + Ancode: conflictEntry.Ancode, + NumberOfStuds: conflictEntry.NumberOfStuds + otherConflict.NumberOfStuds, + PrimussAncodes: append(conflictEntry.PrimussAncodes, otherConflict.PrimussAncodes...), + } + } + } + } + + keys := make([]int, 0, len(conflictsMap)) + for key := range conflictsMap { + keys = append(keys, key) + } + sort.Ints(keys) + + conflicts := make([]*model.ZPAConflict, 0, len(conflictsMap)) + for _, key := range keys { + conflicts = append(conflicts, conflictsMap[key]) + } + + exam.Conflicts = conflicts + + spinner.StopMessage(aurora.Sprintf(aurora.Green("now %d constraints"), + aurora.Red(len(exam.Conflicts)), + )) + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + } + } + return p.dbClient.CacheGeneratedExams(ctx, exams) } @@ -228,3 +321,22 @@ func (p *Plexams) GeneratedExams(ctx context.Context) ([]*model.GeneratedExam, e func (p *Plexams) GeneratedExam(ctx context.Context, ancode int) (*model.GeneratedExam, error) { return p.dbClient.GetGeneratedExam(ctx, ancode) } + +// ConflictingAncodes is the resolver for the conflictingAncodes field. +func (p *Plexams) ConflictingAncodes(ctx context.Context, ancode int) ([]*model.Conflict, error) { + exam, err := p.dbClient.GetGeneratedExam(ctx, ancode) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("cannot get generated exam") + return nil, err + } + + conflicts := make([]*model.Conflict, 0, len(exam.Conflicts)) + for _, zpaConflict := range exam.Conflicts { + conflicts = append(conflicts, &model.Conflict{ + AnCode: zpaConflict.Ancode, + NumberOfStuds: zpaConflict.NumberOfStuds, + }) + } + + return conflicts, nil +} diff --git a/plexams/generateplan/algorithm.go b/plexams/generateplan/algorithm.go index 3a70173..da1822d 100644 --- a/plexams/generateplan/algorithm.go +++ b/plexams/generateplan/algorithm.go @@ -87,7 +87,7 @@ func (algorithm *Algorithm) NRuns(n int) ([]*model.PlanEntry, error) { var exportPlan []*model.PlanEntry for _, exam := range plan.exams { exportPlan = append(exportPlan, - &model.PlanEntry{DayNumber: exam.day, SlotNumber: exam.slot, ExamGroupCode: exam.examGroup.ExamGroupCode, Locked: false}) + &model.PlanEntry{DayNumber: exam.day, SlotNumber: exam.slot, Ancode: exam.examGroup.ExamGroupCode, Locked: false}) } return exportPlan, nil } diff --git a/plexams/plan.go b/plexams/plan.go index 3b97dc3..1e72ab6 100644 --- a/plexams/plan.go +++ b/plexams/plan.go @@ -2,12 +2,107 @@ package plexams import ( "context" + "fmt" "sort" "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" ) +func (p *Plexams) AddExamToSlot(ctx context.Context, ancode int, dayNumber int, timeNumber int) (bool, error) { + // check if slot exists + ok := false + for _, day := range p.semesterConfig.Days { + if day.Number == dayNumber { + ok = true + break + } + } + if !ok { + log.Error().Int("day", dayNumber).Msg("day does not exists") + return false, fmt.Errorf("day %d does not exist", dayNumber) + } + ok = false + for _, time := range p.semesterConfig.Starttimes { + if time.Number == timeNumber { + ok = true + break + } + } + if !ok { + log.Error().Int("time", timeNumber).Msg("time does not exists") + return false, fmt.Errorf("time %d does not exist", timeNumber) + } + + // check if exam with ancode exists + exam, err := p.GeneratedExam(ctx, ancode) + if err != nil || exam == nil { + log.Error().Err(err).Int("ancode", ancode).Msg("exam does not exist or does not need to be planned") + return false, err + } + + // TODO: check if slot is allowed + // allowedSlots, err := p.AllowedSlots(ctx, ancode) + // if err != nil { + // log.Error().Err(err).Int("ancode", ancode).Msg("cannot get allowed slots") + // } + // slotIsAllowed := false + + // for _, slot := range allowedSlots { + // if slot.DayNumber == dayNumber && slot.SlotNumber == timeNumber { + // slotIsAllowed = true + // break + // } + // } + // if !slotIsAllowed { + // log.Debug().Int("day", dayNumber).Int("time", timeNumber).Int("ancode", ancode). + // Msg("slot is not allowed") + // return false, fmt.Errorf("slot (%d,%d) is not allowed for exam group %d", + // dayNumber, timeNumber, ancode) + // } + + return p.dbClient.AddExamToSlot(ctx, dayNumber, timeNumber, ancode) +} + +func (p *Plexams) AllowedSlots(ctx context.Context, ancode int) ([]*model.Slot, error) { + return nil, nil + + // if p.dbClient.ExamIsLocked(ctx, ancode) { + // return []*model.Slot{}, nil + // } + // exam, err := p.GeneratedExam(ctx, ancode) + // if err != nil { + // log.Error().Err(err).Int("ancode", ancode).Msg("exam does not exist") + // } + + // allowedSlots := make([]*model.Slot, 0) + // OUTER: + // for _, slot := range exam.Constraints.PossibleSlots { + // // get ExamGroups for slot and check Conflicts + // examGroups, err := p.ExamGroupsInSlot(ctx, slot.DayNumber, slot.SlotNumber) + // if err != nil { + // log.Error().Err(err).Int("day", slot.DayNumber).Int("time", slot.SlotNumber). + // Msg("cannot get exam groups in slot") + // return nil, err + // } + // for _, otherExamGroup := range examGroups { + // for _, conflict := range examGroup.ExamGroupInfo.Conflicts { + // if otherExamGroup.ExamGroupCode == conflict.ExamGroupCode { + // continue OUTER + // } + // } + // } + + // allowedSlots = append(allowedSlots, &model.Slot{ + // DayNumber: slot.DayNumber, + // SlotNumber: slot.SlotNumber, + // Starttime: p.getSlotTime(slot.DayNumber, slot.SlotNumber), + // }) + // } + + // return allowedSlots, nil +} + func (p *Plexams) ExamsWithoutSlot(ctx context.Context) ([]*model.GeneratedExam, error) { exams, err := p.dbClient.GetGeneratedExams(ctx) if err != nil { @@ -57,3 +152,7 @@ OUTER: return examsWithotSlotsSorted, nil } + +func (p *Plexams) AncodesInPlan(ctx context.Context) ([]int, error) { + return p.dbClient.AncodesInPlan(ctx) +} diff --git a/plexams/plan_examgroups.go b/plexams/plan_examgroups.go index 32c1839..32b2c61 100644 --- a/plexams/plan_examgroups.go +++ b/plexams/plan_examgroups.go @@ -14,14 +14,14 @@ import ( "github.com/spf13/viper" ) -func (p *Plexams) AddExamToSlot(ctx context.Context, ancode int, dayNumber int, timeNumber int) (bool, error) { - examGroup, err := p.GetExamGroupForAncode(ctx, ancode) - if err != nil { - log.Error().Err(err).Int("ancode", ancode).Msg("cannot get exam group for ancode") - } +// func (p *Plexams) AddExamToSlot(ctx context.Context, ancode int, dayNumber int, timeNumber int) (bool, error) { +// examGroup, err := p.GetExamGroupForAncode(ctx, ancode) +// if err != nil { +// log.Error().Err(err).Int("ancode", ancode).Msg("cannot get exam group for ancode") +// } - return p.AddExamGroupToSlot(ctx, dayNumber, timeNumber, examGroup.ExamGroupCode) -} +// return p.AddExamGroupToSlot(ctx, dayNumber, timeNumber, examGroup.ExamGroupCode) +// } func (p *Plexams) GetExamGroupForAncode(ctx context.Context, ancode int) (*model.ExamGroup, error) { return p.dbClient.GetExamGroupForAncode(ctx, ancode) @@ -78,7 +78,7 @@ func (p *Plexams) AddExamGroupToSlot(ctx context.Context, dayNumber int, timeNum dayNumber, timeNumber, examGroupCode) } - return p.dbClient.AddExamGroupToSlot(ctx, dayNumber, timeNumber, examGroupCode) + return p.dbClient.AddExamToSlot(ctx, dayNumber, timeNumber, examGroupCode) } func (p *Plexams) RmExamGroupFromSlot(ctx context.Context, examGroupCode int) (bool, error) { @@ -89,42 +89,42 @@ func (p *Plexams) ExamGroupsInSlot(ctx context.Context, day int, time int) ([]*m return p.dbClient.ExamGroupsInSlot(ctx, day, time) } -func (p *Plexams) AllowedSlots(ctx context.Context, examGroupCode int) ([]*model.Slot, error) { - if p.dbClient.ExamGroupIsLocked(ctx, examGroupCode) { - return []*model.Slot{}, nil - } - examGroup, err := p.ExamGroup(ctx, examGroupCode) - if err != nil { - log.Error().Err(err).Int("examGroupCode", examGroupCode).Msg("exam group does not exist") - } - - allowedSlots := make([]*model.Slot, 0) -OUTER: - for _, slot := range examGroup.ExamGroupInfo.PossibleSlots { - // get ExamGroups for slot and check Conflicts - examGroups, err := p.ExamGroupsInSlot(ctx, slot.DayNumber, slot.SlotNumber) - if err != nil { - log.Error().Err(err).Int("day", slot.DayNumber).Int("time", slot.SlotNumber). - Msg("cannot get exam groups in slot") - return nil, err - } - for _, otherExamGroup := range examGroups { - for _, conflict := range examGroup.ExamGroupInfo.Conflicts { - if otherExamGroup.ExamGroupCode == conflict.ExamGroupCode { - continue OUTER - } - } - } - - allowedSlots = append(allowedSlots, &model.Slot{ - DayNumber: slot.DayNumber, - SlotNumber: slot.SlotNumber, - Starttime: p.getSlotTime(slot.DayNumber, slot.SlotNumber), - }) - } - - return allowedSlots, nil -} +// func (p *Plexams) AllowedSlots(ctx context.Context, examGroupCode int) ([]*model.Slot, error) { +// if p.dbClient.ExamGroupIsLocked(ctx, examGroupCode) { +// return []*model.Slot{}, nil +// } +// examGroup, err := p.ExamGroup(ctx, examGroupCode) +// if err != nil { +// log.Error().Err(err).Int("examGroupCode", examGroupCode).Msg("exam group does not exist") +// } + +// allowedSlots := make([]*model.Slot, 0) +// OUTER: +// for _, slot := range examGroup.ExamGroupInfo.PossibleSlots { +// // get ExamGroups for slot and check Conflicts +// examGroups, err := p.ExamGroupsInSlot(ctx, slot.DayNumber, slot.SlotNumber) +// if err != nil { +// log.Error().Err(err).Int("day", slot.DayNumber).Int("time", slot.SlotNumber). +// Msg("cannot get exam groups in slot") +// return nil, err +// } +// for _, otherExamGroup := range examGroups { +// for _, conflict := range examGroup.ExamGroupInfo.Conflicts { +// if otherExamGroup.ExamGroupCode == conflict.ExamGroupCode { +// continue OUTER +// } +// } +// } + +// allowedSlots = append(allowedSlots, &model.Slot{ +// DayNumber: slot.DayNumber, +// SlotNumber: slot.SlotNumber, +// Starttime: p.getSlotTime(slot.DayNumber, slot.SlotNumber), +// }) +// } + +// return allowedSlots, nil +// } func (p *Plexams) AwkwardSlots(ctx context.Context, examGroupCode int) ([]*model.Slot, error) { if p.dbClient.ExamGroupIsLocked(ctx, examGroupCode) { @@ -179,7 +179,7 @@ func (p *Plexams) ExamGroupsWithoutSlot(ctx context.Context) ([]*model.ExamGroup OUTER: for _, examGroup := range examGroups { for _, planEntry := range planEntries { - if examGroup.ExamGroupCode == planEntry.ExamGroupCode { + if examGroup.ExamGroupCode == planEntry.Ancode { continue OUTER } } @@ -190,16 +190,16 @@ OUTER: } func (p *Plexams) AllProgramsInPlan(ctx context.Context) ([]string, error) { - examGroups, err := p.ExamGroups(ctx) + exams, err := p.GeneratedExams(ctx) if err != nil { - log.Error().Err(err).Msg("cannot get exam groups") + log.Error().Err(err).Msg("cannot get exams") } programSet := set.NewSet[string]() - for _, group := range examGroups { - for _, program := range group.ExamGroupInfo.Programs { - programSet.Add(program) + for _, exam := range exams { + for _, primussExam := range exam.PrimussExams { + programSet.Add(primussExam.Exam.Program) } } @@ -209,10 +209,6 @@ func (p *Plexams) AllProgramsInPlan(ctx context.Context) ([]string, error) { return allPrograms, nil } -func (p *Plexams) AncodesInPlan(ctx context.Context) ([]int, error) { - return p.dbClient.AncodesInPlan(ctx) -} - func (p *Plexams) ExamerInPlan(ctx context.Context) ([]*model.ExamerInPlan, error) { return p.dbClient.ExamerInPlan(ctx) } diff --git a/plexams/prepare_groups.go b/plexams/prepare_groups.go index d09277e..840a8a5 100644 --- a/plexams/prepare_groups.go +++ b/plexams/prepare_groups.go @@ -47,19 +47,7 @@ func (p *Plexams) initPrepareExamGroups(ctx context.Context) (ancodesToPlan []in return } -// Group with one ancode => group number == ancoce -// Group with more ancodes => group number == smallest ancode number -func (p *Plexams) PrepareExamGroupNumbers() error { - // ctx := context.Background() - // generatedExams, err := p.dbClient.GetGeneratedExams(ctx) - // if err != nil { - // log.Error().Err(err).Msg("cannot get generated exams") - // return err - // } - - return nil -} - +// Deprecated: no more exam groups func (p *Plexams) PrepareExamGroups() error { ctx := context.Background() ancodes, examsWithRegs, constraints, err := p.initPrepareExamGroups(ctx) From 3af0015ade0874fe1afd408916f42e9c228d0246 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Wed, 29 Nov 2023 15:32:10 +0100 Subject: [PATCH 35/78] rewrite student regs and nta --- cmd/prepare.go | 54 +- db/nta.go | 9 +- db/plan.go | 63 ++- db/prepare_studentregs.go | 24 + graph/generated/generated.go | 983 +++++++++++++++++------------------ graph/nta.graphqls | 5 + graph/nta.resolvers.go | 21 + graph/plan.graphqls | 5 + graph/plan.resolvers.go | 15 + graph/query.graphqls | 7 +- graph/query.resolvers.go | 32 +- plexams/generatedExams.go | 3 + plexams/nta.go | 160 +++--- plexams/plan.go | 33 +- plexams/plan_examgroups.go | 74 ++- plexams/plannedExams.go | 4 - plexams/prepare.go | 160 +++--- plexams/roomsForNTA.go | 110 ++-- plexams/validate.go | 6 +- 19 files changed, 879 insertions(+), 889 deletions(-) create mode 100644 graph/nta.resolvers.go diff --git a/cmd/prepare.go b/cmd/prepare.go index 1927b95..6fcf1dd 100644 --- a/cmd/prepare.go +++ b/cmd/prepare.go @@ -139,36 +139,36 @@ var ( // os.Exit(1) // } - case "exam-group": - if len(args) < 2 { - log.Fatal("need ancode(s)") - } - ancodes := make([]int, 0, len(args)-1) - for _, arg := range args[1:] { - ancode, err := strconv.Atoi(arg) - if err != nil { - fmt.Printf("cannot use %s as ancode", args[1]) - os.Exit(1) - } - ancodes = append(ancodes, ancode) - } + // case "exam-group": + // if len(args) < 2 { + // log.Fatal("need ancode(s)") + // } + // ancodes := make([]int, 0, len(args)-1) + // for _, arg := range args[1:] { + // ancode, err := strconv.Atoi(arg) + // if err != nil { + // fmt.Printf("cannot use %s as ancode", args[1]) + // os.Exit(1) + // } + // ancodes = append(ancodes, ancode) + // } - err := plexams.PrepareExamGroup(ancodes) - if err != nil { - os.Exit(1) - } + // err := plexams.PrepareExamGroup(ancodes) + // if err != nil { + // os.Exit(1) + // } - case "partition": - err := plexams.PartitionGroups() - if err != nil { - os.Exit(1) - } + // case "partition": + // err := plexams.PartitionGroups() + // if err != nil { + // os.Exit(1) + // } - case "nta": // Deprecated: no longer needed? - err := plexams.PrepareNta() - if err != nil { - os.Exit(1) - } + // case "nta": // Deprecated: part of generate exams + // err := plexams.PrepareNta() + // if err != nil { + // os.Exit(1) + // } case "exams-in-plan": err := plexams.PreparePlannedExams() diff --git a/db/nta.go b/db/nta.go index df96f2c..83da035 100644 --- a/db/nta.go +++ b/db/nta.go @@ -64,21 +64,20 @@ func (db *DB) Ntas(ctx context.Context) ([]*model.NTA, error) { return ntas, nil } -// // Deprecated: remove me -func (db *DB) NtasWithRegs(ctx context.Context) ([]*model.NTAWithRegs, error) { - collection := db.Client.Database(db.databaseName).Collection(collectionNameNTAs) +func (db *DB) NtasWithRegs(ctx context.Context) ([]*model.Student, error) { + collection := db.Client.Database(db.databaseName).Collection(collectionStudentRegsPerStudentPlanned) findOptions := options.Find() findOptions.SetSort(bson.D{{Key: "nta.name", Value: 1}}) - cur, err := collection.Find(ctx, bson.M{}, findOptions) + cur, err := collection.Find(ctx, bson.D{{Key: "nta", Value: bson.D{{Key: "$ne", Value: nil}}}}, findOptions) if err != nil { log.Error().Err(err).Str("collection", "nta").Msg("MongoDB Find") return nil, err } defer cur.Close(ctx) - ntas := make([]*model.NTAWithRegs, 0) + ntas := make([]*model.Student, 0) err = cur.All(ctx, &ntas) if err != nil { log.Error().Err(err).Str("collection", collectionNameNTAs).Msg("Cannot decode to rooms") diff --git a/db/plan.go b/db/plan.go index b0ec068..0cbd138 100644 --- a/db/plan.go +++ b/db/plan.go @@ -57,7 +57,7 @@ func (db *DB) RmExamGroupFromSlot(ctx context.Context, ancode int) (bool, error) return true, nil } -func (db *DB) ExamGroupsInSlot(ctx context.Context, day int, time int) ([]*model.ExamGroup, error) { +func (db *DB) GetExamsInSlot(ctx context.Context, day int, time int) ([]*model.GeneratedExam, error) { collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) filter := bson.M{ @@ -74,35 +74,25 @@ func (db *DB) ExamGroupsInSlot(ctx context.Context, day int, time int) ([]*model defer cur.Close(ctx) planEntries := make([]*model.PlanEntry, 0) - for cur.Next(ctx) { - var planEntry model.PlanEntry - - err := cur.Decode(&planEntry) - if err != nil { - log.Error().Err(err).Str("collection", collectionNamePlan).Interface("cur", cur). - Msg("Cannot decode to nta") - return nil, err - } - - planEntries = append(planEntries, &planEntry) - } - if err := cur.Err(); err != nil { - log.Error().Err(err).Str("collection", collectionNamePlan).Msg("Cursor returned error") + err = cur.All(ctx, &planEntries) + if err != nil { + log.Error().Err(err).Str("collection", collectionNamePlan).Interface("cur", cur). + Msg("Cannot decode to nta") return nil, err } - examGroups := make([]*model.ExamGroup, 0, len(planEntries)) + exams := make([]*model.GeneratedExam, 0, len(planEntries)) for _, planEntry := range planEntries { - examGroup, err := db.ExamGroup(ctx, planEntry.Ancode) + exam, err := db.GetGeneratedExam(ctx, planEntry.Ancode) if err != nil { - log.Error().Err(err).Int("examGroupCode", planEntry.Ancode).Msg("cannot get exam group") - return examGroups, err + log.Error().Err(err).Int("ancode", planEntry.Ancode).Msg("cannot get exam") + return nil, err } - examGroups = append(examGroups, examGroup) + exams = append(exams, exam) } - return examGroups, nil + return exams, nil } // Deprecated: rm me @@ -152,6 +142,30 @@ func (db *DB) PlannedAncodes(ctx context.Context) ([]*model.PlanAncodeEntry, err return planEntries, nil } +func (db *DB) PlanEntry(ctx context.Context, ancode int) (*model.PlanAncodeEntry, error) { + collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) + + res := collection.FindOne(ctx, bson.D{{Key: "ancode", Value: ancode}}) + if res.Err() != nil { + if res.Err() == mongo.ErrNoDocuments { + return nil, nil + } + log.Error().Err(res.Err()).Str("collection", collectionNamePlan).Msg("MongoDB Find") + return nil, res.Err() + } + var entry model.PlanAncodeEntry + + err := res.Decode(&entry) + if err != nil { + log.Error().Err(err).Str("collection", collectionNamePlan). + Msg("Cannot decode to plan entry") + return nil, err + } + + return &entry, nil +} + +// Deprecated: rm me func (db *DB) PlanEntryForExamGroup(ctx context.Context, examGroupCode int) (*model.PlanEntry, error) { collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) @@ -235,6 +249,7 @@ EXAMLOOP: return examer, nil } +// Deprecated: rm me func (db *DB) PlanAncodeEntries(ctx context.Context) ([]*model.PlanAncodeEntry, error) { examGroups, err := db.ExamGroups(ctx) if err != nil { @@ -312,6 +327,12 @@ func (db *DB) UnlockExamGroup(ctx context.Context, examGroupCode int) (*model.Pl return db.PlanEntryForExamGroup(ctx, examGroupCode) } +func (db *DB) ExamIsLocked(ctx context.Context, ancode int) bool { + p, err := db.PlanEntry(ctx, ancode) + return err == nil && p != nil && p.Locked +} + +// Deprecated: rm me func (db *DB) ExamGroupIsLocked(ctx context.Context, examGroupCode int) bool { p, err := db.PlanEntryForExamGroup(ctx, examGroupCode) return err == nil && p != nil && p.Locked diff --git a/db/prepare_studentregs.go b/db/prepare_studentregs.go index 29a33da..30c68d4 100644 --- a/db/prepare_studentregs.go +++ b/db/prepare_studentregs.go @@ -8,6 +8,7 @@ import ( "github.com/rs/zerolog/log" ) +// Deprecated: rm me part of generated exams func (db *DB) SaveStudentRegsPerAncode(ctx context.Context, studentRegsPerAncode map[int]map[string][]*model.StudentReg, all bool) error { ancodes := make([]int, 0, len(studentRegsPerAncode)) for ancode := range studentRegsPerAncode { @@ -63,6 +64,7 @@ func (db *DB) SaveStudentRegsPerAncode(ctx context.Context, studentRegsPerAncode return nil } +// Deprecated: rm me func (db *DB) SaveStudentRegsPerStudent(ctx context.Context, studentRegsPerStudent map[string][]*model.StudentReg, all bool) error { studentRegsSlice := make([]interface{}, 0) @@ -73,6 +75,8 @@ func (db *DB) SaveStudentRegsPerStudent(ctx context.Context, studentRegsPerStude ancodes = append(ancodes, reg.AnCode) } + sort.Ints(ancodes) + studentRegsSlice = append(studentRegsSlice, &model.StudentRegsPerStudent{ Student: &model.Student{ Mtknr: mtknr, @@ -108,3 +112,23 @@ func (db *DB) SaveStudentRegsPerStudent(ctx context.Context, studentRegsPerStude return nil } + +func (db *DB) SaveStudentRegs(ctx context.Context, studentRegs []interface{}) error { + collection := db.Client.Database(db.databaseName).Collection(collectionStudentRegsPerStudentPlanned) + + err := collection.Drop(ctx) + if err != nil { + log.Error().Err(err).Str("collectionName", collectionStudentRegsPerStudentPlanned). + Msg("error while trying to drop the collection") + return err + } + + _, err = collection.InsertMany(ctx, studentRegs) + if err != nil { + log.Error().Err(err).Str("collectionName", collectionStudentRegsPerStudentPlanned). + Msg("error while trying to insert") + return err + } + + return nil +} diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 895fb9d..7210001 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -363,9 +363,9 @@ type ComplexityRoot struct { AdditionalExams func(childComplexity int) int AllProgramsInPlan func(childComplexity int) int AllSemesterNames func(childComplexity int) int - AllowedSlots func(childComplexity int, examGroupCode int) int + AllowedSlots func(childComplexity int, ancode int) int AncodesInPlan func(childComplexity int) int - AwkwardSlots func(childComplexity int, examGroupCode int) int + AwkwardSlots func(childComplexity int, ancode int) int ConflictingAncodes func(childComplexity int, ancode int) int ConnectedExam func(childComplexity int, ancode int) int ConnectedExams func(childComplexity int) int @@ -374,7 +374,6 @@ type ComplexityRoot struct { Exam func(childComplexity int, ancode int) int ExamGroup func(childComplexity int, examGroupCode int) int ExamGroups func(childComplexity int) int - ExamGroupsInSlot func(childComplexity int, day int, time int) int ExamGroupsWithoutSlot func(childComplexity int) int ExamWithRegs func(childComplexity int, ancode int) int ExamerInPlan func(childComplexity int) int @@ -659,17 +658,11 @@ type QueryResolver interface { ZpaExamsToPlanWithConstraints(ctx context.Context) ([]*model.ZPAExamWithConstraints, error) ExamGroups(ctx context.Context) ([]*model.ExamGroup, error) ExamGroup(ctx context.Context, examGroupCode int) (*model.ExamGroup, error) - Ntas(ctx context.Context) ([]*model.NTA, error) - NtasWithRegs(ctx context.Context) ([]*model.NTAWithRegs, error) NtasWithRegsByTeacher(ctx context.Context) ([]*model.NTAWithRegsByExamAndTeacher, error) Nta(ctx context.Context, mtknr string) (*model.NTAWithRegs, error) - AllowedSlots(ctx context.Context, examGroupCode int) ([]*model.Slot, error) - AwkwardSlots(ctx context.Context, examGroupCode int) ([]*model.Slot, error) - ExamGroupsInSlot(ctx context.Context, day int, time int) ([]*model.ExamGroup, error) ExamGroupsWithoutSlot(ctx context.Context) ([]*model.ExamGroup, error) PlannedExamsInSlot(ctx context.Context, day int, time int) ([]*model.PlannedExamWithNta, error) ExamsInPlan(ctx context.Context) ([]*model.ExamInPlan, error) - ExamsInSlot(ctx context.Context, day int, time int) ([]*model.ExamInPlan, error) ExamsInSlotWithRooms(ctx context.Context, day int, time int) ([]*model.ExamWithRegsAndRooms, error) Rooms(ctx context.Context) ([]*model.Room, error) RoomsWithConstraints(ctx context.Context, handicap bool, lab bool, placesWithSocket bool, exahm *bool) ([]*model.Room, error) @@ -689,10 +682,15 @@ type QueryResolver interface { ConflictingAncodes(ctx context.Context, ancode int) ([]*model.Conflict, error) Exam(ctx context.Context, ancode int) (*model.Exam, error) Exams(ctx context.Context) ([]*model.Exam, error) + Ntas(ctx context.Context) ([]*model.NTA, error) + NtasWithRegs(ctx context.Context) ([]*model.Student, error) AllProgramsInPlan(ctx context.Context) ([]string, error) AncodesInPlan(ctx context.Context) ([]int, error) ExamerInPlan(ctx context.Context) ([]*model.ExamerInPlan, error) + ExamsInSlot(ctx context.Context, day int, time int) ([]*model.GeneratedExam, error) ExamsWithoutSlot(ctx context.Context) ([]*model.GeneratedExam, error) + AllowedSlots(ctx context.Context, ancode int) ([]*model.Slot, error) + AwkwardSlots(ctx context.Context, ancode int) ([]*model.Slot, error) StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, error) StudentsByName(ctx context.Context, regex string) ([]*model.Student, error) Teacher(ctx context.Context, id int) (*model.Teacher, error) @@ -2214,7 +2212,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.AllowedSlots(childComplexity, args["examGroupCode"].(int)), true + return e.complexity.Query.AllowedSlots(childComplexity, args["ancode"].(int)), true case "Query.ancodesInPlan": if e.complexity.Query.AncodesInPlan == nil { @@ -2233,7 +2231,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.AwkwardSlots(childComplexity, args["examGroupCode"].(int)), true + return e.complexity.Query.AwkwardSlots(childComplexity, args["ancode"].(int)), true case "Query.conflictingAncodes": if e.complexity.Query.ConflictingAncodes == nil { @@ -2321,18 +2319,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.ExamGroups(childComplexity), true - case "Query.examGroupsInSlot": - if e.complexity.Query.ExamGroupsInSlot == nil { - break - } - - args, err := ec.field_Query_examGroupsInSlot_args(context.TODO(), rawArgs) - if err != nil { - return 0, false - } - - return e.complexity.Query.ExamGroupsInSlot(childComplexity, args["day"].(int), args["time"].(int)), true - case "Query.examGroupsWithoutSlot": if e.complexity.Query.ExamGroupsWithoutSlot == nil { break @@ -3904,7 +3890,12 @@ type RoomWithInvigilator { addRoomToExam(input: RoomForExamInput!): Boolean! } `, BuiltIn: false}, - {Name: "../nta.graphqls", Input: `type NTAExam { + {Name: "../nta.graphqls", Input: `extend type Query { + ntas: [NTA!] + ntasWithRegs: [Student!] +} + +type NTAExam { semester: String! ancode: String! module: String! @@ -3954,7 +3945,12 @@ type NTAWithRegsByExam { allProgramsInPlan: [String!] ancodesInPlan: [Int!] examerInPlan: [ExamerInPlan!] + + examsInSlot(day: Int!, time: Int!): [GeneratedExam!] examsWithoutSlot: [GeneratedExam!]! + + allowedSlots(ancode: Int!): [Slot!] + awkwardSlots(ancode: Int!): [Slot!]! # slots before or after a conflict } extend type Mutation { @@ -4114,21 +4110,16 @@ type ConflictsPerProgramAncode { examGroups: [ExamGroup!]! examGroup(examGroupCode: Int!): ExamGroup # NTAs - ntas: [NTA!] - ntasWithRegs: [NTAWithRegs!] ntasWithRegsByTeacher: [NTAWithRegsByExamAndTeacher!] nta(mtknr: String!): NTAWithRegs # Plan - allowedSlots(examGroupCode: Int!): [Slot!] - awkwardSlots(examGroupCode: Int!): [Slot!]! # slots before or after a conflict - examGroupsInSlot(day: Int!, time: Int!): [ExamGroup!] examGroupsWithoutSlot: [ExamGroup!] # PlannedExamsWithNTA plannedExamsInSlot(day: Int!, time: Int!): [PlannedExamWithNTA!] examsInPlan: [ExamInPlan!] - examsInSlot(day: Int!, time: Int!): [ExamInPlan!] + # examsInSlot(day: Int!, time: Int!): [ExamInPlan!] # Rooms examsInSlotWithRooms(day: Int!, time: Int!): [ExamWithRegsAndRooms!] rooms: [Room!]! @@ -4728,14 +4719,14 @@ func (ec *executionContext) field_Query_allowedSlots_args(ctx context.Context, r var err error args := map[string]interface{}{} var arg0 int - if tmp, ok := rawArgs["examGroupCode"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("examGroupCode")) + if tmp, ok := rawArgs["ancode"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("ancode")) arg0, err = ec.unmarshalNInt2int(ctx, tmp) if err != nil { return nil, err } } - args["examGroupCode"] = arg0 + args["ancode"] = arg0 return args, nil } @@ -4743,14 +4734,14 @@ func (ec *executionContext) field_Query_awkwardSlots_args(ctx context.Context, r var err error args := map[string]interface{}{} var arg0 int - if tmp, ok := rawArgs["examGroupCode"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("examGroupCode")) + if tmp, ok := rawArgs["ancode"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("ancode")) arg0, err = ec.unmarshalNInt2int(ctx, tmp) if err != nil { return nil, err } } - args["examGroupCode"] = arg0 + args["ancode"] = arg0 return args, nil } @@ -4838,30 +4829,6 @@ func (ec *executionContext) field_Query_examGroup_args(ctx context.Context, rawA return args, nil } -func (ec *executionContext) field_Query_examGroupsInSlot_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { - var err error - args := map[string]interface{}{} - var arg0 int - if tmp, ok := rawArgs["day"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("day")) - arg0, err = ec.unmarshalNInt2int(ctx, tmp) - if err != nil { - return nil, err - } - } - args["day"] = arg0 - var arg1 int - if tmp, ok := rawArgs["time"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("time")) - arg1, err = ec.unmarshalNInt2int(ctx, tmp) - if err != nil { - return nil, err - } - } - args["time"] = arg1 - return args, nil -} - func (ec *executionContext) field_Query_examWithRegs_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -15777,116 +15744,6 @@ func (ec *executionContext) fieldContext_Query_examGroup(ctx context.Context, fi return fc, nil } -func (ec *executionContext) _Query_ntas(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_ntas(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Ntas(rctx) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.([]*model.NTA) - fc.Result = res - return ec.marshalONTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAᚄ(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_ntas(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "name": - return ec.fieldContext_NTA_name(ctx, field) - case "mtknr": - return ec.fieldContext_NTA_mtknr(ctx, field) - case "compensation": - return ec.fieldContext_NTA_compensation(ctx, field) - case "deltaDurationPercent": - return ec.fieldContext_NTA_deltaDurationPercent(ctx, field) - case "needsRoomAlone": - return ec.fieldContext_NTA_needsRoomAlone(ctx, field) - case "program": - return ec.fieldContext_NTA_program(ctx, field) - case "from": - return ec.fieldContext_NTA_from(ctx, field) - case "until": - return ec.fieldContext_NTA_until(ctx, field) - case "lastSemester": - return ec.fieldContext_NTA_lastSemester(ctx, field) - case "exams": - return ec.fieldContext_NTA_exams(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type NTA", field.Name) - }, - } - return fc, nil -} - -func (ec *executionContext) _Query_ntasWithRegs(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_ntasWithRegs(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().NtasWithRegs(rctx) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.([]*model.NTAWithRegs) - fc.Result = res - return ec.marshalONTAWithRegs2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsᚄ(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_ntasWithRegs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "nta": - return ec.fieldContext_NTAWithRegs_nta(ctx, field) - case "regs": - return ec.fieldContext_NTAWithRegs_regs(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type NTAWithRegs", field.Name) - }, - } - return fc, nil -} - func (ec *executionContext) _Query_ntasWithRegsByTeacher(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_ntasWithRegsByTeacher(ctx, field) if err != nil { @@ -15992,189 +15849,6 @@ func (ec *executionContext) fieldContext_Query_nta(ctx context.Context, field gr return fc, nil } -func (ec *executionContext) _Query_allowedSlots(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_allowedSlots(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().AllowedSlots(rctx, fc.Args["examGroupCode"].(int)) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.([]*model.Slot) - fc.Result = res - return ec.marshalOSlot2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSlotᚄ(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_allowedSlots(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "dayNumber": - return ec.fieldContext_Slot_dayNumber(ctx, field) - case "slotNumber": - return ec.fieldContext_Slot_slotNumber(ctx, field) - case "starttime": - return ec.fieldContext_Slot_starttime(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type Slot", field.Name) - }, - } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_allowedSlots_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } - return fc, nil -} - -func (ec *executionContext) _Query_awkwardSlots(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_awkwardSlots(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().AwkwardSlots(rctx, fc.Args["examGroupCode"].(int)) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.([]*model.Slot) - fc.Result = res - return ec.marshalNSlot2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSlotᚄ(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_awkwardSlots(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "dayNumber": - return ec.fieldContext_Slot_dayNumber(ctx, field) - case "slotNumber": - return ec.fieldContext_Slot_slotNumber(ctx, field) - case "starttime": - return ec.fieldContext_Slot_starttime(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type Slot", field.Name) - }, - } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_awkwardSlots_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } - return fc, nil -} - -func (ec *executionContext) _Query_examGroupsInSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_examGroupsInSlot(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ExamGroupsInSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.([]*model.ExamGroup) - fc.Result = res - return ec.marshalOExamGroup2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupᚄ(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_examGroupsInSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "examGroupCode": - return ec.fieldContext_ExamGroup_examGroupCode(ctx, field) - case "exams": - return ec.fieldContext_ExamGroup_exams(ctx, field) - case "examGroupInfo": - return ec.fieldContext_ExamGroup_examGroupInfo(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type ExamGroup", field.Name) - }, - } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_examGroupsInSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } - return fc, nil -} - func (ec *executionContext) _Query_examGroupsWithoutSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_examGroupsWithoutSlot(ctx, field) if err != nil { @@ -16335,68 +16009,6 @@ func (ec *executionContext) fieldContext_Query_examsInPlan(ctx context.Context, return fc, nil } -func (ec *executionContext) _Query_examsInSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_examsInSlot(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().ExamsInSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.([]*model.ExamInPlan) - fc.Result = res - return ec.marshalOExamInPlan2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamInPlanᚄ(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_examsInSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "exam": - return ec.fieldContext_ExamInPlan_exam(ctx, field) - case "constraints": - return ec.fieldContext_ExamInPlan_constraints(ctx, field) - case "nta": - return ec.fieldContext_ExamInPlan_nta(ctx, field) - case "slot": - return ec.fieldContext_ExamInPlan_slot(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type ExamInPlan", field.Name) - }, - } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_examsInSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } - return fc, nil -} - func (ec *executionContext) _Query_examsInSlotWithRooms(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_examsInSlotWithRooms(ctx, field) if err != nil { @@ -17534,6 +17146,124 @@ func (ec *executionContext) fieldContext_Query_exams(ctx context.Context, field return fc, nil } +func (ec *executionContext) _Query_ntas(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_ntas(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Ntas(rctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.NTA) + fc.Result = res + return ec.marshalONTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_ntas(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext_NTA_name(ctx, field) + case "mtknr": + return ec.fieldContext_NTA_mtknr(ctx, field) + case "compensation": + return ec.fieldContext_NTA_compensation(ctx, field) + case "deltaDurationPercent": + return ec.fieldContext_NTA_deltaDurationPercent(ctx, field) + case "needsRoomAlone": + return ec.fieldContext_NTA_needsRoomAlone(ctx, field) + case "program": + return ec.fieldContext_NTA_program(ctx, field) + case "from": + return ec.fieldContext_NTA_from(ctx, field) + case "until": + return ec.fieldContext_NTA_until(ctx, field) + case "lastSemester": + return ec.fieldContext_NTA_lastSemester(ctx, field) + case "exams": + return ec.fieldContext_NTA_exams(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type NTA", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Query_ntasWithRegs(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_ntasWithRegs(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().NtasWithRegs(rctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.Student) + fc.Result = res + return ec.marshalOStudent2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_ntasWithRegs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "mtknr": + return ec.fieldContext_Student_mtknr(ctx, field) + case "program": + return ec.fieldContext_Student_program(ctx, field) + case "group": + return ec.fieldContext_Student_group(ctx, field) + case "name": + return ec.fieldContext_Student_name(ctx, field) + case "regs": + return ec.fieldContext_Student_regs(ctx, field) + case "nta": + return ec.fieldContext_Student_nta(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Student", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _Query_allProgramsInPlan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_allProgramsInPlan(ctx, field) if err != nil { @@ -17663,6 +17393,72 @@ func (ec *executionContext) fieldContext_Query_examerInPlan(ctx context.Context, return fc, nil } +func (ec *executionContext) _Query_examsInSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_examsInSlot(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().ExamsInSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.GeneratedExam) + fc.Result = res + return ec.marshalOGeneratedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExamᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_examsInSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "ancode": + return ec.fieldContext_GeneratedExam_ancode(ctx, field) + case "zpaExam": + return ec.fieldContext_GeneratedExam_zpaExam(ctx, field) + case "primussExams": + return ec.fieldContext_GeneratedExam_primussExams(ctx, field) + case "constraints": + return ec.fieldContext_GeneratedExam_constraints(ctx, field) + case "conflicts": + return ec.fieldContext_GeneratedExam_conflicts(ctx, field) + case "studentRegsCount": + return ec.fieldContext_GeneratedExam_studentRegsCount(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type GeneratedExam", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_examsInSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Query_examsWithoutSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_examsWithoutSlot(ctx, field) if err != nil { @@ -17721,6 +17517,129 @@ func (ec *executionContext) fieldContext_Query_examsWithoutSlot(ctx context.Cont return fc, nil } +func (ec *executionContext) _Query_allowedSlots(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_allowedSlots(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().AllowedSlots(rctx, fc.Args["ancode"].(int)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.Slot) + fc.Result = res + return ec.marshalOSlot2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSlotᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_allowedSlots(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "dayNumber": + return ec.fieldContext_Slot_dayNumber(ctx, field) + case "slotNumber": + return ec.fieldContext_Slot_slotNumber(ctx, field) + case "starttime": + return ec.fieldContext_Slot_starttime(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Slot", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_allowedSlots_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_awkwardSlots(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_awkwardSlots(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().AwkwardSlots(rctx, fc.Args["ancode"].(int)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.Slot) + fc.Result = res + return ec.marshalNSlot2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSlotᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_awkwardSlots(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "dayNumber": + return ec.fieldContext_Slot_dayNumber(ctx, field) + case "slotNumber": + return ec.fieldContext_Slot_slotNumber(ctx, field) + case "starttime": + return ec.fieldContext_Slot_starttime(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Slot", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_awkwardSlots_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Query_studentByMtknr(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_studentByMtknr(ctx, field) if err != nil { @@ -28672,26 +28591,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "ntas": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_ntas(ctx, field) - return res - } - - rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, - func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - } - - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "ntasWithRegs": + case "ntasWithRegsByTeacher": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -28700,7 +28600,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_ntasWithRegs(ctx, field) + res = ec._Query_ntasWithRegsByTeacher(ctx, field) return res } @@ -28710,7 +28610,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "ntasWithRegsByTeacher": + case "nta": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -28719,7 +28619,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_ntasWithRegsByTeacher(ctx, field) + res = ec._Query_nta(ctx, field) return res } @@ -28729,7 +28629,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "nta": + case "examGroupsWithoutSlot": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -28738,7 +28638,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_nta(ctx, field) + res = ec._Query_examGroupsWithoutSlot(ctx, field) return res } @@ -28748,7 +28648,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "allowedSlots": + case "plannedExamsInSlot": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -28757,7 +28657,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_allowedSlots(ctx, field) + res = ec._Query_plannedExamsInSlot(ctx, field) return res } @@ -28767,7 +28667,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "awkwardSlots": + case "examsInPlan": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -28776,10 +28676,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_awkwardSlots(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } + res = ec._Query_examsInPlan(ctx, field) return res } @@ -28789,7 +28686,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "examGroupsInSlot": + case "examsInSlotWithRooms": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -28798,7 +28695,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_examGroupsInSlot(ctx, field) + res = ec._Query_examsInSlotWithRooms(ctx, field) return res } @@ -28808,7 +28705,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "examGroupsWithoutSlot": + case "rooms": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -28817,7 +28714,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_examGroupsWithoutSlot(ctx, field) + res = ec._Query_rooms(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -28827,7 +28727,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "plannedExamsInSlot": + case "roomsWithConstraints": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -28836,7 +28736,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_plannedExamsInSlot(ctx, field) + res = ec._Query_roomsWithConstraints(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -28846,7 +28749,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "examsInPlan": + case "roomsForSlot": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -28855,7 +28758,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_examsInPlan(ctx, field) + res = ec._Query_roomsForSlot(ctx, field) return res } @@ -28865,7 +28768,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "examsInSlot": + case "plannedRoomNames": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -28874,7 +28777,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_examsInSlot(ctx, field) + res = ec._Query_plannedRoomNames(ctx, field) return res } @@ -28884,7 +28787,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "examsInSlotWithRooms": + case "plannedRoomNamesInSlot": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -28893,7 +28796,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_examsInSlotWithRooms(ctx, field) + res = ec._Query_plannedRoomNamesInSlot(ctx, field) return res } @@ -28903,7 +28806,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "rooms": + case "invigilatorsWithReq": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -28912,7 +28815,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_rooms(ctx, field) + res = ec._Query_invigilatorsWithReq(ctx, field) if res == graphql.Null { atomic.AddUint32(&fs.Invalids, 1) } @@ -28925,7 +28828,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "roomsWithConstraints": + case "invigilatorTodos": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -28934,10 +28837,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_roomsWithConstraints(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } + res = ec._Query_invigilatorTodos(ctx, field) return res } @@ -28947,7 +28847,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "roomsForSlot": + case "roomsWithInvigilationsForSlot": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -28956,7 +28856,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_roomsForSlot(ctx, field) + res = ec._Query_roomsWithInvigilationsForSlot(ctx, field) return res } @@ -28966,7 +28866,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "plannedRoomNames": + case "invigilatorsForDay": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -28975,7 +28875,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_plannedRoomNames(ctx, field) + res = ec._Query_invigilatorsForDay(ctx, field) return res } @@ -28985,7 +28885,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "plannedRoomNamesInSlot": + case "dayOkForInvigilator": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -28994,7 +28894,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_plannedRoomNamesInSlot(ctx, field) + res = ec._Query_dayOkForInvigilator(ctx, field) return res } @@ -29004,7 +28904,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "invigilatorsWithReq": + case "connectedExam": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -29013,10 +28913,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_invigilatorsWithReq(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } + res = ec._Query_connectedExam(ctx, field) return res } @@ -29026,7 +28923,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "invigilatorTodos": + case "connectedExams": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -29035,7 +28932,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_invigilatorTodos(ctx, field) + res = ec._Query_connectedExams(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -29045,7 +28945,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "roomsWithInvigilationsForSlot": + case "externalExams": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -29054,7 +28954,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_roomsWithInvigilationsForSlot(ctx, field) + res = ec._Query_externalExams(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -29064,7 +28967,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "invigilatorsForDay": + case "generatedExams": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -29073,7 +28976,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_invigilatorsForDay(ctx, field) + res = ec._Query_generatedExams(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -29083,7 +28989,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "dayOkForInvigilator": + case "generatedExam": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -29092,7 +28998,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_dayOkForInvigilator(ctx, field) + res = ec._Query_generatedExam(ctx, field) return res } @@ -29102,7 +29008,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "connectedExam": + case "conflictingAncodes": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -29111,7 +29017,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_connectedExam(ctx, field) + res = ec._Query_conflictingAncodes(ctx, field) return res } @@ -29121,7 +29027,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "connectedExams": + case "exam": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -29130,10 +29036,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_connectedExams(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } + res = ec._Query_exam(ctx, field) return res } @@ -29143,7 +29046,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "externalExams": + case "exams": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -29152,7 +29055,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_externalExams(ctx, field) + res = ec._Query_exams(ctx, field) if res == graphql.Null { atomic.AddUint32(&fs.Invalids, 1) } @@ -29165,7 +29068,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "generatedExams": + case "ntas": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -29174,10 +29077,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_generatedExams(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } + res = ec._Query_ntas(ctx, field) return res } @@ -29187,7 +29087,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "generatedExam": + case "ntasWithRegs": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -29196,7 +29096,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_generatedExam(ctx, field) + res = ec._Query_ntasWithRegs(ctx, field) return res } @@ -29206,7 +29106,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "conflictingAncodes": + case "allProgramsInPlan": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -29215,7 +29115,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_conflictingAncodes(ctx, field) + res = ec._Query_allProgramsInPlan(ctx, field) return res } @@ -29225,7 +29125,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "exam": + case "ancodesInPlan": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -29234,7 +29134,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_exam(ctx, field) + res = ec._Query_ancodesInPlan(ctx, field) return res } @@ -29244,7 +29144,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "exams": + case "examerInPlan": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -29253,10 +29153,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_exams(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } + res = ec._Query_examerInPlan(ctx, field) return res } @@ -29266,7 +29163,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "allProgramsInPlan": + case "examsInSlot": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -29275,7 +29172,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_allProgramsInPlan(ctx, field) + res = ec._Query_examsInSlot(ctx, field) return res } @@ -29285,7 +29182,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "ancodesInPlan": + case "examsWithoutSlot": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -29294,7 +29191,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_ancodesInPlan(ctx, field) + res = ec._Query_examsWithoutSlot(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -29304,7 +29204,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "examerInPlan": + case "allowedSlots": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -29313,7 +29213,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_examerInPlan(ctx, field) + res = ec._Query_allowedSlots(ctx, field) return res } @@ -29323,7 +29223,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "examsWithoutSlot": + case "awkwardSlots": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -29332,7 +29232,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_examsWithoutSlot(ctx, field) + res = ec._Query_awkwardSlots(ctx, field) if res == graphql.Null { atomic.AddUint32(&fs.Invalids, 1) } @@ -34567,6 +34467,53 @@ func (ec *executionContext) marshalOExternalExam2ᚖgithubᚗcomᚋobcodeᚋplex return ec._ExternalExam(ctx, sel, v) } +func (ec *executionContext) marshalOGeneratedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.GeneratedExam) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNGeneratedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExam(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + func (ec *executionContext) marshalOGeneratedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExam(ctx context.Context, sel ast.SelectionSet, v *model.GeneratedExam) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/graph/nta.graphqls b/graph/nta.graphqls index b340c27..9958caa 100644 --- a/graph/nta.graphqls +++ b/graph/nta.graphqls @@ -1,3 +1,8 @@ +extend type Query { + ntas: [NTA!] + ntasWithRegs: [Student!] +} + type NTAExam { semester: String! ancode: String! diff --git a/graph/nta.resolvers.go b/graph/nta.resolvers.go new file mode 100644 index 0000000..8228196 --- /dev/null +++ b/graph/nta.resolvers.go @@ -0,0 +1,21 @@ +package graph + +// This file will be automatically regenerated based on the schema, any resolver implementations +// will be copied through when generating and any unknown code will be moved to the end. +// Code generated by github.com/99designs/gqlgen version v0.17.34 + +import ( + "context" + + "github.com/obcode/plexams.go/graph/model" +) + +// Ntas is the resolver for the ntas field. +func (r *queryResolver) Ntas(ctx context.Context) ([]*model.NTA, error) { + return r.plexams.Ntas(ctx) +} + +// NtasWithRegs is the resolver for the ntasWithRegs field. +func (r *queryResolver) NtasWithRegs(ctx context.Context) ([]*model.Student, error) { + return r.plexams.NtasWithRegs(ctx) +} diff --git a/graph/plan.graphqls b/graph/plan.graphqls index 9f4d85c..6c8fab8 100644 --- a/graph/plan.graphqls +++ b/graph/plan.graphqls @@ -2,7 +2,12 @@ extend type Query { allProgramsInPlan: [String!] ancodesInPlan: [Int!] examerInPlan: [ExamerInPlan!] + + examsInSlot(day: Int!, time: Int!): [GeneratedExam!] examsWithoutSlot: [GeneratedExam!]! + + allowedSlots(ancode: Int!): [Slot!] + awkwardSlots(ancode: Int!): [Slot!]! # slots before or after a conflict } extend type Mutation { diff --git a/graph/plan.resolvers.go b/graph/plan.resolvers.go index aa5770a..ff54887 100644 --- a/graph/plan.resolvers.go +++ b/graph/plan.resolvers.go @@ -36,7 +36,22 @@ func (r *queryResolver) ExamerInPlan(ctx context.Context) ([]*model.ExamerInPlan return r.plexams.ExamerInPlan(ctx) } +// ExamGroupsInSlot is the resolver for the examGroupsInSlot field. +func (r *queryResolver) ExamsInSlot(ctx context.Context, day int, time int) ([]*model.GeneratedExam, error) { + return r.plexams.GetExamsInSlot(ctx, day, time) +} + // ExamsWithoutSlot is the resolver for the examsWithoutSlot field. func (r *queryResolver) ExamsWithoutSlot(ctx context.Context) ([]*model.GeneratedExam, error) { return r.plexams.ExamsWithoutSlot(ctx) } + +// AllowedSlots is the resolver for the allowedSlots field. +func (r *queryResolver) AllowedSlots(ctx context.Context, ancode int) ([]*model.Slot, error) { + return r.plexams.AllowedSlots(ctx, ancode) +} + +// AwkwardSlots is the resolver for the awkwardSlots field. +func (r *queryResolver) AwkwardSlots(ctx context.Context, ancode int) ([]*model.Slot, error) { + return r.plexams.AwkwardSlots(ctx, ancode) +} diff --git a/graph/query.graphqls b/graph/query.graphqls index c2789ab..1ae0fcf 100644 --- a/graph/query.graphqls +++ b/graph/query.graphqls @@ -22,21 +22,16 @@ type Query { examGroups: [ExamGroup!]! examGroup(examGroupCode: Int!): ExamGroup # NTAs - ntas: [NTA!] - ntasWithRegs: [NTAWithRegs!] ntasWithRegsByTeacher: [NTAWithRegsByExamAndTeacher!] nta(mtknr: String!): NTAWithRegs # Plan - allowedSlots(examGroupCode: Int!): [Slot!] - awkwardSlots(examGroupCode: Int!): [Slot!]! # slots before or after a conflict - examGroupsInSlot(day: Int!, time: Int!): [ExamGroup!] examGroupsWithoutSlot: [ExamGroup!] # PlannedExamsWithNTA plannedExamsInSlot(day: Int!, time: Int!): [PlannedExamWithNTA!] examsInPlan: [ExamInPlan!] - examsInSlot(day: Int!, time: Int!): [ExamInPlan!] + # examsInSlot(day: Int!, time: Int!): [ExamInPlan!] # Rooms examsInSlotWithRooms(day: Int!, time: Int!): [ExamWithRegsAndRooms!] rooms: [Room!]! diff --git a/graph/query.resolvers.go b/graph/query.resolvers.go index 03cfc16..20ea136 100644 --- a/graph/query.resolvers.go +++ b/graph/query.resolvers.go @@ -92,16 +92,6 @@ func (r *queryResolver) ExamGroup(ctx context.Context, examGroupCode int) (*mode return r.plexams.ExamGroup(ctx, examGroupCode) } -// Ntas is the resolver for the ntas field. -func (r *queryResolver) Ntas(ctx context.Context) ([]*model.NTA, error) { - return r.plexams.Ntas(ctx) -} - -// NtasWithRegs is the resolver for the ntasWithRegs field. -func (r *queryResolver) NtasWithRegs(ctx context.Context) ([]*model.NTAWithRegs, error) { - return r.plexams.NtasWithRegs(ctx) -} - // NtasWithRegsByTeacher is the resolver for the ntasWithRegsByTeacher field. func (r *queryResolver) NtasWithRegsByTeacher(ctx context.Context) ([]*model.NTAWithRegsByExamAndTeacher, error) { return r.plexams.NtasWithRegsByTeacher(ctx) @@ -112,21 +102,6 @@ func (r *queryResolver) Nta(ctx context.Context, mtknr string) (*model.NTAWithRe return r.plexams.Nta(ctx, mtknr) } -// AllowedSlots is the resolver for the allowedSlots field. -func (r *queryResolver) AllowedSlots(ctx context.Context, examGroupCode int) ([]*model.Slot, error) { - return r.plexams.AllowedSlots(ctx, examGroupCode) -} - -// AwkwardSlots is the resolver for the awkwardSlots field. -func (r *queryResolver) AwkwardSlots(ctx context.Context, examGroupCode int) ([]*model.Slot, error) { - return r.plexams.AwkwardSlots(ctx, examGroupCode) -} - -// ExamGroupsInSlot is the resolver for the examGroupsInSlot field. -func (r *queryResolver) ExamGroupsInSlot(ctx context.Context, day int, time int) ([]*model.ExamGroup, error) { - return r.plexams.ExamGroupsInSlot(ctx, day, time) -} - // ExamGroupsWithoutSlot is the resolver for the examGroupsWithoutSlot field. func (r *queryResolver) ExamGroupsWithoutSlot(ctx context.Context) ([]*model.ExamGroup, error) { return r.plexams.ExamGroupsWithoutSlot(ctx) @@ -134,7 +109,7 @@ func (r *queryResolver) ExamGroupsWithoutSlot(ctx context.Context) ([]*model.Exa // PlannedExamsInSlot is the resolver for the plannedExamsInSlot field. func (r *queryResolver) PlannedExamsInSlot(ctx context.Context, day int, time int) ([]*model.PlannedExamWithNta, error) { - return r.plexams.PlannedExamsInSlot(ctx, day, time) + return nil, nil } // ExamsInPlan is the resolver for the examsInPlan field. @@ -142,11 +117,6 @@ func (r *queryResolver) ExamsInPlan(ctx context.Context) ([]*model.ExamInPlan, e return r.plexams.ExamsInPlan(ctx) } -// ExamsInSlot is the resolver for the examsInSlot field. -func (r *queryResolver) ExamsInSlot(ctx context.Context, day int, time int) ([]*model.ExamInPlan, error) { - return r.plexams.ExamsInSlot(ctx, day, time) -} - // ExamsInSlotWithRooms is the resolver for the examsInSlotWithRooms field. func (r *queryResolver) ExamsInSlotWithRooms(ctx context.Context, day int, time int) ([]*model.ExamWithRegsAndRooms, error) { return r.plexams.ExamsInSlotWithRooms(ctx, day, time) diff --git a/plexams/generatedExams.go b/plexams/generatedExams.go index 98a396c..322ebb8 100644 --- a/plexams/generatedExams.go +++ b/plexams/generatedExams.go @@ -99,6 +99,9 @@ func (p *Plexams) PrepareGeneratedExams() error { conflictsMap := make(map[int]*model.ZPAConflict) for _, enhanced := range enhancedPrimussExams { for _, primussConflict := range enhanced.Conflicts { + if primussConflict.AnCode == enhanced.Exam.AnCode { + continue + } zpaAncode, ok := ancodesMap[PrimussAncode{ Program: enhanced.Exam.Program, Ancode: primussConflict.AnCode, diff --git a/plexams/nta.go b/plexams/nta.go index a05cedf..ac4589b 100644 --- a/plexams/nta.go +++ b/plexams/nta.go @@ -2,7 +2,6 @@ package plexams import ( "context" - "sort" "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" @@ -16,7 +15,7 @@ func (p *Plexams) Ntas(ctx context.Context) ([]*model.NTA, error) { return p.dbClient.Ntas(ctx) } -func (p *Plexams) NtasWithRegs(ctx context.Context) ([]*model.NTAWithRegs, error) { +func (p *Plexams) NtasWithRegs(ctx context.Context) ([]*model.Student, error) { return p.dbClient.NtasWithRegs(ctx) } @@ -63,83 +62,84 @@ func (p *Plexams) PrepareNta() error { return nil } +// Deprecated: rm me func (p *Plexams) NtasWithRegsByTeacher(ctx context.Context) ([]*model.NTAWithRegsByExamAndTeacher, error) { - ntas, err := p.NtasWithRegs(ctx) - if err != nil { - log.Error().Err(err).Msg("cannot get NTAs with regs") - return nil, err - } - - ancodesMap := make(map[int][]*model.NTAWithRegs) - for _, nta := range ntas { - for _, ancode := range nta.Regs.Ancodes { - entry, ok := ancodesMap[ancode] - if ok { - entry = append(entry, nta) - } else { - entry = []*model.NTAWithRegs{nta} - } - ancodesMap[ancode] = entry - } - } - - mainExamerMap := make(map[int][]*model.ZPAExam) - for ancode := range ancodesMap { - exam, err := p.GetZpaExamByAncode(ctx, ancode) - if err != nil { - log.Error().Err(err).Int("ancode", ancode).Msg("cannot get exam with ancode") - return nil, err - } - - exams, ok := mainExamerMap[exam.MainExamerID] - if ok { - exams = append(exams, exam) - } else { - exams = []*model.ZPAExam{exam} - } - mainExamerMap[exam.MainExamerID] = exams - } - - // sort teacher - teacherMap := make(map[string]*model.Teacher) - teacherNames := make([]string, 0, len(mainExamerMap)) - for mainExamerID := range mainExamerMap { - teacher, err := p.GetTeacher(ctx, mainExamerID) - if err != nil { - log.Error().Err(err).Int("mainExamerID", mainExamerID).Msg("cannot get teacher with mainExamerID") - return nil, err - } - teacherMap[teacher.Shortname] = teacher - teacherNames = append(teacherNames, teacher.Shortname) - } - sort.Strings(teacherNames) - - result := make([]*model.NTAWithRegsByExamAndTeacher, 0, len(mainExamerMap)) - for _, teacherName := range teacherNames { - teacher := teacherMap[teacherName] - exams := mainExamerMap[teacher.ID] - examsResult := make([]*model.NTAWithRegsByExam, 0) - for _, exam := range exams { - constraint, err := p.ConstraintForAncode(ctx, exam.AnCode) - if err != nil { - log.Error().Err(err).Int("ancode", exam.AnCode).Msg("cannot get constraint for ancode") - } - if constraint != nil && constraint.NotPlannedByMe { - break - } - examsResult = append(examsResult, &model.NTAWithRegsByExam{ - Exam: exam, - Ntas: ancodesMap[exam.AnCode], - }) - } - - if len(examsResult) > 0 { - result = append(result, &model.NTAWithRegsByExamAndTeacher{ - Teacher: teacher, - Exams: examsResult, - }) - } - } - - return result, err + // ntas, err := p.NtasWithRegs(ctx) + // if err != nil { + // log.Error().Err(err).Msg("cannot get NTAs with regs") + // return nil, err + // } + + // ancodesMap := make(map[int][]*model.NTAWithRegs) + // for _, nta := range ntas { + // for _, ancode := range nta.Regs.Ancodes { + // entry, ok := ancodesMap[ancode] + // if ok { + // entry = append(entry, nta) + // } else { + // entry = []*model.NTAWithRegs{nta} + // } + // ancodesMap[ancode] = entry + // } + // } + + // mainExamerMap := make(map[int][]*model.ZPAExam) + // for ancode := range ancodesMap { + // exam, err := p.GetZpaExamByAncode(ctx, ancode) + // if err != nil { + // log.Error().Err(err).Int("ancode", ancode).Msg("cannot get exam with ancode") + // return nil, err + // } + + // exams, ok := mainExamerMap[exam.MainExamerID] + // if ok { + // exams = append(exams, exam) + // } else { + // exams = []*model.ZPAExam{exam} + // } + // mainExamerMap[exam.MainExamerID] = exams + // } + + // // sort teacher + // teacherMap := make(map[string]*model.Teacher) + // teacherNames := make([]string, 0, len(mainExamerMap)) + // for mainExamerID := range mainExamerMap { + // teacher, err := p.GetTeacher(ctx, mainExamerID) + // if err != nil { + // log.Error().Err(err).Int("mainExamerID", mainExamerID).Msg("cannot get teacher with mainExamerID") + // return nil, err + // } + // teacherMap[teacher.Shortname] = teacher + // teacherNames = append(teacherNames, teacher.Shortname) + // } + // sort.Strings(teacherNames) + + // result := make([]*model.NTAWithRegsByExamAndTeacher, 0, len(mainExamerMap)) + // for _, teacherName := range teacherNames { + // teacher := teacherMap[teacherName] + // exams := mainExamerMap[teacher.ID] + // examsResult := make([]*model.NTAWithRegsByExam, 0) + // for _, exam := range exams { + // constraint, err := p.ConstraintForAncode(ctx, exam.AnCode) + // if err != nil { + // log.Error().Err(err).Int("ancode", exam.AnCode).Msg("cannot get constraint for ancode") + // } + // if constraint != nil && constraint.NotPlannedByMe { + // break + // } + // examsResult = append(examsResult, &model.NTAWithRegsByExam{ + // Exam: exam, + // Ntas: ancodesMap[exam.AnCode], + // }) + // } + + // if len(examsResult) > 0 { + // result = append(result, &model.NTAWithRegsByExamAndTeacher{ + // Teacher: teacher, + // Exams: examsResult, + // }) + // } + // } + + return nil, nil } diff --git a/plexams/plan.go b/plexams/plan.go index 1e72ab6..c74ab1c 100644 --- a/plexams/plan.go +++ b/plexams/plan.go @@ -64,18 +64,23 @@ func (p *Plexams) AddExamToSlot(ctx context.Context, ancode int, dayNumber int, return p.dbClient.AddExamToSlot(ctx, dayNumber, timeNumber, ancode) } +// FIXME: Allowed Slots func (p *Plexams) AllowedSlots(ctx context.Context, ancode int) ([]*model.Slot, error) { - return nil, nil - // if p.dbClient.ExamIsLocked(ctx, ancode) { - // return []*model.Slot{}, nil - // } - // exam, err := p.GeneratedExam(ctx, ancode) - // if err != nil { - // log.Error().Err(err).Int("ancode", ancode).Msg("exam does not exist") - // } + if p.dbClient.ExamIsLocked(ctx, ancode) { + return []*model.Slot{}, nil + } + // exam, err := p.GeneratedExam(ctx, ancode) + // if err != nil { + // log.Error().Err(err).Int("ancode", ancode).Msg("exam does not exist") + // } + + // // TODO: calculate possible slots from constraints + // allSlots := p.semesterConfig.Slots - // allowedSlots := make([]*model.Slot, 0) + // TODO: recalculate from conflicts + + // allowedSlots := make([]*model.Slot, 0) // OUTER: // for _, slot := range exam.Constraints.PossibleSlots { // // get ExamGroups for slot and check Conflicts @@ -101,6 +106,8 @@ func (p *Plexams) AllowedSlots(ctx context.Context, ancode int) ([]*model.Slot, // } // return allowedSlots, nil + return nil, nil + } func (p *Plexams) ExamsWithoutSlot(ctx context.Context) ([]*model.GeneratedExam, error) { @@ -156,3 +163,11 @@ OUTER: func (p *Plexams) AncodesInPlan(ctx context.Context) ([]int, error) { return p.dbClient.AncodesInPlan(ctx) } + +func (p *Plexams) ExamsInSlot(ctx context.Context, day int, time int) ([]*model.ExamInPlan, error) { + return p.dbClient.ExamsInSlot(ctx, day, time) +} + +func (p *Plexams) GetExamsInSlot(ctx context.Context, day int, time int) ([]*model.GeneratedExam, error) { + return p.dbClient.GetExamsInSlot(ctx, day, time) +} diff --git a/plexams/plan_examgroups.go b/plexams/plan_examgroups.go index 32b2c61..03c9a2f 100644 --- a/plexams/plan_examgroups.go +++ b/plexams/plan_examgroups.go @@ -85,10 +85,6 @@ func (p *Plexams) RmExamGroupFromSlot(ctx context.Context, examGroupCode int) (b return p.dbClient.RmExamGroupFromSlot(ctx, examGroupCode) } -func (p *Plexams) ExamGroupsInSlot(ctx context.Context, day int, time int) ([]*model.ExamGroup, error) { - return p.dbClient.ExamGroupsInSlot(ctx, day, time) -} - // func (p *Plexams) AllowedSlots(ctx context.Context, examGroupCode int) ([]*model.Slot, error) { // if p.dbClient.ExamGroupIsLocked(ctx, examGroupCode) { // return []*model.Slot{}, nil @@ -244,44 +240,44 @@ func (p *Plexams) SlotForExamGroup(ctx context.Context, examGroupCode int) (*mod return nil, fmt.Errorf("slot for exam group #%d not found", examGroupCode) } -func (p *Plexams) PlannedExamsInSlot(ctx context.Context, day int, time int) ([]*model.PlannedExamWithNta, error) { - examGroups, err := p.ExamGroupsInSlot(ctx, day, time) - if err != nil { - log.Error().Err(err).Int("day number", day).Int("slot number", time).Msg("cannot get exam group for slot") - } - if examGroups == nil { - return nil, nil - } +// func (p *Plexams) PlannedExamsInSlot(ctx context.Context, day int, time int) ([]*model.PlannedExamWithNta, error) { +// examGroups, err := p.ExamGroupsInSlot(ctx, day, time) +// if err != nil { +// log.Error().Err(err).Int("day number", day).Int("slot number", time).Msg("cannot get exam group for slot") +// } +// if examGroups == nil { +// return nil, nil +// } - ntasWithRegsByTeacher, err := p.NtasWithRegsByTeacher(ctx) - if err != nil { - log.Error().Err(err).Msg("cannot get ntas with regs") - return nil, err - } +// ntasWithRegsByTeacher, err := p.NtasWithRegsByTeacher(ctx) +// if err != nil { +// log.Error().Err(err).Msg("cannot get ntas with regs") +// return nil, err +// } - ancodeNTAMap := make(map[int][]*model.NTAWithRegs) - for _, ntaWithRegByTeacher := range ntasWithRegsByTeacher { - for _, ntaWithRegsByExam := range ntaWithRegByTeacher.Exams { - ancodeNTAMap[ntaWithRegsByExam.Exam.AnCode] = ntaWithRegsByExam.Ntas - } - } +// ancodeNTAMap := make(map[int][]*model.NTAWithRegs) +// for _, ntaWithRegByTeacher := range ntasWithRegsByTeacher { +// for _, ntaWithRegsByExam := range ntaWithRegByTeacher.Exams { +// ancodeNTAMap[ntaWithRegsByExam.Exam.AnCode] = ntaWithRegsByExam.Ntas +// } +// } - plannedExams := make([]*model.PlannedExamWithNta, 0) - for _, examGroup := range examGroups { - for _, exam := range examGroup.Exams { - ntas, ok := ancodeNTAMap[exam.Exam.Ancode] - if !ok { - ntas = nil - } - plannedExams = append(plannedExams, &model.PlannedExamWithNta{ - Exam: exam.Exam, - Constraints: exam.Constraints, - Nta: ntas, - }) - } - } - return plannedExams, nil -} +// plannedExams := make([]*model.PlannedExamWithNta, 0) +// for _, examGroup := range examGroups { +// for _, exam := range examGroup.Exams { +// ntas, ok := ancodeNTAMap[exam.Exam.Ancode] +// if !ok { +// ntas = nil +// } +// plannedExams = append(plannedExams, &model.PlannedExamWithNta{ +// Exam: exam.Exam, +// Constraints: exam.Constraints, +// Nta: ntas, +// }) +// } +// } +// return plannedExams, nil +// } func (p *Plexams) LockExamGroup(ctx context.Context, examGroupCode int) (*model.PlanEntry, *model.ExamGroup, error) { planEntry, err := p.dbClient.LockExamGroup(ctx, examGroupCode) diff --git a/plexams/plannedExams.go b/plexams/plannedExams.go index e9a335e..3fa79ab 100644 --- a/plexams/plannedExams.go +++ b/plexams/plannedExams.go @@ -68,7 +68,3 @@ func (p *Plexams) getTimeForSlot(dayNumber, slotNumber int) *time.Time { } return nil } - -func (p *Plexams) ExamsInSlot(ctx context.Context, day int, time int) ([]*model.ExamInPlan, error) { - return p.dbClient.ExamsInSlot(ctx, day, time) -} diff --git a/plexams/prepare.go b/plexams/prepare.go index 2135670..1a185d6 100644 --- a/plexams/prepare.go +++ b/plexams/prepare.go @@ -4,138 +4,118 @@ import ( "context" "sort" + set "github.com/deckarep/golang-set/v2" "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" ) func (p *Plexams) PrepareStudentRegs() error { ctx := context.Background() - studentRegsPerAncode, studentRegsPerStudent, err := p.prepareAllStudentRegs() - log.Debug().Int("length studentRegsPerAncode", len(studentRegsPerAncode)). - Int("length studentRegsPerStudent", len(studentRegsPerStudent)).Msg("got the following") + + programs, err := p.dbClient.GetPrograms(ctx) if err != nil { + log.Error().Err(err).Msg("cannot get programs") return err } - ancodes, err := p.dbClient.GetZpaAncodesPlanned(ctx) + connectedExams, err := p.dbClient.GetConnectedExams(ctx) if err != nil { + log.Error().Err(err).Msg("cannot get connected exams") return err } - studentRegsPerAncodePlanned := make(map[int]map[string][]*model.StudentReg) - for _, ancode := range (*ancodes).ToSlice() { - studentRegsPerAncodePlanned[ancode] = studentRegsPerAncode[ancode] + type programmAndAncode struct { + Program string `json:"program,omitempty"` + Ancode int `json:"ancode,omitempty"` } - studentRegsPerStudentPlanned := make(map[string][]*model.StudentReg, 0) - for mtknr, studentRegs := range studentRegsPerStudent { - studentRegsPlanned := make([]*model.StudentReg, 0) - for _, studentReg := range studentRegs { - for _, ancode := range (*ancodes).ToSlice() { - if ancode == studentReg.AnCode { - studentRegsPlanned = append(studentRegsPlanned, studentReg) - break - } + plannedZpaAncodes := set.NewSet[int]() + primussAncodesToZpaAncodes := make(map[programmAndAncode]int) + + for _, connectedExam := range connectedExams { + ancode := connectedExam.ZpaExam.AnCode + + plannedZpaAncodes.Add(ancode) + + for _, primussExam := range connectedExam.PrimussExams { + if primussExam.AnCode != ancode { + primussAncodesToZpaAncodes[programmAndAncode{primussExam.Program, primussExam.AnCode}] = ancode } } - studentRegsPerStudentPlanned[mtknr] = studentRegsPlanned - } - - err = p.dbClient.SaveStudentRegsPerAncode(ctx, studentRegsPerAncode, true) - if err != nil { - return err } - err = p.dbClient.SaveStudentRegsPerAncode(ctx, studentRegsPerAncodePlanned, false) - if err != nil { - return err + for k, v := range primussAncodesToZpaAncodes { + log.Debug().Interface("primussAncode", k).Int("zpa ancode", v).Msg("primuss ancodes with different zpa ancodes") } - err = p.dbClient.SaveStudentRegsPerStudent(ctx, studentRegsPerStudent, true) - if err != nil { - return err - } + // mtknr -> studentreg + studentRegsPerStudent := make(map[string][]*model.StudentReg) - err = p.dbClient.SaveStudentRegsPerStudent(ctx, studentRegsPerStudentPlanned, false) - if err != nil { - return err - } + for _, program := range programs { + studentRegs, err := p.dbClient.StudentRegsForProgram(ctx, program) + if err != nil { + log.Error().Err(err).Str("program", program).Msg("cannot get studentregs for program") + return err + } - return nil -} + for _, studentReg := range studentRegs { + zpaAncode, ok := primussAncodesToZpaAncodes[programmAndAncode{program, studentReg.AnCode}] + if ok { + log.Debug().Str("program", program).Int("primussAncode", studentReg.AnCode).Int("zpaAncode", zpaAncode). + Str("name", studentReg.Name).Msg("fixing ancode") + studentReg.AnCode = zpaAncode + } -func (p *Plexams) prepareAllStudentRegs() ( - studentRegsPerAncode map[int]map[string][]*model.StudentReg, - studentRegsPerStudent map[string][]*model.StudentReg, - err error, -) { - ctx := context.Background() - studentRegsPerAncode = make(map[int]map[string][]*model.StudentReg) - studentRegsPerStudent = make(map[string][]*model.StudentReg) + if !plannedZpaAncodes.Contains(studentReg.AnCode) { + continue + } - programs, err := p.dbClient.GetPrograms(ctx) - if err != nil { - log.Error().Err(err).Msg("cannot get programs") - return + otherRegs, ok := studentRegsPerStudent[studentReg.Mtknr] + if ok { + studentRegsPerStudent[studentReg.Mtknr] = append(otherRegs, studentReg) + } else { + studentRegsPerStudent[studentReg.Mtknr] = []*model.StudentReg{studentReg} + } + } } - ancodesPlannedPerProgram, err := p.dbClient.GetAncodesPlannedPerProgram(ctx) + ntas, err := p.Ntas(ctx) if err != nil { - log.Error().Err(err).Msg("cannot get ancodes planned per program") + log.Error().Err(err).Msg("cannot get ntas") + return err } - for _, program := range programs { - var studentRegsPerAncodeForProgram map[int][]*model.StudentReg - studentRegsPerAncodeForProgram, err = p.dbClient.GetPrimussStudentRegsPerAncode(ctx, program) - if err != nil { - log.Error().Err(err).Str("program", program).Msg("cannot get studentregs for program") - return - } + ntaMap := make(map[string]*model.NTA) + for _, nta := range ntas { + ntaMap[nta.Mtknr] = nta + } - for ancode, studentRegs := range studentRegsPerAncodeForProgram { - programsForAncode := ancodesPlannedPerProgram[ancode] - programPlanned := false + studentRegsSlice := make([]interface{}, 0) - for _, programForAncode := range programsForAncode { - if programForAncode == program { - programPlanned = true - break - } + for mtknr, regs := range studentRegsPerStudent { + if len(regs) > 0 { + ancodes := make([]int, 0, len(regs)) + for _, reg := range regs { + ancodes = append(ancodes, reg.AnCode) } - if !programPlanned { - continue - } - // per ancodes - regs, ok := studentRegsPerAncode[ancode] - if !ok { - regs = make(map[string][]*model.StudentReg) - } + sort.Ints(ancodes) - sort.Slice(studentRegs, func(i, j int) bool { - return studentRegs[i].Name < studentRegs[j].Name + studentRegsSlice = append(studentRegsSlice, &model.Student{ + Mtknr: mtknr, + Program: regs[0].Program, + Group: regs[0].Group, + Name: regs[0].Name, + Regs: ancodes, + Nta: ntaMap[mtknr], }) - regs[program] = studentRegs - studentRegsPerAncode[ancode] = regs - - // per student - for _, studentReg := range studentRegs { - regs, ok := studentRegsPerStudent[studentReg.Mtknr] - if !ok { - regs = make([]*model.StudentReg, 0) - } - regs = append(regs, studentReg) - sort.Slice(regs, func(i, j int) bool { - return regs[i].AnCode < regs[j].AnCode - }) - studentRegsPerStudent[studentReg.Mtknr] = regs - } } } - return + return p.dbClient.SaveStudentRegs(ctx, studentRegsSlice) } +// Deprecated: part of generated exams func (p *Plexams) PrepareExamsWithRegs() error { ctx := context.Background() zpaExamsToPlan, err := p.GetZpaExamsToPlan(ctx) diff --git a/plexams/roomsForNTA.go b/plexams/roomsForNTA.go index 7249566..9f48e1d 100644 --- a/plexams/roomsForNTA.go +++ b/plexams/roomsForNTA.go @@ -1,63 +1,57 @@ package plexams -import ( - "context" - "fmt" - "strings" - - "github.com/obcode/plexams.go/graph/model" - "github.com/rs/zerolog/log" -) +import "fmt" +// FIXME: rewrite me func (p *Plexams) GetRoomsForNTA(name string) error { - ctx := context.Background() - ntas, err := p.NtasWithRegs(ctx) - if err != nil { - return err - } - var nta *model.NTAWithRegs - for _, ntaInDB := range ntas { - if strings.HasPrefix(ntaInDB.Nta.Name, name) { - nta = ntaInDB - break - } - } - if nta == nil { - return fmt.Errorf("NTA with name=%s not found", name) - } - log.Debug().Str("name", nta.Nta.Name).Msg("found nta") - -ANCODES: - for _, ancode := range nta.Regs.Ancodes { - exam, err := p.dbClient.GetZpaExamByAncode(ctx, ancode) - if err != nil { - log.Error().Err(err).Int("ancode", ancode).Msg("cannot get zpa exam") - } - - constraints, err := p.ConstraintForAncode(ctx, ancode) - if err != nil { - log.Error().Err(err).Int("ancode", ancode).Msg("cannot get constraints") - } - if constraints != nil && constraints.NotPlannedByMe { - log.Debug().Int("ancode", ancode).Str("examer", exam.MainExamer).Str("module", exam.Module).Msg("exam not planned by me") - continue - } - log.Debug().Int("ancode", ancode).Str("examer", exam.MainExamer).Str("module", exam.Module).Msg("found exam") - - roomsForExam, err := p.dbClient.RoomsForAncode(ctx, ancode) - if err != nil { - log.Error().Err(err).Int("ancode", ancode).Msg("cannot get rooms") - } - for _, room := range roomsForExam { - for _, stud := range room.Students { - if nta.Nta.Mtknr == stud.Mtknr { - fmt.Printf("%d. %s: %s --- Raum %s\n", ancode, exam.MainExamer, exam.Module, room.RoomName) - continue ANCODES - } - } - } - - } - - return nil + // ctx := context.Background() + // ntas, err := p.NtasWithRegs(ctx) + // if err != nil { + // return err + // } + // var nta *model.NTAWithRegs + // for _, ntaInDB := range ntas { + // if strings.HasPrefix(ntaInDB.Nta.Name, name) { + // nta = ntaInDB + // break + // } + // } + // if nta == nil { + // return fmt.Errorf("NTA with name=%s not found", name) + // } + // log.Debug().Str("name", nta.Nta.Name).Msg("found nta") + + // ANCODES: + // for _, ancode := range nta.Regs.Ancodes { + // exam, err := p.dbClient.GetZpaExamByAncode(ctx, ancode) + // if err != nil { + // log.Error().Err(err).Int("ancode", ancode).Msg("cannot get zpa exam") + // } + + // constraints, err := p.ConstraintForAncode(ctx, ancode) + // if err != nil { + // log.Error().Err(err).Int("ancode", ancode).Msg("cannot get constraints") + // } + // if constraints != nil && constraints.NotPlannedByMe { + // log.Debug().Int("ancode", ancode).Str("examer", exam.MainExamer).Str("module", exam.Module).Msg("exam not planned by me") + // continue + // } + // log.Debug().Int("ancode", ancode).Str("examer", exam.MainExamer).Str("module", exam.Module).Msg("found exam") + + // roomsForExam, err := p.dbClient.RoomsForAncode(ctx, ancode) + // if err != nil { + // log.Error().Err(err).Int("ancode", ancode).Msg("cannot get rooms") + // } + // for _, room := range roomsForExam { + // for _, stud := range room.Students { + // if nta.Nta.Mtknr == stud.Mtknr { + // fmt.Printf("%d. %s: %s --- Raum %s\n", ancode, exam.MainExamer, exam.Module, room.RoomName) + // continue ANCODES + // } + // } + // } + + // } + + return fmt.Errorf("rewrite me") } diff --git a/plexams/validate.go b/plexams/validate.go index 2eaec27..6e74f04 100644 --- a/plexams/validate.go +++ b/plexams/validate.go @@ -19,7 +19,7 @@ func (p *Plexams) ValidateConflicts(onlyPlannedByMe bool, ancode int) error { ctx := context.Background() color.Style{color.FgRed, color.BgGreen, color.OpBold}.Println(" --- validating conflicts --- ") - planAncodeEntries, err := p.dbClient.PlanAncodeEntries(ctx) + planAncodeEntries, err := p.dbClient.PlannedAncodes(ctx) if err != nil { log.Error().Err(err).Msg("cannot get plan entries") return err @@ -67,6 +67,10 @@ func validateStudentReg(studentReg *model.StudentRegsPerStudent, planAncodeEntri return } + log.Debug().Str("name", studentReg.Student.Name).Str("mtknr", studentReg.Student.Mtknr). + Int("count", len(planAncodeEntriesForStudent)). + Msg("found exams for student in plan") + p := planAncodeEntriesForStudent for i := 0; i < len(planAncodeEntriesForStudent); i++ { for j := i + 1; j < len(planAncodeEntriesForStudent); j++ { From 32e72baf142abee62610c097a83543fd87893b04 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Wed, 29 Nov 2023 22:49:37 +0100 Subject: [PATCH 36/78] more planning exams --- cmd/generate.go | 2 +- cmd/info.go | 3 +- db/studentregs.go | 10 +- graph/generated/generated.go | 144 ++++++++++++++++++++++++- graph/studentregs.graphqls | 3 +- graph/studentregs.resolvers.go | 5 + main.go | 5 + plexams/generate.go | 1 + plexams/nta.go | 70 ++++++------ plexams/plan.go | 192 +++++++++++++++++++++++++++------ plexams/plan_examgroups.go | 91 ++++++++-------- plexams/primuss.go | 2 +- plexams/studentRegs.go | 94 ++++++++-------- plexams/validate.go | 22 ++-- 14 files changed, 462 insertions(+), 182 deletions(-) diff --git a/cmd/generate.go b/cmd/generate.go index ac95ebd..0832d0d 100644 --- a/cmd/generate.go +++ b/cmd/generate.go @@ -19,7 +19,7 @@ plan --- generate the plan.`, plexams := initPlexamsConfig() switch args[0] { case "plan": - err := plexams.GeneratePlan(context.Background()) + err := plexams.GeneratePlan(context.Background()) // nolint if err != nil { log.Fatalf("got error: %v\n", err) } diff --git a/cmd/info.go b/cmd/info.go index df34850..92d447f 100644 --- a/cmd/info.go +++ b/cmd/info.go @@ -89,7 +89,8 @@ exams-for-student name --- get exams for student.`, if len(args) < 2 { log.Fatal("need name") } - err := p.GetExamsForStudent(args[1]) + // FIXME + err := p.GetExamsForStudent(args[1]) // nolint if err != nil { fmt.Println(err) return diff --git a/db/studentregs.go b/db/studentregs.go index 8032c84..2c817f2 100644 --- a/db/studentregs.go +++ b/db/studentregs.go @@ -9,6 +9,7 @@ import ( "github.com/rs/zerolog/log" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/mongo/options" ) func (db *DB) GetStudentRegsPerAncodePlanned(ctx context.Context) ([]*model.StudentRegsPerAncode, error) { @@ -44,17 +45,20 @@ func (db *DB) GetStudentRegsPerAncodePlanned(ctx context.Context) ([]*model.Stud return studentRegs, nil } -func (db *DB) StudentRegsPerStudentPlanned(ctx context.Context) ([]*model.StudentRegsPerStudent, error) { +func (db *DB) StudentRegsPerStudentPlanned(ctx context.Context) ([]*model.Student, error) { collection := db.Client.Database(db.databaseName).Collection(collectionStudentRegsPerStudentPlanned) - cur, err := collection.Find(ctx, bson.M{}) + findOptions := options.Find() + findOptions.SetSort(bson.D{{Key: "name", Value: 1}}) + + cur, err := collection.Find(ctx, bson.M{}, findOptions) if err != nil { log.Error().Err(err).Str("semester", db.semester).Msg("MongoDB Find") return nil, err } defer cur.Close(ctx) - studentRegs := make([]*model.StudentRegsPerStudent, 0) + studentRegs := make([]*model.Student, 0) err = cur.All(ctx, &studentRegs) if err != nil { diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 7210001..888b6d3 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -411,6 +411,7 @@ type ComplexityRoot struct { StudentByMtknr func(childComplexity int, mtknr string) int StudentRegsForProgram func(childComplexity int, program string) int StudentRegsImportErrors func(childComplexity int) int + Students func(childComplexity int) int StudentsByName func(childComplexity int, regex string) int Teacher func(childComplexity int, id int) int Teachers func(childComplexity int, fromZpa *bool) int @@ -693,6 +694,7 @@ type QueryResolver interface { AwkwardSlots(ctx context.Context, ancode int) ([]*model.Slot, error) StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, error) StudentsByName(ctx context.Context, regex string) ([]*model.Student, error) + Students(ctx context.Context) ([]*model.Student, error) Teacher(ctx context.Context, id int) (*model.Teacher, error) Teachers(ctx context.Context, fromZpa *bool) ([]*model.Teacher, error) Invigilators(ctx context.Context) ([]*model.ZPAInvigilator, error) @@ -2653,6 +2655,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.StudentRegsImportErrors(childComplexity), true + case "Query.students": + if e.complexity.Query.Students == nil { + break + } + + return e.complexity.Query.Students(childComplexity), true + case "Query.studentsByName": if e.complexity.Query.StudentsByName == nil { break @@ -4196,7 +4205,8 @@ type AnCode { `, BuiltIn: false}, {Name: "../studentregs.graphqls", Input: `extend type Query { studentByMtknr(mtknr: String!): Student - studentsByName(regex: String!): [Student!] + studentsByName(regex: String!): [Student!]! + students: [Student!]! } type StudentRegsPerStudent { @@ -17727,11 +17737,14 @@ func (ec *executionContext) _Query_studentsByName(ctx context.Context, field gra return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } res := resTmp.([]*model.Student) fc.Result = res - return ec.marshalOStudent2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentᚄ(ctx, field.Selections, res) + return ec.marshalNStudent2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentᚄ(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Query_studentsByName(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -17772,6 +17785,64 @@ func (ec *executionContext) fieldContext_Query_studentsByName(ctx context.Contex return fc, nil } +func (ec *executionContext) _Query_students(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_students(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Students(rctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.Student) + fc.Result = res + return ec.marshalNStudent2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_students(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "mtknr": + return ec.fieldContext_Student_mtknr(ctx, field) + case "program": + return ec.fieldContext_Student_program(ctx, field) + case "group": + return ec.fieldContext_Student_group(ctx, field) + case "name": + return ec.fieldContext_Student_name(ctx, field) + case "regs": + return ec.fieldContext_Student_regs(ctx, field) + case "nta": + return ec.fieldContext_Student_nta(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Student", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _Query_teacher(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_teacher(ctx, field) if err != nil { @@ -29274,6 +29345,31 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } }() res = ec._Query_studentsByName(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "students": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_students(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -33135,6 +33231,50 @@ func (ec *executionContext) marshalNString2ᚕstringᚄ(ctx context.Context, sel return ret } +func (ec *executionContext) marshalNStudent2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Student) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNStudent2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudent(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + func (ec *executionContext) marshalNStudent2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudent(ctx context.Context, sel ast.SelectionSet, v *model.Student) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { diff --git a/graph/studentregs.graphqls b/graph/studentregs.graphqls index d2aa60d..60b352d 100644 --- a/graph/studentregs.graphqls +++ b/graph/studentregs.graphqls @@ -1,6 +1,7 @@ extend type Query { studentByMtknr(mtknr: String!): Student - studentsByName(regex: String!): [Student!] + studentsByName(regex: String!): [Student!]! + students: [Student!]! } type StudentRegsPerStudent { diff --git a/graph/studentregs.resolvers.go b/graph/studentregs.resolvers.go index 28e9fb3..eae310b 100644 --- a/graph/studentregs.resolvers.go +++ b/graph/studentregs.resolvers.go @@ -19,3 +19,8 @@ func (r *queryResolver) StudentByMtknr(ctx context.Context, mtknr string) (*mode func (r *queryResolver) StudentsByName(ctx context.Context, regex string) ([]*model.Student, error) { return r.plexams.StudentsByName(ctx, regex) } + +// Students is the resolver for the students field. +func (r *queryResolver) Students(ctx context.Context) ([]*model.Student, error) { + return r.plexams.Students(ctx) +} diff --git a/main.go b/main.go index 91d004d..faabac6 100644 --- a/main.go +++ b/main.go @@ -2,9 +2,14 @@ package main import ( + "time" + "github.com/obcode/plexams.go/cmd" ) func main() { + loc, _ := time.LoadLocation("Europe/Berlin") + time.Local = loc + cmd.Execute() } diff --git a/plexams/generate.go b/plexams/generate.go index 58fa455..e5fa8c2 100644 --- a/plexams/generate.go +++ b/plexams/generate.go @@ -8,6 +8,7 @@ import ( "github.com/rs/zerolog/log" ) +// Deprecated: rm me func (p *Plexams) GeneratePlan(ctx context.Context) error { err := p.dbClient.BackupPlan(ctx) diff --git a/plexams/nta.go b/plexams/nta.go index ac4589b..81182ba 100644 --- a/plexams/nta.go +++ b/plexams/nta.go @@ -4,7 +4,6 @@ import ( "context" "github.com/obcode/plexams.go/graph/model" - "github.com/rs/zerolog/log" ) func (p *Plexams) AddNta(ctx context.Context, input model.NTAInput) (*model.NTA, error) { @@ -23,41 +22,42 @@ func (p *Plexams) Nta(ctx context.Context, mtknr string) (*model.NTAWithRegs, er return p.dbClient.NtaWithRegs(ctx, mtknr) } +// Deprecated: rm me func (p *Plexams) PrepareNta() error { - ctx := context.Background() - // get NTAs - ntas, err := p.Ntas(ctx) - if err != nil { - log.Error().Err(err).Msg("cannot get NTAs") - return err - } - - // get StudentRegs - studentRegs, err := p.StudentRegsPerStudentPlanned(ctx) - if err != nil { - log.Error().Err(err).Msg("cannot get student regs") - return err - } - - // merge - ntaWithRegs := make([]*model.NTAWithRegs, 0) - for _, nta := range ntas { - for _, studentReg := range studentRegs { - if nta.Mtknr == studentReg.Student.Mtknr { - ntaWithRegs = append(ntaWithRegs, &model.NTAWithRegs{ - Nta: nta, - Regs: studentReg, - }) - break - } - } - } - - err = p.dbClient.SaveSemesterNTAs(ctx, ntaWithRegs) - if err != nil { - log.Error().Err(err).Msg("cannot save ntas for semester") - return err - } + // ctx := context.Background() + // // get NTAs + // ntas, err := p.Ntas(ctx) + // if err != nil { + // log.Error().Err(err).Msg("cannot get NTAs") + // return err + // } + + // // get StudentRegs + // studentRegs, err := p.StudentRegsPerStudentPlanned(ctx) + // if err != nil { + // log.Error().Err(err).Msg("cannot get student regs") + // return err + // } + + // // merge + // ntaWithRegs := make([]*model.NTAWithRegs, 0) + // for _, nta := range ntas { + // for _, studentReg := range studentRegs { + // if nta.Mtknr == studentReg.Student.Mtknr { + // ntaWithRegs = append(ntaWithRegs, &model.NTAWithRegs{ + // Nta: nta, + // Regs: studentReg, + // }) + // break + // } + // } + // } + + // err = p.dbClient.SaveSemesterNTAs(ctx, ntaWithRegs) + // if err != nil { + // log.Error().Err(err).Msg("cannot save ntas for semester") + // return err + // } return nil } diff --git a/plexams/plan.go b/plexams/plan.go index c74ab1c..4f5c631 100644 --- a/plexams/plan.go +++ b/plexams/plan.go @@ -4,7 +4,9 @@ import ( "context" "fmt" "sort" + "time" + set "github.com/deckarep/golang-set/v2" "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" ) @@ -64,50 +66,147 @@ func (p *Plexams) AddExamToSlot(ctx context.Context, ancode int, dayNumber int, return p.dbClient.AddExamToSlot(ctx, dayNumber, timeNumber, ancode) } -// FIXME: Allowed Slots func (p *Plexams) AllowedSlots(ctx context.Context, ancode int) ([]*model.Slot, error) { - if p.dbClient.ExamIsLocked(ctx, ancode) { - return []*model.Slot{}, nil + slot, err := p.SlotForAncode(ctx, ancode) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("exam is locked, but got an error on getting slot") + return nil, err + } + return []*model.Slot{slot}, nil + } + + exam, err := p.GeneratedExam(ctx, ancode) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("exam does not exist") } - // exam, err := p.GeneratedExam(ctx, ancode) - // if err != nil { - // log.Error().Err(err).Int("ancode", ancode).Msg("exam does not exist") - // } - // // TODO: calculate possible slots from constraints - // allSlots := p.semesterConfig.Slots + allSlots := p.semesterConfig.Slots + + if exam.Constraints != nil && exam.Constraints.FixedTime != nil { + return []*model.Slot{getSlotForTime(allSlots, exam.Constraints.FixedTime)}, nil + } + + if exam.Constraints != nil && exam.Constraints.FixedDay != nil { + return getSlotsForDay(allSlots, exam.Constraints.FixedDay), nil + } + + allowedSlots := make([]*model.Slot, 0) + + if exam.Constraints != nil && exam.Constraints.PossibleDays != nil { + for _, day := range exam.Constraints.PossibleDays { + allowedSlots = append(allowedSlots, getSlotsForDay(allSlots, day)...) + } + } else { + allowedSlots = allSlots + } + + if exam.Constraints != nil && exam.Constraints.ExcludeDays != nil { + for _, day := range exam.Constraints.ExcludeDays { + allowedSlots = removeSlotsForDay(allowedSlots, day) + } + } // TODO: recalculate from conflicts - // allowedSlots := make([]*model.Slot, 0) - // OUTER: - // for _, slot := range exam.Constraints.PossibleSlots { - // // get ExamGroups for slot and check Conflicts - // examGroups, err := p.ExamGroupsInSlot(ctx, slot.DayNumber, slot.SlotNumber) - // if err != nil { - // log.Error().Err(err).Int("day", slot.DayNumber).Int("time", slot.SlotNumber). - // Msg("cannot get exam groups in slot") - // return nil, err - // } - // for _, otherExamGroup := range examGroups { - // for _, conflict := range examGroup.ExamGroupInfo.Conflicts { - // if otherExamGroup.ExamGroupCode == conflict.ExamGroupCode { - // continue OUTER - // } - // } - // } - - // allowedSlots = append(allowedSlots, &model.Slot{ - // DayNumber: slot.DayNumber, - // SlotNumber: slot.SlotNumber, - // Starttime: p.getSlotTime(slot.DayNumber, slot.SlotNumber), - // }) - // } + allowedSlotsWithConflicts := make([]*model.Slot, 0, len(allowedSlots)) + + slotsWithConflicts, err := p.slotsWithConflicts(ctx, exam) + if err != nil { + log.Error().Err(err).Int("ancode", exam.Ancode).Msg("cannot get slots with conflicts") + return nil, err + } - // return allowedSlots, nil - return nil, nil + for _, slot := range allowedSlots { + if !slotsWithConflicts.Contains(*slot) { + allowedSlotsWithConflicts = append(allowedSlotsWithConflicts, slot) + } + } + return allowedSlotsWithConflicts, nil +} + +func (p *Plexams) AwkwardSlots(ctx context.Context, ancode int) ([]*model.Slot, error) { + exam, err := p.GeneratedExam(ctx, ancode) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("exam does not exist") + } + + type SlotID struct { + DayNumber, SlotNumber int + } + + allSlotsMap := make(map[SlotID]*model.Slot) + for _, slot := range p.semesterConfig.Slots { + allSlotsMap[SlotID{slot.DayNumber, slot.SlotNumber}] = slot + } + + slotsWithConflicts, err := p.slotsWithConflicts(ctx, exam) + if err != nil { + log.Error().Err(err).Int("ancode", exam.Ancode).Msg("cannot get slots with conflicts") + return nil, err + } + + awkwardSlots := make([]*model.Slot, 0) + for _, slot := range slotsWithConflicts.ToSlice() { + slotMinus1, ok := allSlotsMap[SlotID{slot.DayNumber, slot.SlotNumber - 1}] + if ok { + awkwardSlots = append(awkwardSlots, slotMinus1) + } + slotPlus1, ok := allSlotsMap[SlotID{slot.DayNumber, slot.SlotNumber + 1}] + if ok { + awkwardSlots = append(awkwardSlots, slotPlus1) + } + } + + return awkwardSlots, nil +} + +func (p *Plexams) slotsWithConflicts(ctx context.Context, exam *model.GeneratedExam) (set.Set[model.Slot], error) { + slotSet := set.NewSet[model.Slot]() + for _, conflict := range exam.Conflicts { + slot, err := p.SlotForAncode(ctx, conflict.Ancode) + if err != nil { + log.Error().Err(err).Int("ancode", conflict.Ancode).Msg("cannot get slot for ancode") + return nil, err + } + if slot != nil { + slotSet.Add(*slot) + } + } + return slotSet, nil +} + +func getSlotForTime(slots []*model.Slot, time *time.Time) *model.Slot { + for _, slot := range slots { + if time.Local().Day() == slot.Starttime.Day() && time.Local().Month() == slot.Starttime.Month() && + time.Local().Hour() == slot.Starttime.Local().Hour() && time.Local().Minute() == slot.Starttime.Local().Minute() { + return slot + } + } + return nil +} + +func getSlotsForDay(allSlots []*model.Slot, day *time.Time) []*model.Slot { + slots := make([]*model.Slot, 0) + + for _, slot := range allSlots { + if day.Local().Day() == slot.Starttime.Day() && day.Local().Month() == slot.Starttime.Month() { + slots = append(slots, slot) + } + } + return slots +} + +func removeSlotsForDay(allSlots []*model.Slot, day *time.Time) []*model.Slot { + slots := make([]*model.Slot, 0) + + for _, slot := range allSlots { + if !(day.Day() == slot.Starttime.Day() && day.Month() == slot.Starttime.Month()) { + slots = append(slots, slot) + } + } + return slots } func (p *Plexams) ExamsWithoutSlot(ctx context.Context) ([]*model.GeneratedExam, error) { @@ -171,3 +270,26 @@ func (p *Plexams) ExamsInSlot(ctx context.Context, day int, time int) ([]*model. func (p *Plexams) GetExamsInSlot(ctx context.Context, day int, time int) ([]*model.GeneratedExam, error) { return p.dbClient.GetExamsInSlot(ctx, day, time) } + +func (p *Plexams) SlotForAncode(ctx context.Context, ancode int) (*model.Slot, error) { + planEntry, err := p.dbClient.PlanEntry(ctx, ancode) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("cannot get plan entry for exam") + return nil, err + } + if planEntry == nil { + return nil, nil + } + + for _, slot := range p.semesterConfig.Slots { + if planEntry.DayNumber == slot.DayNumber && planEntry.SlotNumber == slot.SlotNumber { + return slot, nil + } + } + + return nil, fmt.Errorf("slot for exam #%d not found", ancode) +} + +func (p *Plexams) LockPlan(ctx context.Context) error { + return p.dbClient.LockPlan(ctx) +} diff --git a/plexams/plan_examgroups.go b/plexams/plan_examgroups.go index 03c9a2f..d47f72f 100644 --- a/plexams/plan_examgroups.go +++ b/plexams/plan_examgroups.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "sort" - "time" set "github.com/deckarep/golang-set/v2" "github.com/gookit/color" @@ -122,41 +121,41 @@ func (p *Plexams) RmExamGroupFromSlot(ctx context.Context, examGroupCode int) (b // return allowedSlots, nil // } -func (p *Plexams) AwkwardSlots(ctx context.Context, examGroupCode int) ([]*model.Slot, error) { - if p.dbClient.ExamGroupIsLocked(ctx, examGroupCode) { - return []*model.Slot{}, nil - } - examGroup, err := p.ExamGroup(ctx, examGroupCode) - if err != nil { - log.Error().Err(err).Int("examGroupCode", examGroupCode).Msg("exam group does not exist") - } +// func (p *Plexams) AwkwardSlots(ctx context.Context, examGroupCode int) ([]*model.Slot, error) { +// if p.dbClient.ExamGroupIsLocked(ctx, examGroupCode) { +// return []*model.Slot{}, nil +// } +// examGroup, err := p.ExamGroup(ctx, examGroupCode) +// if err != nil { +// log.Error().Err(err).Int("examGroupCode", examGroupCode).Msg("exam group does not exist") +// } - awkwardSlots := make([]*model.Slot, 0) - for _, conflict := range examGroup.ExamGroupInfo.Conflicts { - planEntry, err := p.dbClient.PlanEntryForExamGroup(ctx, conflict.ExamGroupCode) - if err != nil { - log.Error().Err(err).Int("examGroupCode", conflict.ExamGroupCode).Msg("error while trying to get plan entry") - continue - } +// awkwardSlots := make([]*model.Slot, 0) +// for _, conflict := range examGroup.ExamGroupInfo.Conflicts { +// planEntry, err := p.dbClient.PlanEntryForExamGroup(ctx, conflict.ExamGroupCode) +// if err != nil { +// log.Error().Err(err).Int("examGroupCode", conflict.ExamGroupCode).Msg("error while trying to get plan entry") +// continue +// } - if planEntry != nil { - awkwardSlots = append(awkwardSlots, - &model.Slot{ - DayNumber: planEntry.DayNumber, - SlotNumber: planEntry.SlotNumber - 1, - Starttime: time.Time{}, - }, - &model.Slot{ - DayNumber: planEntry.DayNumber, - SlotNumber: planEntry.SlotNumber + 1, - Starttime: time.Time{}, - }, - ) - } - } +// if planEntry != nil { +// awkwardSlots = append(awkwardSlots, +// &model.Slot{ +// DayNumber: planEntry.DayNumber, +// SlotNumber: planEntry.SlotNumber - 1, +// Starttime: time.Time{}, +// }, +// &model.Slot{ +// DayNumber: planEntry.DayNumber, +// SlotNumber: planEntry.SlotNumber + 1, +// Starttime: time.Time{}, +// }, +// ) +// } +// } - return awkwardSlots, nil -} +// return awkwardSlots, nil +// } // Deprecated: rm me func (p *Plexams) ExamGroupsWithoutSlot(ctx context.Context) ([]*model.ExamGroup, error) { @@ -209,19 +208,21 @@ func (p *Plexams) ExamerInPlan(ctx context.Context) ([]*model.ExamerInPlan, erro return p.dbClient.ExamerInPlan(ctx) } -func (p *Plexams) SlotForAncode(ctx context.Context, ancode int) (*model.Slot, error) { - examGroup, err := p.GetExamGroupForAncode(ctx, ancode) - if err != nil { - log.Error().Err(err).Int("ancode", ancode).Msg("cannot get exam group for ancode") - } +// // Deprecated: rm me +// func (p *Plexams) SlotForAncode(ctx context.Context, ancode int) (*model.Slot, error) { +// examGroup, err := p.GetExamGroupForAncode(ctx, ancode) +// if err != nil { +// log.Error().Err(err).Int("ancode", ancode).Msg("cannot get exam group for ancode") +// } - if examGroup == nil { - return nil, nil - } +// if examGroup == nil { +// return nil, nil +// } - return p.SlotForExamGroup(ctx, examGroup.ExamGroupCode) -} +// return p.SlotForExamGroup(ctx, examGroup.ExamGroupCode) +// } +// Deprecated: rm me func (p *Plexams) SlotForExamGroup(ctx context.Context, examGroupCode int) (*model.Slot, error) { planEntry, err := p.dbClient.PlanEntryForExamGroup(ctx, examGroupCode) if err != nil { @@ -307,10 +308,6 @@ func (p *Plexams) RemoveUnlockedExamGroupsFromPlan(ctx context.Context) (int, er return p.dbClient.RemoveUnlockedExamGroupsFromPlan(ctx) } -func (p *Plexams) LockPlan(ctx context.Context) error { - return p.dbClient.LockPlan(ctx) -} - func (p *Plexams) PreparePlannedExams() error { ctx := context.Background() examGroups, err := p.ExamGroups(ctx) diff --git a/plexams/primuss.go b/plexams/primuss.go index 01665e4..7b54579 100644 --- a/plexams/primuss.go +++ b/plexams/primuss.go @@ -30,7 +30,7 @@ func (p *Plexams) StudentRegsForProgram(ctx context.Context, program string) ([] return p.dbClient.StudentRegsForProgram(ctx, program) } -func (p *Plexams) StudentRegsPerStudentPlanned(ctx context.Context) ([]*model.StudentRegsPerStudent, error) { +func (p *Plexams) StudentRegsPerStudentPlanned(ctx context.Context) ([]*model.Student, error) { return p.dbClient.StudentRegsPerStudentPlanned(ctx) } diff --git a/plexams/studentRegs.go b/plexams/studentRegs.go index dc96341..a484b34 100644 --- a/plexams/studentRegs.go +++ b/plexams/studentRegs.go @@ -3,7 +3,6 @@ package plexams import ( "context" "fmt" - "strings" set "github.com/deckarep/golang-set/v2" "github.com/obcode/plexams.go/graph/model" @@ -64,51 +63,52 @@ func (p *Plexams) GetStudentRegsForAncode(ancode int) (*model.StudentRegsForAnco }, nil } +// Deprecated: rm me func (p *Plexams) GetExamsForStudent(name string) error { - ctx := context.Background() - students, err := p.dbClient.StudentRegsPerStudentPlanned(ctx) - if err != nil { - return err - } - var student *model.StudentRegsPerStudent - for _, studentInDB := range students { - if strings.HasPrefix(studentInDB.Student.Name, name) { - student = studentInDB - break - } - } - if student == nil { - return fmt.Errorf("NTA with name=%s not found", name) - } - log.Debug().Str("name", student.Student.Name).Msg("found student") - - for _, ancode := range student.Ancodes { - exam, err := p.dbClient.GetZpaExamByAncode(ctx, ancode) - if err != nil { - log.Error().Err(err).Int("ancode", ancode).Msg("cannot get zpa exam") - } - - constraints, err := p.ConstraintForAncode(ctx, ancode) - if err != nil { - log.Error().Err(err).Int("ancode", ancode).Msg("cannot get constraints") - } - if constraints != nil && constraints.NotPlannedByMe { - log.Debug().Int("ancode", ancode).Str("examer", exam.MainExamer).Str("module", exam.Module).Msg("exam not planned by me") - continue - } - log.Debug().Int("ancode", ancode).Str("examer", exam.MainExamer).Str("module", exam.Module).Msg("found exam") - - fmt.Printf("%d. %s: %s\n", ancode, exam.MainExamer, exam.Module) - - roomsForExam, err := p.dbClient.RoomsForAncode(ctx, ancode) - if err != nil { - log.Error().Err(err).Int("ancode", ancode).Msg("cannot get rooms") - } - for _, room := range roomsForExam { - fmt.Printf(" - Raum %s\n", room.RoomName) - } - - } + // ctx := context.Background() + // students, err := p.dbClient.StudentRegsPerStudentPlanned(ctx) + // if err != nil { + // return err + // } + // var student *model.StudentRegsPerStudent + // for _, studentInDB := range students { + // if strings.HasPrefix(studentInDB.Student.Name, name) { + // student = studentInDB + // break + // } + // } + // if student == nil { + // return fmt.Errorf("NTA with name=%s not found", name) + // } + // log.Debug().Str("name", student.Student.Name).Msg("found student") + + // for _, ancode := range student.Ancodes { + // exam, err := p.dbClient.GetZpaExamByAncode(ctx, ancode) + // if err != nil { + // log.Error().Err(err).Int("ancode", ancode).Msg("cannot get zpa exam") + // } + + // constraints, err := p.ConstraintForAncode(ctx, ancode) + // if err != nil { + // log.Error().Err(err).Int("ancode", ancode).Msg("cannot get constraints") + // } + // if constraints != nil && constraints.NotPlannedByMe { + // log.Debug().Int("ancode", ancode).Str("examer", exam.MainExamer).Str("module", exam.Module).Msg("exam not planned by me") + // continue + // } + // log.Debug().Int("ancode", ancode).Str("examer", exam.MainExamer).Str("module", exam.Module).Msg("found exam") + + // fmt.Printf("%d. %s: %s\n", ancode, exam.MainExamer, exam.Module) + + // roomsForExam, err := p.dbClient.RoomsForAncode(ctx, ancode) + // if err != nil { + // log.Error().Err(err).Int("ancode", ancode).Msg("cannot get rooms") + // } + // for _, room := range roomsForExam { + // fmt.Printf(" - Raum %s\n", room.RoomName) + // } + + // } return nil } @@ -121,6 +121,10 @@ func (p *Plexams) StudentsByName(ctx context.Context, regex string) ([]*model.St return p.dbClient.StudentsByName(ctx, regex) } +func (p *Plexams) Students(ctx context.Context) ([]*model.Student, error) { + return p.dbClient.StudentRegsPerStudentPlanned(ctx) +} + func (p *Plexams) StudentsFromStudentRegs(ctx context.Context, studentRegs []*model.StudentRegsPerAncodeAndProgram) ( regularStuds, ntaStuds []*model.Student, err error) { regularStuds = make([]*model.Student, 0) diff --git a/plexams/validate.go b/plexams/validate.go index 6e74f04..685904b 100644 --- a/plexams/validate.go +++ b/plexams/validate.go @@ -37,24 +37,24 @@ func (p *Plexams) ValidateConflicts(onlyPlannedByMe bool, ancode int) error { } } - studentRegs, err := p.StudentRegsPerStudentPlanned(ctx) + students, err := p.StudentRegsPerStudentPlanned(ctx) if err != nil { log.Error().Err(err).Msg("cannot get student registries per student") return err } - for _, studentReg := range studentRegs { - validateStudentReg(studentReg, planAncodeEntries, planAncodeEntriesNotPlannedByMe, onlyPlannedByMe, ancode) + for _, student := range students { + validateStudentReg(student, planAncodeEntries, planAncodeEntriesNotPlannedByMe, onlyPlannedByMe, ancode) } return nil } -func validateStudentReg(studentReg *model.StudentRegsPerStudent, planAncodeEntries []*model.PlanAncodeEntry, +func validateStudentReg(student *model.Student, planAncodeEntries []*model.PlanAncodeEntry, planAncodeEntriesNotPlannedByMe set.Set[int], onlyPlannedByMe bool, ancode int) { - log.Debug().Str("name", studentReg.Student.Name).Str("mtknr", studentReg.Student.Mtknr).Msg("checking regs for student") + log.Debug().Str("name", student.Name).Str("mtknr", student.Mtknr).Msg("checking regs for student") planAncodeEntriesForStudent := make([]*model.PlanAncodeEntry, 0) - for _, ancode := range studentReg.Ancodes { + for _, ancode := range student.Regs { for _, planEntry := range planAncodeEntries { if ancode == planEntry.Ancode { planAncodeEntriesForStudent = append(planAncodeEntriesForStudent, planEntry) @@ -63,11 +63,11 @@ func validateStudentReg(studentReg *model.StudentRegsPerStudent, planAncodeEntri } if len(planAncodeEntriesForStudent) == 0 { - log.Debug().Str("name", studentReg.Student.Name).Str("mtknr", studentReg.Student.Mtknr).Msg("no exam for student in plan") + log.Debug().Str("name", student.Name).Str("mtknr", student.Mtknr).Msg("no exam for student in plan") return } - log.Debug().Str("name", studentReg.Student.Name).Str("mtknr", studentReg.Student.Mtknr). + log.Debug().Str("name", student.Name).Str("mtknr", student.Mtknr). Int("count", len(planAncodeEntriesForStudent)). Msg("found exams for student in plan") @@ -97,7 +97,7 @@ func validateStudentReg(studentReg *model.StudentRegsPerStudent, planAncodeEntri color.Red.Printf("%3d. Same slot: ancodes %d (%d, %d) and %d (%d,%d) for student %s (%s/%s)\n", count, p[i].Ancode, p[i].DayNumber, p[i].SlotNumber, p[j].Ancode, p[j].DayNumber, p[j].SlotNumber, - studentReg.Student.Name, studentReg.Student.Program, studentReg.Student.Mtknr, + student.Name, student.Program, student.Mtknr, ) } else // adjacent slots @@ -108,7 +108,7 @@ func validateStudentReg(studentReg *model.StudentRegsPerStudent, planAncodeEntri color.Red.Printf("%3d. Adjacent slots: ancodes %d (%d, %d) and %d (%d,%d) for student %s (%s/%s)\n", count, p[i].Ancode, p[i].DayNumber, p[i].SlotNumber, p[j].Ancode, p[j].DayNumber, p[j].SlotNumber, - studentReg.Student.Name, studentReg.Student.Program, studentReg.Student.Mtknr, + student.Name, student.Program, student.Mtknr, ) } else // same day @@ -117,7 +117,7 @@ func validateStudentReg(studentReg *model.StudentRegsPerStudent, planAncodeEntri color.Yellow.Printf("%3d. Same day: ancodes %d (%d, %d) and %d (%d,%d) for student %s (%s/%s)\n", count, p[i].Ancode, p[i].DayNumber, p[i].SlotNumber, p[j].Ancode, p[j].DayNumber, p[j].SlotNumber, - studentReg.Student.Name, studentReg.Student.Program, studentReg.Student.Mtknr, + student.Name, student.Program, student.Mtknr, ) } } From 8f33cc19cba1a8f66234cef9a1d97f9ae975b09e Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Thu, 30 Nov 2023 08:47:00 +0100 Subject: [PATCH 37/78] planned exams new 1/? --- db/plan.go | 14 +- graph/exam.graphqls | 10 + graph/generated/generated.go | 1349 +++++++++++++++++++++++++++------- graph/model/models_gen.go | 18 + graph/model/plan.go | 24 - graph/plan.graphqls | 8 + plexams/pdfDraft.go | 4 +- plexams/plannedExams.go | 12 +- plexams/validate.go | 4 +- 9 files changed, 1151 insertions(+), 292 deletions(-) delete mode 100644 graph/model/plan.go diff --git a/db/plan.go b/db/plan.go index 0cbd138..7105a52 100644 --- a/db/plan.go +++ b/db/plan.go @@ -123,7 +123,7 @@ func (db *DB) PlanEntries(ctx context.Context) ([]*model.PlanEntry, error) { return planEntries, nil } -func (db *DB) PlannedAncodes(ctx context.Context) ([]*model.PlanAncodeEntry, error) { +func (db *DB) PlannedAncodes(ctx context.Context) ([]*model.PlanEntry, error) { collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) cur, err := collection.Find(ctx, bson.M{}) if err != nil { @@ -132,7 +132,7 @@ func (db *DB) PlannedAncodes(ctx context.Context) ([]*model.PlanAncodeEntry, err } defer cur.Close(ctx) - planEntries := make([]*model.PlanAncodeEntry, 0) + planEntries := make([]*model.PlanEntry, 0) err = cur.All(ctx, &planEntries) if err != nil { log.Error().Err(err).Str("collection", collectionNamePlan).Msg("cannot decode plan ancode entries") @@ -142,7 +142,7 @@ func (db *DB) PlannedAncodes(ctx context.Context) ([]*model.PlanAncodeEntry, err return planEntries, nil } -func (db *DB) PlanEntry(ctx context.Context, ancode int) (*model.PlanAncodeEntry, error) { +func (db *DB) PlanEntry(ctx context.Context, ancode int) (*model.PlanEntry, error) { collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) res := collection.FindOne(ctx, bson.D{{Key: "ancode", Value: ancode}}) @@ -153,7 +153,7 @@ func (db *DB) PlanEntry(ctx context.Context, ancode int) (*model.PlanAncodeEntry log.Error().Err(res.Err()).Str("collection", collectionNamePlan).Msg("MongoDB Find") return nil, res.Err() } - var entry model.PlanAncodeEntry + var entry model.PlanEntry err := res.Decode(&entry) if err != nil { @@ -250,7 +250,7 @@ EXAMLOOP: } // Deprecated: rm me -func (db *DB) PlanAncodeEntries(ctx context.Context) ([]*model.PlanAncodeEntry, error) { +func (db *DB) PlanAncodeEntries(ctx context.Context) ([]*model.PlanEntry, error) { examGroups, err := db.ExamGroups(ctx) if err != nil { log.Error().Err(err).Msg("cannot get exam groups") @@ -266,14 +266,14 @@ func (db *DB) PlanAncodeEntries(ctx context.Context) ([]*model.PlanAncodeEntry, log.Error().Err(err).Msg("cannot get plan entries") } - planAncodeEntries := make([]*model.PlanAncodeEntry, 0) + planAncodeEntries := make([]*model.PlanEntry, 0) for _, planEntry := range planEntries { examGroup, ok := examGroupMap[planEntry.Ancode] if !ok { log.Error().Int("exam group code", planEntry.Ancode).Msg("exam group not found") } for _, exam := range examGroup.Exams { - planAncodeEntries = append(planAncodeEntries, &model.PlanAncodeEntry{ + planAncodeEntries = append(planAncodeEntries, &model.PlanEntry{ DayNumber: planEntry.DayNumber, SlotNumber: planEntry.SlotNumber, Ancode: exam.Exam.Ancode, diff --git a/graph/exam.graphqls b/graph/exam.graphqls index c06e026..3a3dea6 100644 --- a/graph/exam.graphqls +++ b/graph/exam.graphqls @@ -122,6 +122,16 @@ type ZPAConflict { primussAncodes: [PrimussExamAncode!]! } +type PlannedExam { + ancode: Int! + zpaExam: ZPAExam! + primussExams: [EnhancedPrimussExam!]! + constraints: Constraints + conflicts: [ZPAConflict!]! + studentRegsCount: Int! + planEntry: PlanEntry +} + type Exam { ancode: Int! zpaExam: ZPAExam diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 888b6d3..07d7f6e 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -333,6 +333,24 @@ type ComplexityRoot struct { Slots func(childComplexity int) int } + PlanEntry struct { + Ancode func(childComplexity int) int + DayNumber func(childComplexity int) int + Locked func(childComplexity int) int + SlotNumber func(childComplexity int) int + Starttime func(childComplexity int) int + } + + PlannedExam struct { + Ancode func(childComplexity int) int + Conflicts func(childComplexity int) int + Constraints func(childComplexity int) int + PlanEntry func(childComplexity int) int + PrimussExams func(childComplexity int) int + StudentRegsCount func(childComplexity int) int + ZpaExam func(childComplexity int) int + } + PlannedExamWithNTA struct { Constraints func(childComplexity int) int Exam func(childComplexity int) int @@ -2085,6 +2103,90 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Plan.Slots(childComplexity), true + case "PlanEntry.ancode": + if e.complexity.PlanEntry.Ancode == nil { + break + } + + return e.complexity.PlanEntry.Ancode(childComplexity), true + + case "PlanEntry.dayNumber": + if e.complexity.PlanEntry.DayNumber == nil { + break + } + + return e.complexity.PlanEntry.DayNumber(childComplexity), true + + case "PlanEntry.locked": + if e.complexity.PlanEntry.Locked == nil { + break + } + + return e.complexity.PlanEntry.Locked(childComplexity), true + + case "PlanEntry.slotNumber": + if e.complexity.PlanEntry.SlotNumber == nil { + break + } + + return e.complexity.PlanEntry.SlotNumber(childComplexity), true + + case "PlanEntry.starttime": + if e.complexity.PlanEntry.Starttime == nil { + break + } + + return e.complexity.PlanEntry.Starttime(childComplexity), true + + case "PlannedExam.ancode": + if e.complexity.PlannedExam.Ancode == nil { + break + } + + return e.complexity.PlannedExam.Ancode(childComplexity), true + + case "PlannedExam.conflicts": + if e.complexity.PlannedExam.Conflicts == nil { + break + } + + return e.complexity.PlannedExam.Conflicts(childComplexity), true + + case "PlannedExam.constraints": + if e.complexity.PlannedExam.Constraints == nil { + break + } + + return e.complexity.PlannedExam.Constraints(childComplexity), true + + case "PlannedExam.planEntry": + if e.complexity.PlannedExam.PlanEntry == nil { + break + } + + return e.complexity.PlannedExam.PlanEntry(childComplexity), true + + case "PlannedExam.primussExams": + if e.complexity.PlannedExam.PrimussExams == nil { + break + } + + return e.complexity.PlannedExam.PrimussExams(childComplexity), true + + case "PlannedExam.studentRegsCount": + if e.complexity.PlannedExam.StudentRegsCount == nil { + break + } + + return e.complexity.PlannedExam.StudentRegsCount(childComplexity), true + + case "PlannedExam.zpaExam": + if e.complexity.PlannedExam.ZpaExam == nil { + break + } + + return e.complexity.PlannedExam.ZpaExam(childComplexity), true + case "PlannedExamWithNTA.constraints": if e.complexity.PlannedExamWithNTA.Constraints == nil { break @@ -3781,6 +3883,16 @@ type ZPAConflict { primussAncodes: [PrimussExamAncode!]! } +type PlannedExam { + ancode: Int! + zpaExam: ZPAExam! + primussExams: [EnhancedPrimussExam!]! + constraints: Constraints + conflicts: [ZPAConflict!]! + studentRegsCount: Int! + planEntry: PlanEntry +} + type Exam { ancode: Int! zpaExam: ZPAExam @@ -4030,6 +4142,14 @@ type ExamerInPlan { mainExamer: String! mainExamerID: Int! } + +type PlanEntry { + dayNumber: Int! + slotNumber: Int! + starttime: Time! + ancode: Int! + locked: Boolean! +} `, BuiltIn: false}, {Name: "../primuss.graphqls", Input: `type PrimussExam { ancode: Int! @@ -14172,6 +14292,604 @@ func (ec *executionContext) fieldContext_Plan_slots(ctx context.Context, field g return fc, nil } +func (ec *executionContext) _PlanEntry_dayNumber(ctx context.Context, field graphql.CollectedField, obj *model.PlanEntry) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlanEntry_dayNumber(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.DayNumber, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlanEntry_dayNumber(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlanEntry", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PlanEntry_slotNumber(ctx context.Context, field graphql.CollectedField, obj *model.PlanEntry) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlanEntry_slotNumber(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.SlotNumber, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlanEntry_slotNumber(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlanEntry", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PlanEntry_starttime(ctx context.Context, field graphql.CollectedField, obj *model.PlanEntry) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlanEntry_starttime(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Starttime, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(time.Time) + fc.Result = res + return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlanEntry_starttime(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlanEntry", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Time does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PlanEntry_ancode(ctx context.Context, field graphql.CollectedField, obj *model.PlanEntry) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlanEntry_ancode(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Ancode, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlanEntry_ancode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlanEntry", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PlanEntry_locked(ctx context.Context, field graphql.CollectedField, obj *model.PlanEntry) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlanEntry_locked(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Locked, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlanEntry_locked(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlanEntry", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PlannedExam_ancode(ctx context.Context, field graphql.CollectedField, obj *model.PlannedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedExam_ancode(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Ancode, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedExam_ancode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PlannedExam_zpaExam(ctx context.Context, field graphql.CollectedField, obj *model.PlannedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedExam_zpaExam(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ZpaExam, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.ZPAExam) + fc.Result = res + return ec.marshalNZPAExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExam(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedExam_zpaExam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "zpaID": + return ec.fieldContext_ZPAExam_zpaID(ctx, field) + case "semester": + return ec.fieldContext_ZPAExam_semester(ctx, field) + case "ancode": + return ec.fieldContext_ZPAExam_ancode(ctx, field) + case "module": + return ec.fieldContext_ZPAExam_module(ctx, field) + case "mainExamer": + return ec.fieldContext_ZPAExam_mainExamer(ctx, field) + case "mainExamerID": + return ec.fieldContext_ZPAExam_mainExamerID(ctx, field) + case "examType": + return ec.fieldContext_ZPAExam_examType(ctx, field) + case "examTypeFull": + return ec.fieldContext_ZPAExam_examTypeFull(ctx, field) + case "duration": + return ec.fieldContext_ZPAExam_duration(ctx, field) + case "isRepeaterExam": + return ec.fieldContext_ZPAExam_isRepeaterExam(ctx, field) + case "groups": + return ec.fieldContext_ZPAExam_groups(ctx, field) + case "primussAncodes": + return ec.fieldContext_ZPAExam_primussAncodes(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ZPAExam", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _PlannedExam_primussExams(ctx context.Context, field graphql.CollectedField, obj *model.PlannedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedExam_primussExams(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PrimussExams, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.EnhancedPrimussExam) + fc.Result = res + return ec.marshalNEnhancedPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPrimussExamᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedExam_primussExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "exam": + return ec.fieldContext_EnhancedPrimussExam_exam(ctx, field) + case "studentRegs": + return ec.fieldContext_EnhancedPrimussExam_studentRegs(ctx, field) + case "conflicts": + return ec.fieldContext_EnhancedPrimussExam_conflicts(ctx, field) + case "ntas": + return ec.fieldContext_EnhancedPrimussExam_ntas(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type EnhancedPrimussExam", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _PlannedExam_constraints(ctx context.Context, field graphql.CollectedField, obj *model.PlannedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedExam_constraints(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Constraints, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.Constraints) + fc.Result = res + return ec.marshalOConstraints2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConstraints(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedExam_constraints(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "ancode": + return ec.fieldContext_Constraints_ancode(ctx, field) + case "notPlannedByMe": + return ec.fieldContext_Constraints_notPlannedByMe(ctx, field) + case "excludeDays": + return ec.fieldContext_Constraints_excludeDays(ctx, field) + case "possibleDays": + return ec.fieldContext_Constraints_possibleDays(ctx, field) + case "fixedDay": + return ec.fieldContext_Constraints_fixedDay(ctx, field) + case "fixedTime": + return ec.fieldContext_Constraints_fixedTime(ctx, field) + case "sameSlot": + return ec.fieldContext_Constraints_sameSlot(ctx, field) + case "online": + return ec.fieldContext_Constraints_online(ctx, field) + case "roomConstraints": + return ec.fieldContext_Constraints_roomConstraints(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Constraints", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _PlannedExam_conflicts(ctx context.Context, field graphql.CollectedField, obj *model.PlannedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedExam_conflicts(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Conflicts, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.ZPAConflict) + fc.Result = res + return ec.marshalNZPAConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAConflictᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedExam_conflicts(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "ancode": + return ec.fieldContext_ZPAConflict_ancode(ctx, field) + case "numberOfStuds": + return ec.fieldContext_ZPAConflict_numberOfStuds(ctx, field) + case "primussAncodes": + return ec.fieldContext_ZPAConflict_primussAncodes(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ZPAConflict", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _PlannedExam_studentRegsCount(ctx context.Context, field graphql.CollectedField, obj *model.PlannedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedExam_studentRegsCount(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.StudentRegsCount, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedExam_studentRegsCount(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PlannedExam_planEntry(ctx context.Context, field graphql.CollectedField, obj *model.PlannedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedExam_planEntry(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PlanEntry, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.PlanEntry) + fc.Result = res + return ec.marshalOPlanEntry2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlanEntry(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedExam_planEntry(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "dayNumber": + return ec.fieldContext_PlanEntry_dayNumber(ctx, field) + case "slotNumber": + return ec.fieldContext_PlanEntry_slotNumber(ctx, field) + case "starttime": + return ec.fieldContext_PlanEntry_starttime(ctx, field) + case "ancode": + return ec.fieldContext_PlanEntry_ancode(ctx, field) + case "locked": + return ec.fieldContext_PlanEntry_locked(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type PlanEntry", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _PlannedExamWithNTA_exam(ctx context.Context, field graphql.CollectedField, obj *model.PlannedExamWithNta) (ret graphql.Marshaler) { fc, err := ec.fieldContext_PlannedExamWithNTA_exam(ctx, field) if err != nil { @@ -27630,169 +28348,304 @@ func (ec *executionContext) _InvigilatorsForDay(ctx context.Context, sel ast.Sel return out } -var mutationImplementors = []string{"Mutation"} +var mutationImplementors = []string{"Mutation"} + +func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, mutationImplementors) + ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ + Object: "Mutation", + }) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + innerCtx := graphql.WithRootFieldContext(ctx, &graphql.RootFieldContext{ + Object: field.Name, + Field: field, + }) + + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Mutation") + case "setSemester": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_setSemester(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "zpaExamsToPlan": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_zpaExamsToPlan(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "addZpaExamToPlan": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_addZpaExamToPlan(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "rmZpaExamFromPlan": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_rmZpaExamFromPlan(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "addAdditionalExam": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_addAdditionalExam(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "removePrimussExam": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_removePrimussExam(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "addNTA": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_addNTA(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "notPlannedByMe": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_notPlannedByMe(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "excludeDays": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_excludeDays(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "possibleDays": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_possibleDays(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "sameSlot": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_sameSlot(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "placesWithSockets": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_placesWithSockets(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "lab": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_lab(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "exahmRooms": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_exahmRooms(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "seb": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_seb(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "online": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_online(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "addExamGroupToSlot": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_addExamGroupToSlot(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "rmExamGroupFromSlot": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_rmExamGroupFromSlot(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "addRoomToExam": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_addRoomToExam(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "addExamToSlot": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_addExamToSlot(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "rmExamFromSlot": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_rmExamFromSlot(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var nTAImplementors = []string{"NTA"} + +func (ec *executionContext) _NTA(ctx context.Context, sel ast.SelectionSet, obj *model.NTA) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, nTAImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("NTA") + case "name": + out.Values[i] = ec._NTA_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "mtknr": + out.Values[i] = ec._NTA_mtknr(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "compensation": + out.Values[i] = ec._NTA_compensation(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "deltaDurationPercent": + out.Values[i] = ec._NTA_deltaDurationPercent(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "needsRoomAlone": + out.Values[i] = ec._NTA_needsRoomAlone(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "program": + out.Values[i] = ec._NTA_program(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "from": + out.Values[i] = ec._NTA_from(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "until": + out.Values[i] = ec._NTA_until(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "lastSemester": + out.Values[i] = ec._NTA_lastSemester(ctx, field, obj) + case "exams": + out.Values[i] = ec._NTA_exams(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var nTAExamImplementors = []string{"NTAExam"} -func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, mutationImplementors) - ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ - Object: "Mutation", - }) +func (ec *executionContext) _NTAExam(ctx context.Context, sel ast.SelectionSet, obj *model.NTAExam) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, nTAExamImplementors) out := graphql.NewFieldSet(fields) deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { - innerCtx := graphql.WithRootFieldContext(ctx, &graphql.RootFieldContext{ - Object: field.Name, - Field: field, - }) - switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("Mutation") - case "setSemester": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_setSemester(ctx, field) - }) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "zpaExamsToPlan": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_zpaExamsToPlan(ctx, field) - }) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "addZpaExamToPlan": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_addZpaExamToPlan(ctx, field) - }) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "rmZpaExamFromPlan": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_rmZpaExamFromPlan(ctx, field) - }) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "addAdditionalExam": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_addAdditionalExam(ctx, field) - }) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "removePrimussExam": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_removePrimussExam(ctx, field) - }) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "addNTA": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_addNTA(ctx, field) - }) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "notPlannedByMe": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_notPlannedByMe(ctx, field) - }) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "excludeDays": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_excludeDays(ctx, field) - }) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "possibleDays": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_possibleDays(ctx, field) - }) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "sameSlot": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_sameSlot(ctx, field) - }) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "placesWithSockets": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_placesWithSockets(ctx, field) - }) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "lab": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_lab(ctx, field) - }) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "exahmRooms": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_exahmRooms(ctx, field) - }) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "seb": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_seb(ctx, field) - }) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "online": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_online(ctx, field) - }) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "addExamGroupToSlot": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_addExamGroupToSlot(ctx, field) - }) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "rmExamGroupFromSlot": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_rmExamGroupFromSlot(ctx, field) - }) + out.Values[i] = graphql.MarshalString("NTAExam") + case "semester": + out.Values[i] = ec._NTAExam_semester(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "addRoomToExam": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_addRoomToExam(ctx, field) - }) + case "ancode": + out.Values[i] = ec._NTAExam_ancode(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "addExamToSlot": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_addExamToSlot(ctx, field) - }) + case "module": + out.Values[i] = ec._NTAExam_module(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "rmExamFromSlot": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_rmExamFromSlot(ctx, field) - }) + case "mainExamer": + out.Values[i] = ec._NTAExam_mainExamer(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } @@ -27819,64 +28672,24 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) return out } -var nTAImplementors = []string{"NTA"} +var nTAWithRegsImplementors = []string{"NTAWithRegs"} -func (ec *executionContext) _NTA(ctx context.Context, sel ast.SelectionSet, obj *model.NTA) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, nTAImplementors) +func (ec *executionContext) _NTAWithRegs(ctx context.Context, sel ast.SelectionSet, obj *model.NTAWithRegs) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, nTAWithRegsImplementors) out := graphql.NewFieldSet(fields) deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("NTA") - case "name": - out.Values[i] = ec._NTA_name(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "mtknr": - out.Values[i] = ec._NTA_mtknr(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "compensation": - out.Values[i] = ec._NTA_compensation(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "deltaDurationPercent": - out.Values[i] = ec._NTA_deltaDurationPercent(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "needsRoomAlone": - out.Values[i] = ec._NTA_needsRoomAlone(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "program": - out.Values[i] = ec._NTA_program(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "from": - out.Values[i] = ec._NTA_from(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "until": - out.Values[i] = ec._NTA_until(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "lastSemester": - out.Values[i] = ec._NTA_lastSemester(ctx, field, obj) - case "exams": - out.Values[i] = ec._NTA_exams(ctx, field, obj) + out.Values[i] = graphql.MarshalString("NTAWithRegs") + case "nta": + out.Values[i] = ec._NTAWithRegs_nta(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } + case "regs": + out.Values[i] = ec._NTAWithRegs_regs(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -27900,37 +28713,24 @@ func (ec *executionContext) _NTA(ctx context.Context, sel ast.SelectionSet, obj return out } -var nTAExamImplementors = []string{"NTAExam"} +var nTAWithRegsByExamImplementors = []string{"NTAWithRegsByExam"} -func (ec *executionContext) _NTAExam(ctx context.Context, sel ast.SelectionSet, obj *model.NTAExam) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, nTAExamImplementors) +func (ec *executionContext) _NTAWithRegsByExam(ctx context.Context, sel ast.SelectionSet, obj *model.NTAWithRegsByExam) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, nTAWithRegsByExamImplementors) out := graphql.NewFieldSet(fields) deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("NTAExam") - case "semester": - out.Values[i] = ec._NTAExam_semester(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "ancode": - out.Values[i] = ec._NTAExam_ancode(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "module": - out.Values[i] = ec._NTAExam_module(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "mainExamer": - out.Values[i] = ec._NTAExam_mainExamer(ctx, field, obj) + out.Values[i] = graphql.MarshalString("NTAWithRegsByExam") + case "exam": + out.Values[i] = ec._NTAWithRegsByExam_exam(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } + case "ntas": + out.Values[i] = ec._NTAWithRegsByExam_ntas(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -27954,24 +28754,24 @@ func (ec *executionContext) _NTAExam(ctx context.Context, sel ast.SelectionSet, return out } -var nTAWithRegsImplementors = []string{"NTAWithRegs"} +var nTAWithRegsByExamAndTeacherImplementors = []string{"NTAWithRegsByExamAndTeacher"} -func (ec *executionContext) _NTAWithRegs(ctx context.Context, sel ast.SelectionSet, obj *model.NTAWithRegs) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, nTAWithRegsImplementors) +func (ec *executionContext) _NTAWithRegsByExamAndTeacher(ctx context.Context, sel ast.SelectionSet, obj *model.NTAWithRegsByExamAndTeacher) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, nTAWithRegsByExamAndTeacherImplementors) out := graphql.NewFieldSet(fields) deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("NTAWithRegs") - case "nta": - out.Values[i] = ec._NTAWithRegs_nta(ctx, field, obj) + out.Values[i] = graphql.MarshalString("NTAWithRegsByExamAndTeacher") + case "teacher": + out.Values[i] = ec._NTAWithRegsByExamAndTeacher_teacher(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "regs": - out.Values[i] = ec._NTAWithRegs_regs(ctx, field, obj) + case "exams": + out.Values[i] = ec._NTAWithRegsByExamAndTeacher_exams(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -27995,24 +28795,21 @@ func (ec *executionContext) _NTAWithRegs(ctx context.Context, sel ast.SelectionS return out } -var nTAWithRegsByExamImplementors = []string{"NTAWithRegsByExam"} +var planImplementors = []string{"Plan"} -func (ec *executionContext) _NTAWithRegsByExam(ctx context.Context, sel ast.SelectionSet, obj *model.NTAWithRegsByExam) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, nTAWithRegsByExamImplementors) +func (ec *executionContext) _Plan(ctx context.Context, sel ast.SelectionSet, obj *model.Plan) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, planImplementors) out := graphql.NewFieldSet(fields) deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("NTAWithRegsByExam") - case "exam": - out.Values[i] = ec._NTAWithRegsByExam_exam(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "ntas": - out.Values[i] = ec._NTAWithRegsByExam_ntas(ctx, field, obj) + out.Values[i] = graphql.MarshalString("Plan") + case "semesterConfig": + out.Values[i] = ec._Plan_semesterConfig(ctx, field, obj) + case "slots": + out.Values[i] = ec._Plan_slots(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -28036,24 +28833,42 @@ func (ec *executionContext) _NTAWithRegsByExam(ctx context.Context, sel ast.Sele return out } -var nTAWithRegsByExamAndTeacherImplementors = []string{"NTAWithRegsByExamAndTeacher"} +var planEntryImplementors = []string{"PlanEntry"} -func (ec *executionContext) _NTAWithRegsByExamAndTeacher(ctx context.Context, sel ast.SelectionSet, obj *model.NTAWithRegsByExamAndTeacher) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, nTAWithRegsByExamAndTeacherImplementors) +func (ec *executionContext) _PlanEntry(ctx context.Context, sel ast.SelectionSet, obj *model.PlanEntry) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, planEntryImplementors) out := graphql.NewFieldSet(fields) deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("NTAWithRegsByExamAndTeacher") - case "teacher": - out.Values[i] = ec._NTAWithRegsByExamAndTeacher_teacher(ctx, field, obj) + out.Values[i] = graphql.MarshalString("PlanEntry") + case "dayNumber": + out.Values[i] = ec._PlanEntry_dayNumber(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "slotNumber": + out.Values[i] = ec._PlanEntry_slotNumber(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "starttime": + out.Values[i] = ec._PlanEntry_starttime(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "ancode": + out.Values[i] = ec._PlanEntry_ancode(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "locked": + out.Values[i] = ec._PlanEntry_locked(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "exams": - out.Values[i] = ec._NTAWithRegsByExamAndTeacher_exams(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -28077,21 +28892,46 @@ func (ec *executionContext) _NTAWithRegsByExamAndTeacher(ctx context.Context, se return out } -var planImplementors = []string{"Plan"} +var plannedExamImplementors = []string{"PlannedExam"} -func (ec *executionContext) _Plan(ctx context.Context, sel ast.SelectionSet, obj *model.Plan) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, planImplementors) +func (ec *executionContext) _PlannedExam(ctx context.Context, sel ast.SelectionSet, obj *model.PlannedExam) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, plannedExamImplementors) out := graphql.NewFieldSet(fields) deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("Plan") - case "semesterConfig": - out.Values[i] = ec._Plan_semesterConfig(ctx, field, obj) - case "slots": - out.Values[i] = ec._Plan_slots(ctx, field, obj) + out.Values[i] = graphql.MarshalString("PlannedExam") + case "ancode": + out.Values[i] = ec._PlannedExam_ancode(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "zpaExam": + out.Values[i] = ec._PlannedExam_zpaExam(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "primussExams": + out.Values[i] = ec._PlannedExam_primussExams(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "constraints": + out.Values[i] = ec._PlannedExam_constraints(ctx, field, obj) + case "conflicts": + out.Values[i] = ec._PlannedExam_conflicts(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "studentRegsCount": + out.Values[i] = ec._PlannedExam_studentRegsCount(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "planEntry": + out.Values[i] = ec._PlannedExam_planEntry(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -35037,6 +35877,13 @@ func (ec *executionContext) marshalONTAWithRegsByExamAndTeacher2ᚕᚖgithubᚗc return ret } +func (ec *executionContext) marshalOPlanEntry2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlanEntry(ctx context.Context, sel ast.SelectionSet, v *model.PlanEntry) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._PlanEntry(ctx, sel, v) +} + func (ec *executionContext) marshalOPlannedExamWithNTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExamWithNtaᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PlannedExamWithNta) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index b2c464e..931698d 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -257,6 +257,24 @@ type Plan struct { Slots []*SlotWithExamGroups `json:"slots,omitempty"` } +type PlanEntry struct { + DayNumber int `json:"dayNumber"` + SlotNumber int `json:"slotNumber"` + Starttime time.Time `json:"starttime"` + Ancode int `json:"ancode"` + Locked bool `json:"locked"` +} + +type PlannedExam struct { + Ancode int `json:"ancode"` + ZpaExam *ZPAExam `json:"zpaExam"` + PrimussExams []*EnhancedPrimussExam `json:"primussExams"` + Constraints *Constraints `json:"constraints,omitempty"` + Conflicts []*ZPAConflict `json:"conflicts"` + StudentRegsCount int `json:"studentRegsCount"` + PlanEntry *PlanEntry `json:"planEntry,omitempty"` +} + type PlannedExamWithNta struct { Exam *ExamWithRegs `json:"exam"` Constraints *Constraints `json:"constraints,omitempty"` diff --git a/graph/model/plan.go b/graph/model/plan.go deleted file mode 100644 index 280c2d9..0000000 --- a/graph/model/plan.go +++ /dev/null @@ -1,24 +0,0 @@ -package model - -import "time" - -type PlanEntry struct { - DayNumber int `json:"dayNumber"` - SlotNumber int `json:"slotNumber"` - Ancode int `json:"ancode"` - Locked bool `json:"locked"` -} - -type PlanAncodeEntry struct { - DayNumber int `json:"dayNumber"` - SlotNumber int `json:"slotNumber"` - Ancode int `json:"ancode"` - Locked bool `json:"locked"` -} - -type PlannedExam struct { - Ancode int - Module string - MainExamer string - DateTime *time.Time -} diff --git a/graph/plan.graphqls b/graph/plan.graphqls index 6c8fab8..1951969 100644 --- a/graph/plan.graphqls +++ b/graph/plan.graphqls @@ -78,3 +78,11 @@ type ExamerInPlan { mainExamer: String! mainExamerID: Int! } + +type PlanEntry { + dayNumber: Int! + slotNumber: Int! + starttime: Time! + ancode: Int! + locked: Boolean! +} diff --git a/plexams/pdfDraft.go b/plexams/pdfDraft.go index d591a16..e72a371 100644 --- a/plexams/pdfDraft.go +++ b/plexams/pdfDraft.go @@ -239,8 +239,8 @@ func (p *Plexams) tableForProgram(ctx context.Context, program, programLong stri } for _, exam := range exams { contents = append(contents, - []string{strconv.Itoa(exam.Ancode), exam.Module, exam.MainExamer, - r.Replace(exam.DateTime.Format("Mon. 02.01.06, 15:04 Uhr"))}) + []string{strconv.Itoa(exam.Ancode), exam.ZpaExam.Module, exam.ZpaExam.MainExamer, + r.Replace(exam.PlanEntry.Starttime.Format("Mon. 02.01.06, 15:04 Uhr"))}) } grayColor := color.Color{ diff --git a/plexams/plannedExams.go b/plexams/plannedExams.go index 3fa79ab..88ee19f 100644 --- a/plexams/plannedExams.go +++ b/plexams/plannedExams.go @@ -31,11 +31,11 @@ func (p *Plexams) PlannedExamsForProgram(ctx context.Context, program string) ([ var plannedExam *model.PlannedExam for _, primussExam := range connectedExam.PrimussExams { if primussExam.Program == program { - plannedExam = &model.PlannedExam{ - Ancode: connectedExam.ZpaExam.AnCode, - Module: connectedExam.ZpaExam.Module, - MainExamer: connectedExam.ZpaExam.MainExamer, - DateTime: nil, + plannedExam = &model.PlannedExam{ // FIXME: new planned exam + Ancode: connectedExam.ZpaExam.AnCode, + // Module: connectedExam.ZpaExam.Module, + // MainExamer: connectedExam.ZpaExam.MainExamer, + // DateTime: nil, } } } @@ -52,7 +52,7 @@ func (p *Plexams) PlannedExamsForProgram(ctx context.Context, program string) ([ return nil, err } if slot != nil { - plannedExam.DateTime = p.getTimeForSlot(slot.DayNumber, slot.SlotNumber) + // plannedExam.DateTime = p.getTimeForSlot(slot.DayNumber, slot.SlotNumber) // FIXME: new planned exam } plannedExams = append(plannedExams, plannedExam) } diff --git a/plexams/validate.go b/plexams/validate.go index 685904b..4d0acae 100644 --- a/plexams/validate.go +++ b/plexams/validate.go @@ -49,11 +49,11 @@ func (p *Plexams) ValidateConflicts(onlyPlannedByMe bool, ancode int) error { return nil } -func validateStudentReg(student *model.Student, planAncodeEntries []*model.PlanAncodeEntry, +func validateStudentReg(student *model.Student, planAncodeEntries []*model.PlanEntry, planAncodeEntriesNotPlannedByMe set.Set[int], onlyPlannedByMe bool, ancode int) { log.Debug().Str("name", student.Name).Str("mtknr", student.Mtknr).Msg("checking regs for student") - planAncodeEntriesForStudent := make([]*model.PlanAncodeEntry, 0) + planAncodeEntriesForStudent := make([]*model.PlanEntry, 0) for _, ancode := range student.Regs { for _, planEntry := range planAncodeEntries { if ancode == planEntry.Ancode { From c64ded2c75683f6efdf28dece883b870c6d0d7ce Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Thu, 30 Nov 2023 08:55:08 +0100 Subject: [PATCH 38/78] make linter happy --- db/plan.go | 18 +++---- plexams/plan.go | 6 ++- plexams/plan_examgroups.go | 102 +++++++++++++++++++------------------ plexams/plannedExams.go | 18 ++++--- 4 files changed, 74 insertions(+), 70 deletions(-) diff --git a/db/plan.go b/db/plan.go index 7105a52..4116775 100644 --- a/db/plan.go +++ b/db/plan.go @@ -11,28 +11,24 @@ import ( "go.mongodb.org/mongo-driver/mongo" ) -func (db *DB) AddExamToSlot(ctx context.Context, dayNumber int, timeNumber int, ancode int) (bool, error) { - if db.ExamGroupIsLocked(ctx, ancode) { - return false, fmt.Errorf("exam %d is locked", ancode) +func (db *DB) AddExamToSlot(ctx context.Context, planEntry *model.PlanEntry) (bool, error) { + if db.ExamGroupIsLocked(ctx, planEntry.Ancode) { + return false, fmt.Errorf("exam %d is locked", planEntry.Ancode) } collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) - _, err := collection.DeleteMany(ctx, bson.D{{Key: "ancode", Value: ancode}}) + _, err := collection.DeleteMany(ctx, bson.D{{Key: "ancode", Value: planEntry.Ancode}}) if err != nil { - log.Error().Err(err).Int("day", dayNumber).Int("time", timeNumber).Int("ancode", ancode). + log.Error().Err(err).Int("day", planEntry.DayNumber).Int("time", planEntry.SlotNumber).Int("ancode", planEntry.Ancode). Msg("cannot rm exam from plan") return false, err } - _, err = collection.InsertOne(ctx, &model.PlanEntry{ - DayNumber: dayNumber, - SlotNumber: timeNumber, - Ancode: ancode, - }) + _, err = collection.InsertOne(ctx, planEntry) if err != nil { - log.Error().Err(err).Int("day", dayNumber).Int("time", timeNumber).Int("ancode", ancode). + log.Error().Err(err).Int("day", planEntry.DayNumber).Int("time", planEntry.SlotNumber).Int("ancode", planEntry.Ancode). Msg("cannot add exam to slot") return false, err } diff --git a/plexams/plan.go b/plexams/plan.go index 4f5c631..fa81101 100644 --- a/plexams/plan.go +++ b/plexams/plan.go @@ -63,7 +63,11 @@ func (p *Plexams) AddExamToSlot(ctx context.Context, ancode int, dayNumber int, // dayNumber, timeNumber, ancode) // } - return p.dbClient.AddExamToSlot(ctx, dayNumber, timeNumber, ancode) + return p.dbClient.AddExamToSlot(ctx, &model.PlanEntry{ + DayNumber: dayNumber, + SlotNumber: timeNumber, + Ancode: ancode, + }) } func (p *Plexams) AllowedSlots(ctx context.Context, ancode int) ([]*model.Slot, error) { diff --git a/plexams/plan_examgroups.go b/plexams/plan_examgroups.go index d47f72f..cde04cf 100644 --- a/plexams/plan_examgroups.go +++ b/plexams/plan_examgroups.go @@ -26,58 +26,60 @@ func (p *Plexams) GetExamGroupForAncode(ctx context.Context, ancode int) (*model return p.dbClient.GetExamGroupForAncode(ctx, ancode) } +// Deprecated: rm me func (p *Plexams) AddExamGroupToSlot(ctx context.Context, dayNumber int, timeNumber int, examGroupCode int) (bool, error) { + return false, fmt.Errorf("not implemented") // check if slot exists - ok := false - for _, day := range p.semesterConfig.Days { - if day.Number == dayNumber { - ok = true - break - } - } - if !ok { - log.Error().Int("day", dayNumber).Msg("day does not exists") - return false, fmt.Errorf("day %d does not exist", dayNumber) - } - ok = false - for _, time := range p.semesterConfig.Starttimes { - if time.Number == timeNumber { - ok = true - break - } - } - if !ok { - log.Error().Int("time", timeNumber).Msg("time does not exists") - return false, fmt.Errorf("time %d does not exist", timeNumber) - } - - // check if examGroup exists - _, err := p.ExamGroup(ctx, examGroupCode) - if err != nil { - log.Error().Err(err).Int("examGroupCode", examGroupCode).Msg("exam group does not exist") - } - - // check if slot is allowed - allowedSlots, err := p.AllowedSlots(ctx, examGroupCode) - if err != nil { - log.Error().Err(err).Int("examGroupCode", examGroupCode).Msg("cannot get allowed slots") - } - slotIsAllowed := false - - for _, slot := range allowedSlots { - if slot.DayNumber == dayNumber && slot.SlotNumber == timeNumber { - slotIsAllowed = true - break - } - } - if !slotIsAllowed { - log.Debug().Int("day", dayNumber).Int("time", timeNumber).Int("examGroupCode", examGroupCode). - Msg("slot is not allowed") - return false, fmt.Errorf("slot (%d,%d) is not allowed for exam group %d", - dayNumber, timeNumber, examGroupCode) - } - - return p.dbClient.AddExamToSlot(ctx, dayNumber, timeNumber, examGroupCode) + // ok := false + // for _, day := range p.semesterConfig.Days { + // if day.Number == dayNumber { + // ok = true + // break + // } + // } + // if !ok { + // log.Error().Int("day", dayNumber).Msg("day does not exists") + // return false, fmt.Errorf("day %d does not exist", dayNumber) + // } + // ok = false + // for _, time := range p.semesterConfig.Starttimes { + // if time.Number == timeNumber { + // ok = true + // break + // } + // } + // if !ok { + // log.Error().Int("time", timeNumber).Msg("time does not exists") + // return false, fmt.Errorf("time %d does not exist", timeNumber) + // } + + // // check if examGroup exists + // _, err := p.ExamGroup(ctx, examGroupCode) + // if err != nil { + // log.Error().Err(err).Int("examGroupCode", examGroupCode).Msg("exam group does not exist") + // } + + // // check if slot is allowed + // allowedSlots, err := p.AllowedSlots(ctx, examGroupCode) + // if err != nil { + // log.Error().Err(err).Int("examGroupCode", examGroupCode).Msg("cannot get allowed slots") + // } + // slotIsAllowed := false + + // for _, slot := range allowedSlots { + // if slot.DayNumber == dayNumber && slot.SlotNumber == timeNumber { + // slotIsAllowed = true + // break + // } + // } + // if !slotIsAllowed { + // log.Debug().Int("day", dayNumber).Int("time", timeNumber).Int("examGroupCode", examGroupCode). + // Msg("slot is not allowed") + // return false, fmt.Errorf("slot (%d,%d) is not allowed for exam group %d", + // dayNumber, timeNumber, examGroupCode) + // } + + // return p.dbClient.AddExamToSlot(ctx, dayNumber, timeNumber, examGroupCode) } func (p *Plexams) RmExamGroupFromSlot(ctx context.Context, examGroupCode int) (bool, error) { diff --git a/plexams/plannedExams.go b/plexams/plannedExams.go index 88ee19f..4640fd0 100644 --- a/plexams/plannedExams.go +++ b/plexams/plannedExams.go @@ -46,20 +46,22 @@ func (p *Plexams) PlannedExamsForProgram(ctx context.Context, program string) ([ log.Debug().Int("ancode", plannedExam.Ancode).Msg("found connected exam") - slot, err := p.SlotForAncode(ctx, plannedExam.Ancode) - if err != nil { - log.Error().Err(err).Int("ancode", plannedExam.Ancode).Msg("cannot get slot for ancode") - return nil, err - } - if slot != nil { - // plannedExam.DateTime = p.getTimeForSlot(slot.DayNumber, slot.SlotNumber) // FIXME: new planned exam - } + // slot, err := p.SlotForAncode(ctx, plannedExam.Ancode) + // if err != nil { + // log.Error().Err(err).Int("ancode", plannedExam.Ancode).Msg("cannot get slot for ancode") + // return nil, err + // } + // if slot != nil { + // // plannedExam.DateTime = p.getTimeForSlot(slot.DayNumber, slot.SlotNumber) // FIXME: new planned exam + // } plannedExams = append(plannedExams, plannedExam) } return plannedExams, nil } +// TODO: needed? +// nolint func (p *Plexams) getTimeForSlot(dayNumber, slotNumber int) *time.Time { for _, slot := range p.semesterConfig.Slots { if slot.DayNumber == dayNumber && slot.SlotNumber == slotNumber { From 1c39f23baa6e9e8c843f4a57dfd1c264da1dc4d0 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Fri, 1 Dec 2023 22:19:15 +0100 Subject: [PATCH 39/78] more planning --- cmd/info.go | 3 + cmd/plan.go | 62 +- db/plan.go | 59 +- db/primuss_exam.go | 24 +- db/primuss_studentregs.go | 20 + graph/exam.graphqls | 3 + graph/exam.resolvers.go | 10 + graph/generated/generated.go | 1634 +++++++++++++++++++++++++--------- graph/model/models_gen.go | 14 +- graph/plan.graphqls | 4 +- graph/plan.resolvers.go | 4 +- graph/primuss.graphqls | 24 +- graph/primuss.resolvers.go | 16 + graph/query.graphqls | 1 - graph/query.resolvers.go | 5 - plexams/pdfDraft.go | 14 +- plexams/plan.go | 94 +- plexams/plan_examgroups.go | 16 +- plexams/plannedExams.go | 113 ++- plexams/samename.go | 46 + plexams/validate.go | 92 +- 21 files changed, 1651 insertions(+), 607 deletions(-) create mode 100644 graph/primuss.resolvers.go create mode 100644 plexams/samename.go diff --git a/cmd/info.go b/cmd/info.go index 92d447f..eebcbe9 100644 --- a/cmd/info.go +++ b/cmd/info.go @@ -16,6 +16,7 @@ var ( Use: "info [subcommand]", Short: "get info", Long: `Get info. +samename --- exams with same module name goslots --- info about slots for GO/GN request-rooms --- which rooms to request stats --- get statistics @@ -26,6 +27,8 @@ exams-for-student name --- get exams for student.`, Run: func(cmd *cobra.Command, args []string) { p := initPlexamsConfig() switch args[0] { + case "samename": + p.PrintSameName() case "goslots": err := plexams.PrintGOSlots(p.GetSemesterConfig().Slots, p.GetGoSlots()) if err != nil { diff --git a/cmd/plan.go b/cmd/plan.go index 728d40e..7fa74a5 100644 --- a/cmd/plan.go +++ b/cmd/plan.go @@ -17,8 +17,8 @@ var ( Long: `Manipulate the plan. move-to ancode day slot --- move [ancode] to [day number] [slot number] change-room ancode oldroom newroom --- change room for [ancode] from [oldroom] to [newroom] - lock-examgroup groupcode --- lock exam group to slot - unlock-examgroup groupcode --- unlock / allow moving + lock-exam ancode --- lock exam to slot + unlock-exam ancode --- unlock / allow moving remove-unlocked --- remove all unlocked exam groups from the plan lock --- lock the whole plan`, Args: cobra.MinimumNArgs(1), @@ -50,6 +50,24 @@ var ( fmt.Printf("successfully moved exam %d to (%d,%d)\n", ancode, day, slot) } + case "fixslotsindb": + planEntries, err := plexams.PlanEntries(context.TODO()) + if err != nil { + log.Fatal("cannot get plan entries") + } + + for i, planEntry := range planEntries { + fmt.Printf("%2d. fixing %v", i+1, planEntry) + success, err := plexams.AddExamToSlot(context.Background(), planEntry.Ancode, planEntry.DayNumber, planEntry.SlotNumber) + if err != nil { + fmt.Printf("error: %v\n", err) + os.Exit(1) + } + if success { + fmt.Println(" ... success") + } + } + case "change-room": if len(args) < 4 { log.Fatal("need ancode, old room and new room names") @@ -69,50 +87,38 @@ var ( fmt.Printf("successfully moved exam %d from %s to %s\n", ancode, oldRoom, newRoom) } - case "lock-examgroup": + case "lock-exam": if len(args) < 2 { - log.Fatal("need exam group code") + log.Fatal("need ancode") } - examGroupCode, err := strconv.Atoi(args[1]) + ancode, err := strconv.Atoi(args[1]) if err != nil { log.Fatalf("cannot convert %s to int", args[1]) } - planEntry, examGroup, err := plexams.LockExamGroup(context.Background(), examGroupCode) + planEntry, exam, err := plexams.LockExam(context.Background(), ancode) if err != nil { os.Exit(1) } - if planEntry != nil { - fmt.Printf("successfully locked exam group %d to slot (%d,%d)\n", - planEntry.Ancode, planEntry.DayNumber, planEntry.SlotNumber) - } - if examGroup != nil { - for _, exam := range examGroup.Exams { - fmt.Printf(" - %d. %s, %s\n", - exam.Exam.Ancode, exam.Exam.ZpaExam.MainExamer, exam.Exam.ZpaExam.Module) - } + if planEntry != nil && exam != nil { + fmt.Printf("successfully locked exam %d. %s, %s to slot (%d,%d)\n", + exam.Ancode, exam.ZpaExam.MainExamer, exam.ZpaExam.Module, planEntry.DayNumber, planEntry.SlotNumber) } - case "unlock-examgroup": + case "unlock-exam": if len(args) < 2 { - log.Fatal("need exam group code") + log.Fatal("need ancode") } - examGroupCode, err := strconv.Atoi(args[1]) + ancode, err := strconv.Atoi(args[1]) if err != nil { log.Fatalf("cannot convert %s to int", args[1]) } - planEntry, examGroup, err := plexams.UnlockExamGroup(context.Background(), examGroupCode) + planEntry, exam, err := plexams.UnlockExam(context.Background(), ancode) if err != nil { os.Exit(1) } - if planEntry != nil { - fmt.Printf("successfully unlocked exam group %d to slot (%d,%d)\n", - planEntry.Ancode, planEntry.DayNumber, planEntry.SlotNumber) - } - if examGroup != nil { - for _, exam := range examGroup.Exams { - fmt.Printf(" - %d. %s, %s\n", - exam.Exam.Ancode, exam.Exam.ZpaExam.MainExamer, exam.Exam.ZpaExam.Module) - } + if planEntry != nil && exam != nil { + fmt.Printf("successfully unlocked exam %d. %s, %s from slot (%d,%d)\n", + exam.Ancode, exam.ZpaExam.MainExamer, exam.ZpaExam.Module, planEntry.DayNumber, planEntry.SlotNumber) } case "remove-unlocked": diff --git a/db/plan.go b/db/plan.go index 4116775..9bcc219 100644 --- a/db/plan.go +++ b/db/plan.go @@ -53,7 +53,7 @@ func (db *DB) RmExamGroupFromSlot(ctx context.Context, ancode int) (bool, error) return true, nil } -func (db *DB) GetExamsInSlot(ctx context.Context, day int, time int) ([]*model.GeneratedExam, error) { +func (db *DB) GetExamsInSlot(ctx context.Context, day int, time int) ([]*model.PlannedExam, error) { collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) filter := bson.M{ @@ -78,20 +78,27 @@ func (db *DB) GetExamsInSlot(ctx context.Context, day int, time int) ([]*model.G return nil, err } - exams := make([]*model.GeneratedExam, 0, len(planEntries)) + exams := make([]*model.PlannedExam, 0, len(planEntries)) for _, planEntry := range planEntries { exam, err := db.GetGeneratedExam(ctx, planEntry.Ancode) if err != nil { log.Error().Err(err).Int("ancode", planEntry.Ancode).Msg("cannot get exam") return nil, err } - exams = append(exams, exam) + exams = append(exams, &model.PlannedExam{ + Ancode: exam.Ancode, + ZpaExam: exam.ZpaExam, + PrimussExams: exam.PrimussExams, + Constraints: exam.Constraints, + Conflicts: exam.Conflicts, + StudentRegsCount: exam.StudentRegsCount, + PlanEntry: planEntry, + }) } return exams, nil } -// Deprecated: rm me func (db *DB) PlanEntries(ctx context.Context) ([]*model.PlanEntry, error) { collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) @@ -103,17 +110,11 @@ func (db *DB) PlanEntries(ctx context.Context) ([]*model.PlanEntry, error) { defer cur.Close(ctx) planEntries := make([]*model.PlanEntry, 0) - for cur.Next(ctx) { - var planEntry model.PlanEntry - - err := cur.Decode(&planEntry) - if err != nil { - log.Error().Err(err).Str("collection", collectionNamePlan).Interface("cur", cur). - Msg("Cannot decode to plan entry") - return nil, err - } - - planEntries = append(planEntries, &planEntry) + err = cur.All(ctx, &planEntries) + if err != nil { + log.Error().Err(err).Str("collection", collectionNamePlan). + Msg("Cannot decode to plan entries") + return nil, err } return planEntries, nil @@ -279,48 +280,48 @@ func (db *DB) PlanAncodeEntries(ctx context.Context) ([]*model.PlanEntry, error) return planAncodeEntries, nil } -func (db *DB) LockExamGroup(ctx context.Context, examGroupCode int) (*model.PlanEntry, error) { - _, err := db.PlanEntryForExamGroup(ctx, examGroupCode) +func (db *DB) LockExam(ctx context.Context, ancode int) (*model.PlanEntry, error) { + _, err := db.PlanEntry(ctx, ancode) if err != nil { - log.Error().Err(err).Int("exam group code", examGroupCode). + log.Error().Err(err).Int("ancodecode", ancode). Msg("cannot find plan entry") return nil, err } collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) - filter := bson.D{{Key: "examgroupcode", Value: examGroupCode}} + filter := bson.D{{Key: "ancode", Value: ancode}} update := bson.D{{Key: "$set", Value: bson.D{{Key: "locked", Value: true}}}} _, err = collection.UpdateOne(ctx, filter, update) if err != nil { - log.Error().Err(err).Int("examgroupcode", examGroupCode). - Msg("cannot lock exam group to slot") + log.Error().Err(err).Int("ancode", ancode). + Msg("cannot lock exam to slot") return nil, err } - return db.PlanEntryForExamGroup(ctx, examGroupCode) + return db.PlanEntry(ctx, ancode) } -func (db *DB) UnlockExamGroup(ctx context.Context, examGroupCode int) (*model.PlanEntry, error) { - _, err := db.PlanEntryForExamGroup(ctx, examGroupCode) +func (db *DB) UnlockExam(ctx context.Context, ancode int) (*model.PlanEntry, error) { + _, err := db.PlanEntry(ctx, ancode) if err != nil { - log.Error().Err(err).Int("exam group code", examGroupCode). + log.Error().Err(err).Int("ancode", ancode). Msg("cannot find plan entry") return nil, err } collection := db.Client.Database(db.databaseName).Collection(collectionNamePlan) - filter := bson.D{{Key: "examgroupcode", Value: examGroupCode}} + filter := bson.D{{Key: "ancode", Value: ancode}} update := bson.D{{Key: "$set", Value: bson.D{{Key: "locked", Value: false}}}} _, err = collection.UpdateOne(ctx, filter, update) if err != nil { - log.Error().Err(err).Int("examgroupcode", examGroupCode). - Msg("cannot unlock exam group") + log.Error().Err(err).Int("ancode", ancode). + Msg("cannot unlock exam ") return nil, err } - return db.PlanEntryForExamGroup(ctx, examGroupCode) + return db.PlanEntry(ctx, ancode) } func (db *DB) ExamIsLocked(ctx context.Context, ancode int) bool { diff --git a/db/primuss_exam.go b/db/primuss_exam.go index 3aa0479..54b630a 100644 --- a/db/primuss_exam.go +++ b/db/primuss_exam.go @@ -90,11 +90,31 @@ func (db *DB) GetPrimussExams(ctx context.Context) ([]*model.PrimussExamByProgra for _, program := range programs { exams, err := db.getPrimussExams(ctx, program) if err != nil { - return primussExams, err + return nil, err } + + examsWithCount := make([]*model.PrimussExamWithCount, 0, len(exams)) + for _, exam := range exams { + sum, err := db.GetStudentRegsCount(ctx, program, exam.AnCode) + if err != nil { + log.Error().Err(err).Str("program", program).Int("ancode", exam.AnCode). + Msg("cannot get student regs sum") + } + + examsWithCount = append(examsWithCount, &model.PrimussExamWithCount{ + Ancode: exam.AnCode, + Module: exam.Module, + MainExamer: exam.MainExamer, + Program: exam.Program, + ExamType: exam.ExamType, + Presence: exam.Presence, + StudentRegsCount: sum, + }) + } + primussExams = append(primussExams, &model.PrimussExamByProgram{ Program: program, - Exams: exams, + Exams: examsWithCount, }) } diff --git a/db/primuss_studentregs.go b/db/primuss_studentregs.go index ef62d9a..9a80416 100644 --- a/db/primuss_studentregs.go +++ b/db/primuss_studentregs.go @@ -7,6 +7,7 @@ import ( "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) @@ -203,6 +204,25 @@ func (db *DB) CheckStudentRegsCount(ctx context.Context, program string, ancode, return true } +func (db *DB) GetStudentRegsCount(ctx context.Context, program string, ancode int) (int, error) { + // log.Debug().Str("collectionName", collectionName).Int("ancode", ancode).Int("studentRegsCount", studentRegsCount). + // Msg("checking count") + collection := db.getCollection(program, Counts) + var result Count + res := collection.FindOne(ctx, bson.D{{Key: "AnCo", Value: ancode}, {Key: "Sum", Value: bson.D{{Key: "$ne", Value: ""}}}}) + if res.Err() == mongo.ErrNoDocuments { + return 0, nil + } + err := res.Decode(&result) + if err != nil { + log.Error().Err(err).Str("semester", db.semester).Str("program", program). + Int("ancode", ancode).Msg("error finding count") + return -1, err + } + + return result.Sum, nil +} + func (db *DB) ChangeAncodeInStudentRegsCount(ctx context.Context, program string, ancode, newAncode int) error { collection := db.getCollection(program, Counts) diff --git a/graph/exam.graphqls b/graph/exam.graphqls index 3a3dea6..ed83763 100644 --- a/graph/exam.graphqls +++ b/graph/exam.graphqls @@ -7,6 +7,9 @@ extend type Query { generatedExams: [GeneratedExam!]! generatedExam(ancode: Int!): GeneratedExam + plannedExams: [PlannedExam!]! + plannedExam(ancode: Int!): PlannedExam + conflictingAncodes(ancode: Int!): [Conflict!] exam(ancode: Int!): Exam diff --git a/graph/exam.resolvers.go b/graph/exam.resolvers.go index c55bb58..3f7e03d 100644 --- a/graph/exam.resolvers.go +++ b/graph/exam.resolvers.go @@ -35,6 +35,16 @@ func (r *queryResolver) GeneratedExam(ctx context.Context, ancode int) (*model.G return r.plexams.GeneratedExam(ctx, ancode) } +// PlannedExams is the resolver for the plannedExams field. +func (r *queryResolver) PlannedExams(ctx context.Context) ([]*model.PlannedExam, error) { + return r.plexams.PlannedExams(ctx) +} + +// PlannedExam is the resolver for the plannedExam field. +func (r *queryResolver) PlannedExam(ctx context.Context, ancode int) (*model.PlannedExam, error) { + return r.plexams.PlannedExam(ctx, ancode) +} + // ConflictingAncodes is the resolver for the conflictingAncodes field. func (r *queryResolver) ConflictingAncodes(ctx context.Context, ancode int) ([]*model.Conflict, error) { return r.plexams.ConflictingAncodes(ctx, ancode) diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 07d7f6e..7ba8593 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -377,6 +377,16 @@ type ComplexityRoot struct { Program func(childComplexity int) int } + PrimussExamWithCount struct { + Ancode func(childComplexity int) int + ExamType func(childComplexity int) int + MainExamer func(childComplexity int) int + Module func(childComplexity int) int + Presence func(childComplexity int) int + Program func(childComplexity int) int + StudentRegsCount func(childComplexity int) int + } + Query struct { AdditionalExams func(childComplexity int) int AllProgramsInPlan func(childComplexity int) int @@ -414,6 +424,8 @@ type ComplexityRoot struct { Ntas func(childComplexity int) int NtasWithRegs func(childComplexity int) int NtasWithRegsByTeacher func(childComplexity int) int + PlannedExam func(childComplexity int, ancode int) int + PlannedExams func(childComplexity int) int PlannedExamsInSlot func(childComplexity int, day int, time int) int PlannedRoomNames func(childComplexity int) int PlannedRoomNamesInSlot func(childComplexity int, day int, time int) int @@ -667,7 +679,6 @@ type QueryResolver interface { Semester(ctx context.Context) (*model.Semester, error) SemesterConfig(ctx context.Context) (*model.SemesterConfig, error) AdditionalExams(ctx context.Context) ([]*model.AdditionalExam, error) - PrimussExams(ctx context.Context) ([]*model.PrimussExamByProgram, error) PrimussExam(ctx context.Context, program string, ancode int) (*model.PrimussExam, error) PrimussExamsForAnCode(ctx context.Context, ancode int) ([]*model.PrimussExam, error) StudentRegsForProgram(ctx context.Context, program string) ([]*model.StudentReg, error) @@ -698,6 +709,8 @@ type QueryResolver interface { ExternalExams(ctx context.Context) ([]*model.ExternalExam, error) GeneratedExams(ctx context.Context) ([]*model.GeneratedExam, error) GeneratedExam(ctx context.Context, ancode int) (*model.GeneratedExam, error) + PlannedExams(ctx context.Context) ([]*model.PlannedExam, error) + PlannedExam(ctx context.Context, ancode int) (*model.PlannedExam, error) ConflictingAncodes(ctx context.Context, ancode int) ([]*model.Conflict, error) Exam(ctx context.Context, ancode int) (*model.Exam, error) Exams(ctx context.Context) ([]*model.Exam, error) @@ -706,10 +719,11 @@ type QueryResolver interface { AllProgramsInPlan(ctx context.Context) ([]string, error) AncodesInPlan(ctx context.Context) ([]int, error) ExamerInPlan(ctx context.Context) ([]*model.ExamerInPlan, error) - ExamsInSlot(ctx context.Context, day int, time int) ([]*model.GeneratedExam, error) - ExamsWithoutSlot(ctx context.Context) ([]*model.GeneratedExam, error) + ExamsInSlot(ctx context.Context, day int, time int) ([]*model.PlannedExam, error) + ExamsWithoutSlot(ctx context.Context) ([]*model.PlannedExam, error) AllowedSlots(ctx context.Context, ancode int) ([]*model.Slot, error) AwkwardSlots(ctx context.Context, ancode int) ([]*model.Slot, error) + PrimussExams(ctx context.Context) ([]*model.PrimussExamByProgram, error) StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, error) StudentsByName(ctx context.Context, regex string) ([]*model.Student, error) Students(ctx context.Context) ([]*model.Student, error) @@ -2285,6 +2299,55 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PrimussExamByProgram.Program(childComplexity), true + case "PrimussExamWithCount.ancode": + if e.complexity.PrimussExamWithCount.Ancode == nil { + break + } + + return e.complexity.PrimussExamWithCount.Ancode(childComplexity), true + + case "PrimussExamWithCount.examType": + if e.complexity.PrimussExamWithCount.ExamType == nil { + break + } + + return e.complexity.PrimussExamWithCount.ExamType(childComplexity), true + + case "PrimussExamWithCount.mainExamer": + if e.complexity.PrimussExamWithCount.MainExamer == nil { + break + } + + return e.complexity.PrimussExamWithCount.MainExamer(childComplexity), true + + case "PrimussExamWithCount.module": + if e.complexity.PrimussExamWithCount.Module == nil { + break + } + + return e.complexity.PrimussExamWithCount.Module(childComplexity), true + + case "PrimussExamWithCount.presence": + if e.complexity.PrimussExamWithCount.Presence == nil { + break + } + + return e.complexity.PrimussExamWithCount.Presence(childComplexity), true + + case "PrimussExamWithCount.program": + if e.complexity.PrimussExamWithCount.Program == nil { + break + } + + return e.complexity.PrimussExamWithCount.Program(childComplexity), true + + case "PrimussExamWithCount.studentRegsCount": + if e.complexity.PrimussExamWithCount.StudentRegsCount == nil { + break + } + + return e.complexity.PrimussExamWithCount.StudentRegsCount(childComplexity), true + case "Query.additionalExams": if e.complexity.Query.AdditionalExams == nil { break @@ -2607,6 +2670,25 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.NtasWithRegsByTeacher(childComplexity), true + case "Query.plannedExam": + if e.complexity.Query.PlannedExam == nil { + break + } + + args, err := ec.field_Query_plannedExam_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.PlannedExam(childComplexity, args["ancode"].(int)), true + + case "Query.plannedExams": + if e.complexity.Query.PlannedExams == nil { + break + } + + return e.complexity.Query.PlannedExams(childComplexity), true + case "Query.plannedExamsInSlot": if e.complexity.Query.PlannedExamsInSlot == nil { break @@ -3768,6 +3850,9 @@ var sources = []*ast.Source{ generatedExams: [GeneratedExam!]! generatedExam(ancode: Int!): GeneratedExam + plannedExams: [PlannedExam!]! + plannedExam(ancode: Int!): PlannedExam + conflictingAncodes(ancode: Int!): [Conflict!] exam(ancode: Int!): Exam @@ -4067,8 +4152,8 @@ type NTAWithRegsByExam { ancodesInPlan: [Int!] examerInPlan: [ExamerInPlan!] - examsInSlot(day: Int!, time: Int!): [GeneratedExam!] - examsWithoutSlot: [GeneratedExam!]! + examsInSlot(day: Int!, time: Int!): [PlannedExam!] + examsWithoutSlot: [PlannedExam!]! allowedSlots(ancode: Int!): [Slot!] awkwardSlots(ancode: Int!): [Slot!]! # slots before or after a conflict @@ -4151,7 +4236,11 @@ type PlanEntry { locked: Boolean! } `, BuiltIn: false}, - {Name: "../primuss.graphqls", Input: `type PrimussExam { + {Name: "../primuss.graphqls", Input: `extend type Query { + primussExams: [PrimussExamByProgram] +} + +type PrimussExam { ancode: Int! module: String! mainExamer: String! @@ -4167,20 +4256,30 @@ type EnhancedPrimussExam { ntas: [NTA!]! } -type PrimussExamAncode { +type PrimussExamWithCount { ancode: Int! + module: String! + mainExamer: String! program: String! - numberOfStuds: Int! + examType: String! + presence: String! + studentRegsCount: Int! } -input PrimussExamInput { +type PrimussExamByProgram { + program: String! + exams: [PrimussExamWithCount!]! +} + +type PrimussExamAncode { ancode: Int! program: String! + numberOfStuds: Int! } -type PrimussExamByProgram { +input PrimussExamInput { + ancode: Int! program: String! - exams: [PrimussExam!]! } type StudentReg { @@ -4224,7 +4323,6 @@ type ConflictsPerProgramAncode { # Additional Exams additionalExams: [AdditionalExam!]! # Primuss - primussExams: [PrimussExamByProgram] primussExam(program: String!, ancode: Int!): PrimussExam! primussExamsForAnCode(ancode: Int!): [PrimussExam!] studentRegsForProgram(program: String!): [StudentReg!] @@ -5082,6 +5180,21 @@ func (ec *executionContext) field_Query_nta_args(ctx context.Context, rawArgs ma return args, nil } +func (ec *executionContext) field_Query_plannedExam_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 int + if tmp, ok := rawArgs["ancode"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("ancode")) + arg0, err = ec.unmarshalNInt2int(ctx, tmp) + if err != nil { + return nil, err + } + } + args["ancode"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query_plannedExamsInSlot_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -15522,9 +15635,9 @@ func (ec *executionContext) _PrimussExamByProgram_exams(ctx context.Context, fie } return graphql.Null } - res := resTmp.([]*model.PrimussExam) + res := resTmp.([]*model.PrimussExamWithCount) fc.Result = res - return ec.marshalNPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamᚄ(ctx, field.Selections, res) + return ec.marshalNPrimussExamWithCount2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamWithCountᚄ(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_PrimussExamByProgram_exams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -15536,19 +15649,329 @@ func (ec *executionContext) fieldContext_PrimussExamByProgram_exams(ctx context. Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { case "ancode": - return ec.fieldContext_PrimussExam_ancode(ctx, field) + return ec.fieldContext_PrimussExamWithCount_ancode(ctx, field) case "module": - return ec.fieldContext_PrimussExam_module(ctx, field) + return ec.fieldContext_PrimussExamWithCount_module(ctx, field) case "mainExamer": - return ec.fieldContext_PrimussExam_mainExamer(ctx, field) + return ec.fieldContext_PrimussExamWithCount_mainExamer(ctx, field) case "program": - return ec.fieldContext_PrimussExam_program(ctx, field) + return ec.fieldContext_PrimussExamWithCount_program(ctx, field) case "examType": - return ec.fieldContext_PrimussExam_examType(ctx, field) + return ec.fieldContext_PrimussExamWithCount_examType(ctx, field) case "presence": - return ec.fieldContext_PrimussExam_presence(ctx, field) + return ec.fieldContext_PrimussExamWithCount_presence(ctx, field) + case "studentRegsCount": + return ec.fieldContext_PrimussExamWithCount_studentRegsCount(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type PrimussExam", field.Name) + return nil, fmt.Errorf("no field named %q was found under type PrimussExamWithCount", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _PrimussExamWithCount_ancode(ctx context.Context, field graphql.CollectedField, obj *model.PrimussExamWithCount) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PrimussExamWithCount_ancode(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Ancode, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PrimussExamWithCount_ancode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PrimussExamWithCount", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PrimussExamWithCount_module(ctx context.Context, field graphql.CollectedField, obj *model.PrimussExamWithCount) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PrimussExamWithCount_module(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Module, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PrimussExamWithCount_module(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PrimussExamWithCount", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PrimussExamWithCount_mainExamer(ctx context.Context, field graphql.CollectedField, obj *model.PrimussExamWithCount) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PrimussExamWithCount_mainExamer(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.MainExamer, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PrimussExamWithCount_mainExamer(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PrimussExamWithCount", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PrimussExamWithCount_program(ctx context.Context, field graphql.CollectedField, obj *model.PrimussExamWithCount) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PrimussExamWithCount_program(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Program, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PrimussExamWithCount_program(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PrimussExamWithCount", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PrimussExamWithCount_examType(ctx context.Context, field graphql.CollectedField, obj *model.PrimussExamWithCount) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PrimussExamWithCount_examType(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ExamType, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PrimussExamWithCount_examType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PrimussExamWithCount", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PrimussExamWithCount_presence(ctx context.Context, field graphql.CollectedField, obj *model.PrimussExamWithCount) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PrimussExamWithCount_presence(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Presence, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PrimussExamWithCount_presence(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PrimussExamWithCount", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PrimussExamWithCount_studentRegsCount(ctx context.Context, field graphql.CollectedField, obj *model.PrimussExamWithCount) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PrimussExamWithCount_studentRegsCount(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.StudentRegsCount, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PrimussExamWithCount_studentRegsCount(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PrimussExamWithCount", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") }, } return fc, nil @@ -15869,53 +16292,6 @@ func (ec *executionContext) fieldContext_Query_additionalExams(ctx context.Conte return fc, nil } -func (ec *executionContext) _Query_primussExams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_primussExams(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().PrimussExams(rctx) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.([]*model.PrimussExamByProgram) - fc.Result = res - return ec.marshalOPrimussExamByProgram2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamByProgram(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_primussExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "program": - return ec.fieldContext_PrimussExamByProgram_program(ctx, field) - case "exams": - return ec.fieldContext_PrimussExamByProgram_exams(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type PrimussExamByProgram", field.Name) - }, - } - return fc, nil -} - func (ec *executionContext) _Query_primussExam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_primussExam(ctx, field) if err != nil { @@ -17668,6 +18044,134 @@ func (ec *executionContext) fieldContext_Query_generatedExam(ctx context.Context return fc, nil } +func (ec *executionContext) _Query_plannedExams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_plannedExams(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().PlannedExams(rctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.PlannedExam) + fc.Result = res + return ec.marshalNPlannedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExamᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_plannedExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "ancode": + return ec.fieldContext_PlannedExam_ancode(ctx, field) + case "zpaExam": + return ec.fieldContext_PlannedExam_zpaExam(ctx, field) + case "primussExams": + return ec.fieldContext_PlannedExam_primussExams(ctx, field) + case "constraints": + return ec.fieldContext_PlannedExam_constraints(ctx, field) + case "conflicts": + return ec.fieldContext_PlannedExam_conflicts(ctx, field) + case "studentRegsCount": + return ec.fieldContext_PlannedExam_studentRegsCount(ctx, field) + case "planEntry": + return ec.fieldContext_PlannedExam_planEntry(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type PlannedExam", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Query_plannedExam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_plannedExam(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().PlannedExam(rctx, fc.Args["ancode"].(int)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.PlannedExam) + fc.Result = res + return ec.marshalOPlannedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExam(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_plannedExam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "ancode": + return ec.fieldContext_PlannedExam_ancode(ctx, field) + case "zpaExam": + return ec.fieldContext_PlannedExam_zpaExam(ctx, field) + case "primussExams": + return ec.fieldContext_PlannedExam_primussExams(ctx, field) + case "constraints": + return ec.fieldContext_PlannedExam_constraints(ctx, field) + case "conflicts": + return ec.fieldContext_PlannedExam_conflicts(ctx, field) + case "studentRegsCount": + return ec.fieldContext_PlannedExam_studentRegsCount(ctx, field) + case "planEntry": + return ec.fieldContext_PlannedExam_planEntry(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type PlannedExam", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_plannedExam_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Query_conflictingAncodes(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_conflictingAncodes(ctx, field) if err != nil { @@ -18144,9 +18648,9 @@ func (ec *executionContext) _Query_examsInSlot(ctx context.Context, field graphq if resTmp == nil { return graphql.Null } - res := resTmp.([]*model.GeneratedExam) + res := resTmp.([]*model.PlannedExam) fc.Result = res - return ec.marshalOGeneratedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExamᚄ(ctx, field.Selections, res) + return ec.marshalOPlannedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExamᚄ(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Query_examsInSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -18158,19 +18662,21 @@ func (ec *executionContext) fieldContext_Query_examsInSlot(ctx context.Context, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { case "ancode": - return ec.fieldContext_GeneratedExam_ancode(ctx, field) + return ec.fieldContext_PlannedExam_ancode(ctx, field) case "zpaExam": - return ec.fieldContext_GeneratedExam_zpaExam(ctx, field) + return ec.fieldContext_PlannedExam_zpaExam(ctx, field) case "primussExams": - return ec.fieldContext_GeneratedExam_primussExams(ctx, field) + return ec.fieldContext_PlannedExam_primussExams(ctx, field) case "constraints": - return ec.fieldContext_GeneratedExam_constraints(ctx, field) + return ec.fieldContext_PlannedExam_constraints(ctx, field) case "conflicts": - return ec.fieldContext_GeneratedExam_conflicts(ctx, field) + return ec.fieldContext_PlannedExam_conflicts(ctx, field) case "studentRegsCount": - return ec.fieldContext_GeneratedExam_studentRegsCount(ctx, field) + return ec.fieldContext_PlannedExam_studentRegsCount(ctx, field) + case "planEntry": + return ec.fieldContext_PlannedExam_planEntry(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type GeneratedExam", field.Name) + return nil, fmt.Errorf("no field named %q was found under type PlannedExam", field.Name) }, } defer func() { @@ -18213,9 +18719,9 @@ func (ec *executionContext) _Query_examsWithoutSlot(ctx context.Context, field g } return graphql.Null } - res := resTmp.([]*model.GeneratedExam) + res := resTmp.([]*model.PlannedExam) fc.Result = res - return ec.marshalNGeneratedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExamᚄ(ctx, field.Selections, res) + return ec.marshalNPlannedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExamᚄ(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Query_examsWithoutSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -18227,19 +18733,21 @@ func (ec *executionContext) fieldContext_Query_examsWithoutSlot(ctx context.Cont Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { case "ancode": - return ec.fieldContext_GeneratedExam_ancode(ctx, field) + return ec.fieldContext_PlannedExam_ancode(ctx, field) case "zpaExam": - return ec.fieldContext_GeneratedExam_zpaExam(ctx, field) + return ec.fieldContext_PlannedExam_zpaExam(ctx, field) case "primussExams": - return ec.fieldContext_GeneratedExam_primussExams(ctx, field) + return ec.fieldContext_PlannedExam_primussExams(ctx, field) case "constraints": - return ec.fieldContext_GeneratedExam_constraints(ctx, field) + return ec.fieldContext_PlannedExam_constraints(ctx, field) case "conflicts": - return ec.fieldContext_GeneratedExam_conflicts(ctx, field) + return ec.fieldContext_PlannedExam_conflicts(ctx, field) case "studentRegsCount": - return ec.fieldContext_GeneratedExam_studentRegsCount(ctx, field) + return ec.fieldContext_PlannedExam_studentRegsCount(ctx, field) + case "planEntry": + return ec.fieldContext_PlannedExam_planEntry(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type GeneratedExam", field.Name) + return nil, fmt.Errorf("no field named %q was found under type PlannedExam", field.Name) }, } return fc, nil @@ -18368,6 +18876,53 @@ func (ec *executionContext) fieldContext_Query_awkwardSlots(ctx context.Context, return fc, nil } +func (ec *executionContext) _Query_primussExams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_primussExams(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().PrimussExams(rctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.PrimussExamByProgram) + fc.Result = res + return ec.marshalOPrimussExamByProgram2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamByProgram(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_primussExams(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "program": + return ec.fieldContext_PrimussExamByProgram_program(ctx, field) + case "exams": + return ec.fieldContext_PrimussExamByProgram_exams(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type PrimussExamByProgram", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _Query_studentByMtknr(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_studentByMtknr(ctx, field) if err != nil { @@ -29062,73 +29617,142 @@ func (ec *executionContext) _PrimussExam(ctx context.Context, sel ast.SelectionS return out } -var primussExamAncodeImplementors = []string{"PrimussExamAncode"} +var primussExamAncodeImplementors = []string{"PrimussExamAncode"} + +func (ec *executionContext) _PrimussExamAncode(ctx context.Context, sel ast.SelectionSet, obj *model.PrimussExamAncode) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, primussExamAncodeImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("PrimussExamAncode") + case "ancode": + out.Values[i] = ec._PrimussExamAncode_ancode(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "program": + out.Values[i] = ec._PrimussExamAncode_program(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "numberOfStuds": + out.Values[i] = ec._PrimussExamAncode_numberOfStuds(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var primussExamByProgramImplementors = []string{"PrimussExamByProgram"} + +func (ec *executionContext) _PrimussExamByProgram(ctx context.Context, sel ast.SelectionSet, obj *model.PrimussExamByProgram) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, primussExamByProgramImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("PrimussExamByProgram") + case "program": + out.Values[i] = ec._PrimussExamByProgram_program(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "exams": + out.Values[i] = ec._PrimussExamByProgram_exams(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var primussExamWithCountImplementors = []string{"PrimussExamWithCount"} -func (ec *executionContext) _PrimussExamAncode(ctx context.Context, sel ast.SelectionSet, obj *model.PrimussExamAncode) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, primussExamAncodeImplementors) +func (ec *executionContext) _PrimussExamWithCount(ctx context.Context, sel ast.SelectionSet, obj *model.PrimussExamWithCount) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, primussExamWithCountImplementors) out := graphql.NewFieldSet(fields) deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("PrimussExamAncode") + out.Values[i] = graphql.MarshalString("PrimussExamWithCount") case "ancode": - out.Values[i] = ec._PrimussExamAncode_ancode(ctx, field, obj) + out.Values[i] = ec._PrimussExamWithCount_ancode(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "program": - out.Values[i] = ec._PrimussExamAncode_program(ctx, field, obj) + case "module": + out.Values[i] = ec._PrimussExamWithCount_module(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "numberOfStuds": - out.Values[i] = ec._PrimussExamAncode_numberOfStuds(ctx, field, obj) + case "mainExamer": + out.Values[i] = ec._PrimussExamWithCount_mainExamer(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - default: - panic("unknown field " + strconv.Quote(field.Name)) - } - } - out.Dispatch(ctx) - if out.Invalids > 0 { - return graphql.Null - } - - atomic.AddInt32(&ec.deferred, int32(len(deferred))) - - for label, dfs := range deferred { - ec.processDeferredGroup(graphql.DeferredGroup{ - Label: label, - Path: graphql.GetPath(ctx), - FieldSet: dfs, - Context: ctx, - }) - } - - return out -} - -var primussExamByProgramImplementors = []string{"PrimussExamByProgram"} - -func (ec *executionContext) _PrimussExamByProgram(ctx context.Context, sel ast.SelectionSet, obj *model.PrimussExamByProgram) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, primussExamByProgramImplementors) - - out := graphql.NewFieldSet(fields) - deferred := make(map[string]*graphql.FieldSet) - for i, field := range fields { - switch field.Name { - case "__typename": - out.Values[i] = graphql.MarshalString("PrimussExamByProgram") case "program": - out.Values[i] = ec._PrimussExamByProgram_program(ctx, field, obj) + out.Values[i] = ec._PrimussExamWithCount_program(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "exams": - out.Values[i] = ec._PrimussExamByProgram_exams(ctx, field, obj) + case "examType": + out.Values[i] = ec._PrimussExamWithCount_examType(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "presence": + out.Values[i] = ec._PrimussExamWithCount_presence(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "studentRegsCount": + out.Values[i] = ec._PrimussExamWithCount_studentRegsCount(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } @@ -29302,25 +29926,6 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "primussExams": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_primussExams(ctx, field) - return res - } - - rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, - func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "primussExam": field := field @@ -29918,6 +30523,47 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "plannedExams": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_plannedExams(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "plannedExam": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_plannedExam(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "conflictingAncodes": field := field @@ -30155,6 +30801,25 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "primussExams": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_primussExams(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "studentByMtknr": field := field @@ -33284,7 +33949,140 @@ func (ec *executionContext) marshalNNTAExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexam if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNNTAExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAExam(ctx, sel, v[i]) + ret[i] = ec.marshalNNTAExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAExam(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNNTAExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAExam(ctx context.Context, sel ast.SelectionSet, v *model.NTAExam) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._NTAExam(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNNTAInput2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAInput(ctx context.Context, v interface{}) (model.NTAInput, error) { + res, err := ec.unmarshalInputNTAInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNNTAWithRegs2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.NTAWithRegs) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNNTAWithRegs2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegs(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNNTAWithRegs2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegs(ctx context.Context, sel ast.SelectionSet, v *model.NTAWithRegs) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._NTAWithRegs(ctx, sel, v) +} + +func (ec *executionContext) marshalNNTAWithRegsByExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsByExam(ctx context.Context, sel ast.SelectionSet, v *model.NTAWithRegsByExam) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._NTAWithRegsByExam(ctx, sel, v) +} + +func (ec *executionContext) marshalNNTAWithRegsByExamAndTeacher2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsByExamAndTeacher(ctx context.Context, sel ast.SelectionSet, v *model.NTAWithRegsByExamAndTeacher) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._NTAWithRegsByExamAndTeacher(ctx, sel, v) +} + +func (ec *executionContext) marshalNPlannedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PlannedExam) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNPlannedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExam(ctx, sel, v[i]) } if isLen1 { f(i) @@ -33304,22 +34102,31 @@ func (ec *executionContext) marshalNNTAExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexam return ret } -func (ec *executionContext) marshalNNTAExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAExam(ctx context.Context, sel ast.SelectionSet, v *model.NTAExam) graphql.Marshaler { +func (ec *executionContext) marshalNPlannedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExam(ctx context.Context, sel ast.SelectionSet, v *model.PlannedExam) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._NTAExam(ctx, sel, v) + return ec._PlannedExam(ctx, sel, v) } -func (ec *executionContext) unmarshalNNTAInput2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAInput(ctx context.Context, v interface{}) (model.NTAInput, error) { - res, err := ec.unmarshalInputNTAInput(ctx, v) - return res, graphql.ErrorOnPath(ctx, err) +func (ec *executionContext) marshalNPlannedExamWithNTA2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExamWithNta(ctx context.Context, sel ast.SelectionSet, v *model.PlannedExamWithNta) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._PlannedExamWithNTA(ctx, sel, v) } -func (ec *executionContext) marshalNNTAWithRegs2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.NTAWithRegs) graphql.Marshaler { +func (ec *executionContext) marshalNPrimussExam2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx context.Context, sel ast.SelectionSet, v model.PrimussExam) graphql.Marshaler { + return ec._PrimussExam(ctx, sel, &v) +} + +func (ec *executionContext) marshalNPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PrimussExam) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -33343,7 +34150,7 @@ func (ec *executionContext) marshalNNTAWithRegs2ᚕᚖgithubᚗcomᚋobcodeᚋpl if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNNTAWithRegs2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegs(ctx, sel, v[i]) + ret[i] = ec.marshalNPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx, sel, v[i]) } if isLen1 { f(i) @@ -33363,51 +34170,17 @@ func (ec *executionContext) marshalNNTAWithRegs2ᚕᚖgithubᚗcomᚋobcodeᚋpl return ret } -func (ec *executionContext) marshalNNTAWithRegs2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegs(ctx context.Context, sel ast.SelectionSet, v *model.NTAWithRegs) graphql.Marshaler { - if v == nil { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - return graphql.Null - } - return ec._NTAWithRegs(ctx, sel, v) -} - -func (ec *executionContext) marshalNNTAWithRegsByExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsByExam(ctx context.Context, sel ast.SelectionSet, v *model.NTAWithRegsByExam) graphql.Marshaler { - if v == nil { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - return graphql.Null - } - return ec._NTAWithRegsByExam(ctx, sel, v) -} - -func (ec *executionContext) marshalNNTAWithRegsByExamAndTeacher2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsByExamAndTeacher(ctx context.Context, sel ast.SelectionSet, v *model.NTAWithRegsByExamAndTeacher) graphql.Marshaler { - if v == nil { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - return graphql.Null - } - return ec._NTAWithRegsByExamAndTeacher(ctx, sel, v) -} - -func (ec *executionContext) marshalNPlannedExamWithNTA2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExamWithNta(ctx context.Context, sel ast.SelectionSet, v *model.PlannedExamWithNta) graphql.Marshaler { +func (ec *executionContext) marshalNPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx context.Context, sel ast.SelectionSet, v *model.PrimussExam) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._PlannedExamWithNTA(ctx, sel, v) -} - -func (ec *executionContext) marshalNPrimussExam2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx context.Context, sel ast.SelectionSet, v model.PrimussExam) graphql.Marshaler { - return ec._PrimussExam(ctx, sel, &v) + return ec._PrimussExam(ctx, sel, v) } -func (ec *executionContext) marshalNPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PrimussExam) graphql.Marshaler { +func (ec *executionContext) marshalNPrimussExamAncode2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncodeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PrimussExamAncode) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -33431,7 +34204,7 @@ func (ec *executionContext) marshalNPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋpl if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx, sel, v[i]) + ret[i] = ec.marshalNPrimussExamAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncode(ctx, sel, v[i]) } if isLen1 { f(i) @@ -33451,17 +34224,17 @@ func (ec *executionContext) marshalNPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋpl return ret } -func (ec *executionContext) marshalNPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx context.Context, sel ast.SelectionSet, v *model.PrimussExam) graphql.Marshaler { +func (ec *executionContext) marshalNPrimussExamAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncode(ctx context.Context, sel ast.SelectionSet, v *model.PrimussExamAncode) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._PrimussExam(ctx, sel, v) + return ec._PrimussExamAncode(ctx, sel, v) } -func (ec *executionContext) marshalNPrimussExamAncode2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncodeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PrimussExamAncode) graphql.Marshaler { +func (ec *executionContext) marshalNPrimussExamWithCount2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamWithCountᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PrimussExamWithCount) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -33485,7 +34258,7 @@ func (ec *executionContext) marshalNPrimussExamAncode2ᚕᚖgithubᚗcomᚋobcod if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNPrimussExamAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncode(ctx, sel, v[i]) + ret[i] = ec.marshalNPrimussExamWithCount2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamWithCount(ctx, sel, v[i]) } if isLen1 { f(i) @@ -33505,14 +34278,14 @@ func (ec *executionContext) marshalNPrimussExamAncode2ᚕᚖgithubᚗcomᚋobcod return ret } -func (ec *executionContext) marshalNPrimussExamAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncode(ctx context.Context, sel ast.SelectionSet, v *model.PrimussExamAncode) graphql.Marshaler { +func (ec *executionContext) marshalNPrimussExamWithCount2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamWithCount(ctx context.Context, sel ast.SelectionSet, v *model.PrimussExamWithCount) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._PrimussExamAncode(ctx, sel, v) + return ec._PrimussExamWithCount(ctx, sel, v) } func (ec *executionContext) marshalNRegWithError2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRegWithErrorᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.RegWithError) graphql.Marshaler { @@ -34973,197 +35746,7 @@ func (ec *executionContext) marshalOAnCode2ᚕᚖgithubᚗcomᚋobcodeᚋplexams if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalOAnCode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAnCode(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - - } - wg.Wait() - - return ret -} - -func (ec *executionContext) marshalOAnCode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAnCode(ctx context.Context, sel ast.SelectionSet, v *model.AnCode) graphql.Marshaler { - if v == nil { - return graphql.Null - } - return ec._AnCode(ctx, sel, v) -} - -func (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) { - res, err := graphql.UnmarshalBoolean(v) - return res, graphql.ErrorOnPath(ctx, err) -} - -func (ec *executionContext) marshalOBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { - res := graphql.MarshalBoolean(v) - return res -} - -func (ec *executionContext) unmarshalOBoolean2ᚖbool(ctx context.Context, v interface{}) (*bool, error) { - if v == nil { - return nil, nil - } - res, err := graphql.UnmarshalBoolean(v) - return &res, graphql.ErrorOnPath(ctx, err) -} - -func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast.SelectionSet, v *bool) graphql.Marshaler { - if v == nil { - return graphql.Null - } - res := graphql.MarshalBoolean(*v) - return res -} - -func (ec *executionContext) marshalOConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Conflict) graphql.Marshaler { - if v == nil { - return graphql.Null - } - ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } - for i := range v { - i := i - fc := &graphql.FieldContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithFieldContext(ctx, fc) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalNConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflict(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - - } - wg.Wait() - - for _, e := range ret { - if e == graphql.Null { - return graphql.Null - } - } - - return ret -} - -func (ec *executionContext) marshalOConflicts2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflicts(ctx context.Context, sel ast.SelectionSet, v *model.Conflicts) graphql.Marshaler { - if v == nil { - return graphql.Null - } - return ec._Conflicts(ctx, sel, v) -} - -func (ec *executionContext) marshalOConnectedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExam(ctx context.Context, sel ast.SelectionSet, v *model.ConnectedExam) graphql.Marshaler { - if v == nil { - return graphql.Null - } - return ec._ConnectedExam(ctx, sel, v) -} - -func (ec *executionContext) marshalOConstraints2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConstraints(ctx context.Context, sel ast.SelectionSet, v *model.Constraints) graphql.Marshaler { - if v == nil { - return graphql.Null - } - return ec._Constraints(ctx, sel, v) -} - -func (ec *executionContext) marshalOExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExam(ctx context.Context, sel ast.SelectionSet, v *model.Exam) graphql.Marshaler { - if v == nil { - return graphql.Null - } - return ec._Exam(ctx, sel, v) -} - -func (ec *executionContext) marshalOExamGroup2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroup(ctx context.Context, sel ast.SelectionSet, v []*model.ExamGroup) graphql.Marshaler { - if v == nil { - return graphql.Null - } - ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } - for i := range v { - i := i - fc := &graphql.FieldContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithFieldContext(ctx, fc) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalOExamGroup2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroup(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - - } - wg.Wait() - - return ret -} - -func (ec *executionContext) marshalOExamGroup2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExamGroup) graphql.Marshaler { - if v == nil { - return graphql.Null - } - ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } - for i := range v { - i := i - fc := &graphql.FieldContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithFieldContext(ctx, fc) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalNExamGroup2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroup(ctx, sel, v[i]) + ret[i] = ec.marshalOAnCode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAnCode(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35174,23 +35757,43 @@ func (ec *executionContext) marshalOExamGroup2ᚕᚖgithubᚗcomᚋobcodeᚋplex } wg.Wait() - for _, e := range ret { - if e == graphql.Null { - return graphql.Null - } + return ret +} + +func (ec *executionContext) marshalOAnCode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAnCode(ctx context.Context, sel ast.SelectionSet, v *model.AnCode) graphql.Marshaler { + if v == nil { + return graphql.Null } + return ec._AnCode(ctx, sel, v) +} - return ret +func (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) { + res, err := graphql.UnmarshalBoolean(v) + return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalOExamGroup2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroup(ctx context.Context, sel ast.SelectionSet, v *model.ExamGroup) graphql.Marshaler { +func (ec *executionContext) marshalOBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { + res := graphql.MarshalBoolean(v) + return res +} + +func (ec *executionContext) unmarshalOBoolean2ᚖbool(ctx context.Context, v interface{}) (*bool, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalBoolean(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast.SelectionSet, v *bool) graphql.Marshaler { if v == nil { return graphql.Null } - return ec._ExamGroup(ctx, sel, v) + res := graphql.MarshalBoolean(*v) + return res } -func (ec *executionContext) marshalOExamGroupConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupConflict(ctx context.Context, sel ast.SelectionSet, v []*model.ExamGroupConflict) graphql.Marshaler { +func (ec *executionContext) marshalOConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Conflict) graphql.Marshaler { if v == nil { return graphql.Null } @@ -35217,7 +35820,7 @@ func (ec *executionContext) marshalOExamGroupConflict2ᚕᚖgithubᚗcomᚋobcod if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalOExamGroupConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupConflict(ctx, sel, v[i]) + ret[i] = ec.marshalNConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflict(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35228,24 +35831,44 @@ func (ec *executionContext) marshalOExamGroupConflict2ᚕᚖgithubᚗcomᚋobcod } wg.Wait() + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + return ret } -func (ec *executionContext) marshalOExamGroupConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupConflict(ctx context.Context, sel ast.SelectionSet, v *model.ExamGroupConflict) graphql.Marshaler { +func (ec *executionContext) marshalOConflicts2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflicts(ctx context.Context, sel ast.SelectionSet, v *model.Conflicts) graphql.Marshaler { if v == nil { return graphql.Null } - return ec._ExamGroupConflict(ctx, sel, v) + return ec._Conflicts(ctx, sel, v) } -func (ec *executionContext) marshalOExamGroupInfo2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupInfo(ctx context.Context, sel ast.SelectionSet, v *model.ExamGroupInfo) graphql.Marshaler { +func (ec *executionContext) marshalOConnectedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExam(ctx context.Context, sel ast.SelectionSet, v *model.ConnectedExam) graphql.Marshaler { if v == nil { return graphql.Null } - return ec._ExamGroupInfo(ctx, sel, v) + return ec._ConnectedExam(ctx, sel, v) } -func (ec *executionContext) marshalOExamInPlan2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamInPlanᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExamInPlan) graphql.Marshaler { +func (ec *executionContext) marshalOConstraints2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConstraints(ctx context.Context, sel ast.SelectionSet, v *model.Constraints) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._Constraints(ctx, sel, v) +} + +func (ec *executionContext) marshalOExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExam(ctx context.Context, sel ast.SelectionSet, v *model.Exam) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._Exam(ctx, sel, v) +} + +func (ec *executionContext) marshalOExamGroup2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroup(ctx context.Context, sel ast.SelectionSet, v []*model.ExamGroup) graphql.Marshaler { if v == nil { return graphql.Null } @@ -35272,7 +35895,7 @@ func (ec *executionContext) marshalOExamInPlan2ᚕᚖgithubᚗcomᚋobcodeᚋple if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNExamInPlan2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamInPlan(ctx, sel, v[i]) + ret[i] = ec.marshalOExamGroup2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroup(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35283,16 +35906,10 @@ func (ec *executionContext) marshalOExamInPlan2ᚕᚖgithubᚗcomᚋobcodeᚋple } wg.Wait() - for _, e := range ret { - if e == graphql.Null { - return graphql.Null - } - } - return ret } -func (ec *executionContext) marshalOExamWithRegs2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegsᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExamWithRegs) graphql.Marshaler { +func (ec *executionContext) marshalOExamGroup2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExamGroup) graphql.Marshaler { if v == nil { return graphql.Null } @@ -35319,7 +35936,7 @@ func (ec *executionContext) marshalOExamWithRegs2ᚕᚖgithubᚗcomᚋobcodeᚋp if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNExamWithRegs2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegs(ctx, sel, v[i]) + ret[i] = ec.marshalNExamGroup2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroup(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35339,14 +35956,14 @@ func (ec *executionContext) marshalOExamWithRegs2ᚕᚖgithubᚗcomᚋobcodeᚋp return ret } -func (ec *executionContext) marshalOExamWithRegs2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegs(ctx context.Context, sel ast.SelectionSet, v *model.ExamWithRegs) graphql.Marshaler { +func (ec *executionContext) marshalOExamGroup2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroup(ctx context.Context, sel ast.SelectionSet, v *model.ExamGroup) graphql.Marshaler { if v == nil { return graphql.Null } - return ec._ExamWithRegs(ctx, sel, v) + return ec._ExamGroup(ctx, sel, v) } -func (ec *executionContext) marshalOExamWithRegsAndRooms2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegsAndRoomsᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExamWithRegsAndRooms) graphql.Marshaler { +func (ec *executionContext) marshalOExamGroupConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupConflict(ctx context.Context, sel ast.SelectionSet, v []*model.ExamGroupConflict) graphql.Marshaler { if v == nil { return graphql.Null } @@ -35373,7 +35990,62 @@ func (ec *executionContext) marshalOExamWithRegsAndRooms2ᚕᚖgithubᚗcomᚋob if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNExamWithRegsAndRooms2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegsAndRooms(ctx, sel, v[i]) + ret[i] = ec.marshalOExamGroupConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupConflict(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + return ret +} + +func (ec *executionContext) marshalOExamGroupConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupConflict(ctx context.Context, sel ast.SelectionSet, v *model.ExamGroupConflict) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._ExamGroupConflict(ctx, sel, v) +} + +func (ec *executionContext) marshalOExamGroupInfo2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupInfo(ctx context.Context, sel ast.SelectionSet, v *model.ExamGroupInfo) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._ExamGroupInfo(ctx, sel, v) +} + +func (ec *executionContext) marshalOExamInPlan2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamInPlanᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExamInPlan) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNExamInPlan2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamInPlan(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35393,7 +36065,7 @@ func (ec *executionContext) marshalOExamWithRegsAndRooms2ᚕᚖgithubᚗcomᚋob return ret } -func (ec *executionContext) marshalOExamerInPlan2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamerInPlanᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExamerInPlan) graphql.Marshaler { +func (ec *executionContext) marshalOExamWithRegs2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegsᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExamWithRegs) graphql.Marshaler { if v == nil { return graphql.Null } @@ -35420,7 +36092,7 @@ func (ec *executionContext) marshalOExamerInPlan2ᚕᚖgithubᚗcomᚋobcodeᚋp if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNExamerInPlan2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamerInPlan(ctx, sel, v[i]) + ret[i] = ec.marshalNExamWithRegs2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegs(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35440,14 +36112,14 @@ func (ec *executionContext) marshalOExamerInPlan2ᚕᚖgithubᚗcomᚋobcodeᚋp return ret } -func (ec *executionContext) marshalOExternalExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExternalExam(ctx context.Context, sel ast.SelectionSet, v *model.ExternalExam) graphql.Marshaler { +func (ec *executionContext) marshalOExamWithRegs2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegs(ctx context.Context, sel ast.SelectionSet, v *model.ExamWithRegs) graphql.Marshaler { if v == nil { return graphql.Null } - return ec._ExternalExam(ctx, sel, v) + return ec._ExamWithRegs(ctx, sel, v) } -func (ec *executionContext) marshalOGeneratedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.GeneratedExam) graphql.Marshaler { +func (ec *executionContext) marshalOExamWithRegsAndRooms2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegsAndRoomsᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExamWithRegsAndRooms) graphql.Marshaler { if v == nil { return graphql.Null } @@ -35474,7 +36146,54 @@ func (ec *executionContext) marshalOGeneratedExam2ᚕᚖgithubᚗcomᚋobcodeᚋ if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNGeneratedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExam(ctx, sel, v[i]) + ret[i] = ec.marshalNExamWithRegsAndRooms2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegsAndRooms(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalOExamerInPlan2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamerInPlanᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExamerInPlan) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNExamerInPlan2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamerInPlan(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35494,6 +36213,13 @@ func (ec *executionContext) marshalOGeneratedExam2ᚕᚖgithubᚗcomᚋobcodeᚋ return ret } +func (ec *executionContext) marshalOExternalExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExternalExam(ctx context.Context, sel ast.SelectionSet, v *model.ExternalExam) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._ExternalExam(ctx, sel, v) +} + func (ec *executionContext) marshalOGeneratedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExam(ctx context.Context, sel ast.SelectionSet, v *model.GeneratedExam) graphql.Marshaler { if v == nil { return graphql.Null @@ -35884,6 +36610,60 @@ func (ec *executionContext) marshalOPlanEntry2ᚖgithubᚗcomᚋobcodeᚋplexams return ec._PlanEntry(ctx, sel, v) } +func (ec *executionContext) marshalOPlannedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PlannedExam) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNPlannedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExam(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalOPlannedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExam(ctx context.Context, sel ast.SelectionSet, v *model.PlannedExam) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._PlannedExam(ctx, sel, v) +} + func (ec *executionContext) marshalOPlannedExamWithNTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExamWithNtaᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PlannedExamWithNta) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index 931698d..5f5cd90 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -288,8 +288,8 @@ type PrimussExamAncode struct { } type PrimussExamByProgram struct { - Program string `json:"program"` - Exams []*PrimussExam `json:"exams"` + Program string `json:"program"` + Exams []*PrimussExamWithCount `json:"exams"` } type PrimussExamInput struct { @@ -297,6 +297,16 @@ type PrimussExamInput struct { Program string `json:"program"` } +type PrimussExamWithCount struct { + Ancode int `json:"ancode"` + Module string `json:"module"` + MainExamer string `json:"mainExamer"` + Program string `json:"program"` + ExamType string `json:"examType"` + Presence string `json:"presence"` + StudentRegsCount int `json:"studentRegsCount"` +} + type Room struct { Name string `json:"name"` Seats int `json:"seats"` diff --git a/graph/plan.graphqls b/graph/plan.graphqls index 1951969..78c6e65 100644 --- a/graph/plan.graphqls +++ b/graph/plan.graphqls @@ -3,8 +3,8 @@ extend type Query { ancodesInPlan: [Int!] examerInPlan: [ExamerInPlan!] - examsInSlot(day: Int!, time: Int!): [GeneratedExam!] - examsWithoutSlot: [GeneratedExam!]! + examsInSlot(day: Int!, time: Int!): [PlannedExam!] + examsWithoutSlot: [PlannedExam!]! allowedSlots(ancode: Int!): [Slot!] awkwardSlots(ancode: Int!): [Slot!]! # slots before or after a conflict diff --git a/graph/plan.resolvers.go b/graph/plan.resolvers.go index ff54887..fd0aa42 100644 --- a/graph/plan.resolvers.go +++ b/graph/plan.resolvers.go @@ -37,12 +37,12 @@ func (r *queryResolver) ExamerInPlan(ctx context.Context) ([]*model.ExamerInPlan } // ExamGroupsInSlot is the resolver for the examGroupsInSlot field. -func (r *queryResolver) ExamsInSlot(ctx context.Context, day int, time int) ([]*model.GeneratedExam, error) { +func (r *queryResolver) ExamsInSlot(ctx context.Context, day int, time int) ([]*model.PlannedExam, error) { return r.plexams.GetExamsInSlot(ctx, day, time) } // ExamsWithoutSlot is the resolver for the examsWithoutSlot field. -func (r *queryResolver) ExamsWithoutSlot(ctx context.Context) ([]*model.GeneratedExam, error) { +func (r *queryResolver) ExamsWithoutSlot(ctx context.Context) ([]*model.PlannedExam, error) { return r.plexams.ExamsWithoutSlot(ctx) } diff --git a/graph/primuss.graphqls b/graph/primuss.graphqls index 1845a49..70a2f19 100644 --- a/graph/primuss.graphqls +++ b/graph/primuss.graphqls @@ -1,3 +1,7 @@ +extend type Query { + primussExams: [PrimussExamByProgram] +} + type PrimussExam { ancode: Int! module: String! @@ -14,20 +18,30 @@ type EnhancedPrimussExam { ntas: [NTA!]! } -type PrimussExamAncode { +type PrimussExamWithCount { ancode: Int! + module: String! + mainExamer: String! program: String! - numberOfStuds: Int! + examType: String! + presence: String! + studentRegsCount: Int! } -input PrimussExamInput { +type PrimussExamByProgram { + program: String! + exams: [PrimussExamWithCount!]! +} + +type PrimussExamAncode { ancode: Int! program: String! + numberOfStuds: Int! } -type PrimussExamByProgram { +input PrimussExamInput { + ancode: Int! program: String! - exams: [PrimussExam!]! } type StudentReg { diff --git a/graph/primuss.resolvers.go b/graph/primuss.resolvers.go new file mode 100644 index 0000000..cf00785 --- /dev/null +++ b/graph/primuss.resolvers.go @@ -0,0 +1,16 @@ +package graph + +// This file will be automatically regenerated based on the schema, any resolver implementations +// will be copied through when generating and any unknown code will be moved to the end. +// Code generated by github.com/99designs/gqlgen version v0.17.34 + +import ( + "context" + + "github.com/obcode/plexams.go/graph/model" +) + +// PrimussExams is the resolver for the primussExams field. +func (r *queryResolver) PrimussExams(ctx context.Context) ([]*model.PrimussExamByProgram, error) { + return r.plexams.PrimussExams(ctx) +} diff --git a/graph/query.graphqls b/graph/query.graphqls index 1ae0fcf..74fe3e8 100644 --- a/graph/query.graphqls +++ b/graph/query.graphqls @@ -7,7 +7,6 @@ type Query { # Additional Exams additionalExams: [AdditionalExam!]! # Primuss - primussExams: [PrimussExamByProgram] primussExam(program: String!, ancode: Int!): PrimussExam! primussExamsForAnCode(ancode: Int!): [PrimussExam!] studentRegsForProgram(program: String!): [StudentReg!] diff --git a/graph/query.resolvers.go b/graph/query.resolvers.go index 20ea136..6431ed8 100644 --- a/graph/query.resolvers.go +++ b/graph/query.resolvers.go @@ -42,11 +42,6 @@ func (r *queryResolver) AdditionalExams(ctx context.Context) ([]*model.Additiona return r.plexams.AdditionalExams(ctx) } -// PrimussExams is the resolver for the primussExams field. -func (r *queryResolver) PrimussExams(ctx context.Context) ([]*model.PrimussExamByProgram, error) { - return r.plexams.PrimussExams(ctx) -} - // PrimussExam is the resolver for the primussExam field. func (r *queryResolver) PrimussExam(ctx context.Context, program string, ancode int) (*model.PrimussExam, error) { return r.plexams.GetPrimussExam(ctx, program, ancode) diff --git a/plexams/pdfDraft.go b/plexams/pdfDraft.go index e72a371..877a85e 100644 --- a/plexams/pdfDraft.go +++ b/plexams/pdfDraft.go @@ -233,14 +233,20 @@ func (p *Plexams) tableForProgram(ctx context.Context, program, programLong stri contents := make([][]string, 0) - exams, err := p.PlannedExamsForProgram(ctx, program) + exams, err := p.PlannedExamsForProgram(ctx, program, true) if err != nil { log.Error().Err(err).Msg("error while getting exams") } for _, exam := range exams { - contents = append(contents, - []string{strconv.Itoa(exam.Ancode), exam.ZpaExam.Module, exam.ZpaExam.MainExamer, - r.Replace(exam.PlanEntry.Starttime.Format("Mon. 02.01.06, 15:04 Uhr"))}) + if exam.PlanEntry == nil { + contents = append(contents, + []string{strconv.Itoa(exam.Ancode), exam.ZpaExam.Module, exam.ZpaExam.MainExamer, + "fehlt noch"}) + } else { + contents = append(contents, + []string{strconv.Itoa(exam.Ancode), exam.ZpaExam.Module, exam.ZpaExam.MainExamer, + r.Replace(exam.PlanEntry.Starttime.Local().Format("Mon. 02.01.06, 15:04 Uhr"))}) + } } grayColor := color.Color{ diff --git a/plexams/plan.go b/plexams/plan.go index fa81101..4ed80a6 100644 --- a/plexams/plan.go +++ b/plexams/plan.go @@ -12,28 +12,19 @@ import ( ) func (p *Plexams) AddExamToSlot(ctx context.Context, ancode int, dayNumber int, timeNumber int) (bool, error) { - // check if slot exists - ok := false - for _, day := range p.semesterConfig.Days { - if day.Number == dayNumber { - ok = true - break - } - } - if !ok { - log.Error().Int("day", dayNumber).Msg("day does not exists") - return false, fmt.Errorf("day %d does not exist", dayNumber) - } - ok = false - for _, time := range p.semesterConfig.Starttimes { - if time.Number == timeNumber { - ok = true + var slot *model.Slot + + for _, s := range p.semesterConfig.Slots { + if s.DayNumber == dayNumber && s.SlotNumber == timeNumber { + slot = s break } } - if !ok { - log.Error().Int("time", timeNumber).Msg("time does not exists") - return false, fmt.Errorf("time %d does not exist", timeNumber) + + if slot == nil { + err := fmt.Errorf("slot (%d,%d) does not exist", dayNumber, timeNumber) + log.Error().Err(err).Int("day", dayNumber).Int("slot", timeNumber).Msg("slot does not exist") + return false, err } // check if exam with ancode exists @@ -43,30 +34,31 @@ func (p *Plexams) AddExamToSlot(ctx context.Context, ancode int, dayNumber int, return false, err } - // TODO: check if slot is allowed - // allowedSlots, err := p.AllowedSlots(ctx, ancode) - // if err != nil { - // log.Error().Err(err).Int("ancode", ancode).Msg("cannot get allowed slots") - // } - // slotIsAllowed := false - - // for _, slot := range allowedSlots { - // if slot.DayNumber == dayNumber && slot.SlotNumber == timeNumber { - // slotIsAllowed = true - // break - // } - // } - // if !slotIsAllowed { - // log.Debug().Int("day", dayNumber).Int("time", timeNumber).Int("ancode", ancode). - // Msg("slot is not allowed") - // return false, fmt.Errorf("slot (%d,%d) is not allowed for exam group %d", - // dayNumber, timeNumber, ancode) - // } + allowedSlots, err := p.AllowedSlots(ctx, ancode) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("cannot get allowed slots") + } + slotIsAllowed := false + + for _, slot := range allowedSlots { + if slot.DayNumber == dayNumber && slot.SlotNumber == timeNumber { + slotIsAllowed = true + break + } + } + if !slotIsAllowed { + log.Debug().Int("day", dayNumber).Int("time", timeNumber).Int("ancode", ancode). + Msg("slot is not allowed") + return false, fmt.Errorf("slot (%d,%d) is not allowed for exam %d", + dayNumber, timeNumber, ancode) + } return p.dbClient.AddExamToSlot(ctx, &model.PlanEntry{ - DayNumber: dayNumber, - SlotNumber: timeNumber, + DayNumber: slot.DayNumber, + SlotNumber: slot.SlotNumber, + Starttime: slot.Starttime, Ancode: ancode, + Locked: false, }) } @@ -213,7 +205,7 @@ func removeSlotsForDay(allSlots []*model.Slot, day *time.Time) []*model.Slot { return slots } -func (p *Plexams) ExamsWithoutSlot(ctx context.Context) ([]*model.GeneratedExam, error) { +func (p *Plexams) ExamsWithoutSlot(ctx context.Context) ([]*model.PlannedExam, error) { exams, err := p.dbClient.GetGeneratedExams(ctx) if err != nil { log.Error().Err(err).Msg("cannot get generated exams") @@ -226,7 +218,7 @@ func (p *Plexams) ExamsWithoutSlot(ctx context.Context) ([]*model.GeneratedExam, return nil, err } - examsWithotSlots := make([]*model.GeneratedExam, 0) + examsWithotSlots := make([]*model.PlannedExam, 0) OUTER: for _, exam := range exams { @@ -235,15 +227,23 @@ OUTER: continue OUTER } } - examsWithotSlots = append(examsWithotSlots, exam) + examsWithotSlots = append(examsWithotSlots, &model.PlannedExam{ + Ancode: exam.Ancode, + ZpaExam: exam.ZpaExam, + PrimussExams: exam.PrimussExams, + Constraints: exam.Constraints, + Conflicts: exam.Conflicts, + StudentRegsCount: exam.StudentRegsCount, + PlanEntry: nil, + }) } // sort by student regs - examsMap := make(map[int][]*model.GeneratedExam) + examsMap := make(map[int][]*model.PlannedExam) for _, exam := range examsWithotSlots { exams, ok := examsMap[exam.StudentRegsCount] if !ok { - exams = make([]*model.GeneratedExam, 0, 1) + exams = make([]*model.PlannedExam, 0, 1) } examsMap[exam.StudentRegsCount] = append(exams, exam) } @@ -255,7 +255,7 @@ OUTER: sort.Sort(sort.Reverse(sort.IntSlice(keys))) - examsWithotSlotsSorted := make([]*model.GeneratedExam, 0, len(examsWithotSlots)) + examsWithotSlotsSorted := make([]*model.PlannedExam, 0, len(examsWithotSlots)) for _, key := range keys { examsWithotSlotsSorted = append(examsWithotSlotsSorted, examsMap[key]...) } @@ -271,7 +271,7 @@ func (p *Plexams) ExamsInSlot(ctx context.Context, day int, time int) ([]*model. return p.dbClient.ExamsInSlot(ctx, day, time) } -func (p *Plexams) GetExamsInSlot(ctx context.Context, day int, time int) ([]*model.GeneratedExam, error) { +func (p *Plexams) GetExamsInSlot(ctx context.Context, day int, time int) ([]*model.PlannedExam, error) { return p.dbClient.GetExamsInSlot(ctx, day, time) } diff --git a/plexams/plan_examgroups.go b/plexams/plan_examgroups.go index cde04cf..53a87be 100644 --- a/plexams/plan_examgroups.go +++ b/plexams/plan_examgroups.go @@ -282,28 +282,28 @@ func (p *Plexams) SlotForExamGroup(ctx context.Context, examGroupCode int) (*mod // return plannedExams, nil // } -func (p *Plexams) LockExamGroup(ctx context.Context, examGroupCode int) (*model.PlanEntry, *model.ExamGroup, error) { - planEntry, err := p.dbClient.LockExamGroup(ctx, examGroupCode) +func (p *Plexams) LockExam(ctx context.Context, ancode int) (*model.PlanEntry, *model.GeneratedExam, error) { + planEntry, err := p.dbClient.LockExam(ctx, ancode) if err != nil { return nil, nil, err } - examGroup, err := p.dbClient.ExamGroup(ctx, examGroupCode) + exam, err := p.dbClient.GetGeneratedExam(ctx, ancode) if err != nil { return planEntry, nil, err } - return planEntry, examGroup, nil + return planEntry, exam, nil } -func (p *Plexams) UnlockExamGroup(ctx context.Context, examGroupCode int) (*model.PlanEntry, *model.ExamGroup, error) { - planEntry, err := p.dbClient.UnlockExamGroup(ctx, examGroupCode) +func (p *Plexams) UnlockExam(ctx context.Context, ancode int) (*model.PlanEntry, *model.GeneratedExam, error) { + planEntry, err := p.dbClient.UnlockExam(ctx, ancode) if err != nil { return nil, nil, err } - examGroup, err := p.dbClient.ExamGroup(ctx, examGroupCode) + exam, err := p.dbClient.GetGeneratedExam(ctx, ancode) if err != nil { return planEntry, nil, err } - return planEntry, examGroup, nil + return planEntry, exam, nil } func (p *Plexams) RemoveUnlockedExamGroupsFromPlan(ctx context.Context) (int, error) { diff --git a/plexams/plannedExams.go b/plexams/plannedExams.go index 4640fd0..88c0f28 100644 --- a/plexams/plannedExams.go +++ b/plexams/plannedExams.go @@ -8,58 +8,93 @@ import ( "github.com/rs/zerolog/log" ) -func (p *Plexams) PlannedExamsForProgram(ctx context.Context, program string) ([]*model.PlannedExam, error) { - connectedExams, err := p.GetConnectedExams(ctx) +func (p *Plexams) PlanEntries(ctx context.Context) ([]*model.PlanEntry, error) { + return p.dbClient.PlanEntries(ctx) +} + +func (p *Plexams) PlannedExam(ctx context.Context, ancode int) (*model.PlannedExam, error) { + exam, err := p.GeneratedExam(ctx, ancode) if err != nil { - log.Error().Err(err).Msg("cannot get connected exams") + log.Error().Err(err).Int("ancode", ancode).Msg("cannot get generated exam") return nil, err } - plannedExams := make([]*model.PlannedExam, 0) + planEntry, err := p.dbClient.PlanEntry(ctx, ancode) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("cannot get planEntry for ancode") + return nil, err + } - for _, connectedExam := range connectedExams { - constraints, _ := p.ConstraintForAncode(ctx, connectedExam.ZpaExam.AnCode) - if constraints != nil && constraints.NotPlannedByMe { - // if notPlannedByMe, _ := p.NotPlannedByMe(ctx, connectedExam.ZpaExam.AnCode); notPlannedByMe { - log.Debug().Int("ancode", connectedExam.ZpaExam.AnCode). - Str("module", connectedExam.ZpaExam.Module). - Str("main examer", connectedExam.ZpaExam.MainExamer). - Msg("exam not planned by me") - continue - } + return &model.PlannedExam{ + Ancode: exam.Ancode, + ZpaExam: exam.ZpaExam, + PrimussExams: exam.PrimussExams, + Constraints: exam.Constraints, + Conflicts: exam.Conflicts, + StudentRegsCount: exam.StudentRegsCount, + PlanEntry: planEntry, + }, err +} - var plannedExam *model.PlannedExam - for _, primussExam := range connectedExam.PrimussExams { - if primussExam.Program == program { - plannedExam = &model.PlannedExam{ // FIXME: new planned exam - Ancode: connectedExam.ZpaExam.AnCode, - // Module: connectedExam.ZpaExam.Module, - // MainExamer: connectedExam.ZpaExam.MainExamer, - // DateTime: nil, - } - } - } +func (p *Plexams) PlannedExams(ctx context.Context) ([]*model.PlannedExam, error) { + exams, err := p.GeneratedExams(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get generated exams") + return nil, err + } - if plannedExam == nil { - continue - } + planEntries, err := p.dbClient.PlanEntries(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get planEntries") + return nil, err + } + + planEntryMap := make(map[int]*model.PlanEntry) + for _, planEntry := range planEntries { + planEntryMap[planEntry.Ancode] = planEntry + } + + plannedExams := make([]*model.PlannedExam, 0, len(exams)) - log.Debug().Int("ancode", plannedExam.Ancode).Msg("found connected exam") - - // slot, err := p.SlotForAncode(ctx, plannedExam.Ancode) - // if err != nil { - // log.Error().Err(err).Int("ancode", plannedExam.Ancode).Msg("cannot get slot for ancode") - // return nil, err - // } - // if slot != nil { - // // plannedExam.DateTime = p.getTimeForSlot(slot.DayNumber, slot.SlotNumber) // FIXME: new planned exam - // } - plannedExams = append(plannedExams, plannedExam) + for _, exam := range exams { + plannedExams = append(plannedExams, + &model.PlannedExam{ + Ancode: exam.Ancode, + ZpaExam: exam.ZpaExam, + PrimussExams: exam.PrimussExams, + Constraints: exam.Constraints, + Conflicts: exam.Conflicts, + StudentRegsCount: exam.StudentRegsCount, + PlanEntry: planEntryMap[exam.Ancode], + }) } return plannedExams, nil } +func (p *Plexams) PlannedExamsForProgram(ctx context.Context, program string, onlyPlannedByMe bool) ([]*model.PlannedExam, error) { + plannedExams, err := p.PlannedExams(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get planned exams") + return nil, err + } + + plannedExamsForProgram := make([]*model.PlannedExam, 0) + for _, plannedExam := range plannedExams { + if onlyPlannedByMe && plannedExam.Constraints != nil && plannedExam.Constraints.NotPlannedByMe { + continue + } + for _, primussExam := range plannedExam.PrimussExams { + if primussExam.Exam.Program == program { + plannedExamsForProgram = append(plannedExamsForProgram, plannedExam) + break + } + } + } + + return plannedExamsForProgram, nil +} + // TODO: needed? // nolint func (p *Plexams) getTimeForSlot(dayNumber, slotNumber int) *time.Time { diff --git a/plexams/samename.go b/plexams/samename.go new file mode 100644 index 0000000..e0ab784 --- /dev/null +++ b/plexams/samename.go @@ -0,0 +1,46 @@ +package plexams + +import ( + "context" + "fmt" + "sort" + + "github.com/logrusorgru/aurora" + "github.com/obcode/plexams.go/graph/model" + "github.com/rs/zerolog/log" +) + +func (p *Plexams) PrintSameName() { + exams, err := p.GetZpaExamsToPlan(context.TODO()) + if err != nil { + log.Error().Err(err).Msg("cannot get zpa exams to plan") + } + + sameNames := make(map[string][]*model.ZPAExam) + + for _, exam := range exams { + _, ok := sameNames[exam.Module] + if ok { + sameNames[exam.Module] = append(sameNames[exam.Module], exam) + } else { + sameNames[exam.Module] = []*model.ZPAExam{exam} + } + } + + keys := make([]string, 0, len(sameNames)) + for k := range sameNames { + keys = append(keys, k) + } + + sort.Strings(keys) + + for _, name := range keys { + sameNameExams := sameNames[name] + if len(sameNameExams) > 1 { + fmt.Printf("- %s\n", aurora.Blue(name)) + for _, e := range sameNameExams { + fmt.Printf(" - %d. %s\n", aurora.Red(e.AnCode), aurora.Green(e.MainExamer)) + } + } + } +} diff --git a/plexams/validate.go b/plexams/validate.go index 4d0acae..5fe1f6f 100644 --- a/plexams/validate.go +++ b/plexams/validate.go @@ -2,20 +2,30 @@ package plexams import ( "context" + "fmt" "time" set "github.com/deckarep/golang-set/v2" "github.com/gookit/color" "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" + "github.com/spf13/viper" ) // TODO: Validate if all NTAs have MTKNR -var count = 0 +var ( + count = 0 + knownConflictsCount = 0 +) + +type KnownConflict struct { + Mtknr, Ancode1, Ancode2 string +} func (p *Plexams) ValidateConflicts(onlyPlannedByMe bool, ancode int) error { count = 0 + knownConflictsCount = 0 ctx := context.Background() color.Style{color.FgRed, color.BgGreen, color.OpBold}.Println(" --- validating conflicts --- ") @@ -43,14 +53,36 @@ func (p *Plexams) ValidateConflicts(onlyPlannedByMe bool, ancode int) error { return err } + knownConflicts := set.NewSet[KnownConflict]() + + knownConflictsConf := viper.Get("knownConflicts.studentRegs") + if knownConflictsConf != nil { + knownConflictsSlice := knownConflictsConf.([]interface{}) + for _, knownConflict := range knownConflictsSlice { + knownConflictSlice := knownConflict.([]interface{}) + knownConflicts.Add(KnownConflict{ + Mtknr: knownConflictSlice[0].(string), + Ancode1: knownConflictSlice[1].(string), + Ancode2: knownConflictSlice[2].(string), + }) + } + } + + log.Debug().Int("count", knownConflicts.Cardinality()).Interface("conflicts", knownConflicts).Msg("found known conflicts") + for _, student := range students { - validateStudentReg(student, planAncodeEntries, planAncodeEntriesNotPlannedByMe, onlyPlannedByMe, ancode) + validateStudentReg(student, planAncodeEntries, planAncodeEntriesNotPlannedByMe, onlyPlannedByMe, knownConflicts, ancode) + } + + if knownConflictsCount > 0 { + color.Green.Printf("%d known conflicts found\n", knownConflictsCount) } + return nil } func validateStudentReg(student *model.Student, planAncodeEntries []*model.PlanEntry, - planAncodeEntriesNotPlannedByMe set.Set[int], onlyPlannedByMe bool, ancode int) { + planAncodeEntriesNotPlannedByMe set.Set[int], onlyPlannedByMe bool, knownConflicts set.Set[KnownConflict], ancode int) { log.Debug().Str("name", student.Name).Str("mtknr", student.Mtknr).Msg("checking regs for student") planAncodeEntriesForStudent := make([]*model.PlanEntry, 0) @@ -79,6 +111,15 @@ func validateStudentReg(student *model.Student, planAncodeEntries []*model.PlanE p[i].Ancode == p[j].Ancode { continue } + if knownConflicts.Contains(KnownConflict{ + Mtknr: student.Mtknr, + Ancode1: fmt.Sprint(p[i].Ancode), + Ancode2: fmt.Sprint(p[j].Ancode), + }) { + // fmt.Printf("found known conflict: [%s, %d, %d]\n", student.Mtknr, p[i].Ancode, p[j].Ancode) + knownConflictsCount++ + continue + } if onlyPlannedByMe && planAncodeEntriesNotPlannedByMe.Contains(p[i].Ancode) && planAncodeEntriesNotPlannedByMe.Contains(p[j].Ancode) { @@ -94,7 +135,8 @@ func validateStudentReg(student *model.Student, planAncodeEntries []*model.PlanE if p[i].DayNumber == p[j].DayNumber && p[i].SlotNumber == p[j].SlotNumber { count++ - color.Red.Printf("%3d. Same slot: ancodes %d (%d, %d) and %d (%d,%d) for student %s (%s/%s)\n", count, + color.Red.Printf(" - [\"%s\", \"%d\", \"%d\"] # %3d. Same slot: ancodes %d (%d, %d) and %d (%d,%d) for student %s (%s/%s)\n", + student.Mtknr, p[i].Ancode, p[j].Ancode, count, p[i].Ancode, p[i].DayNumber, p[i].SlotNumber, p[j].Ancode, p[j].DayNumber, p[j].SlotNumber, student.Name, student.Program, student.Mtknr, @@ -105,7 +147,8 @@ func validateStudentReg(student *model.Student, planAncodeEntries []*model.PlanE (p[i].SlotNumber+1 == p[j].SlotNumber || p[i].SlotNumber-1 == p[j].SlotNumber) { count++ - color.Red.Printf("%3d. Adjacent slots: ancodes %d (%d, %d) and %d (%d,%d) for student %s (%s/%s)\n", count, + color.Red.Printf(" - [\"%s\", \"%d\", \"%d\"] # %3d. Adjacent slots: ancodes %d (%d, %d) and %d (%d,%d) for student %s (%s/%s)\n", + student.Mtknr, p[i].Ancode, p[j].Ancode, count, p[i].Ancode, p[i].DayNumber, p[i].SlotNumber, p[j].Ancode, p[j].DayNumber, p[j].SlotNumber, student.Name, student.Program, student.Mtknr, @@ -133,6 +176,11 @@ func (p *Plexams) ValidateConstraints() error { log.Error().Err(err).Msg("cannot get constraints") } + constraintsMap := make(map[int]*model.Constraints) + for _, constraint := range constraints { + constraintsMap[constraint.Ancode] = constraint + } + for _, constraint := range constraints { slot, err := p.SlotForAncode(ctx, constraint.Ancode) if err != nil { @@ -143,12 +191,43 @@ func (p *Plexams) ValidateConstraints() error { continue } + // if len(constraint.SameSlot) > 0 { + for _, otherAncode := range constraint.SameSlot { + log.Debug().Int("ancode", constraint.Ancode).Int("other ancode", otherAncode).Msg("checking same slot") + otherSlot, err := p.SlotForAncode(ctx, otherAncode) + if err != nil { + log.Error().Err(err).Int("ancode", otherAncode).Msg("cannot get slot for other ancode") + } + + if otherSlot == nil { + otherConstraint, ok := constraintsMap[otherAncode] + if ok && otherConstraint.NotPlannedByMe { + continue + } + + color.Red.Printf("Exams %d and %d must be in the same slot, are %v and %v\n", constraint.Ancode, otherAncode, slot, otherSlot) + continue + } + + if *slot != *otherSlot { + color.Red.Printf("Exams %d and %d must be in the same slot, are %v and %v\n", constraint.Ancode, otherAncode, slot, otherSlot) + } + } + // } + if constraint.FixedDay != nil { color.Red.Println("FIXME: FixedDay") } if constraint.FixedTime != nil { - color.Red.Println("FIXME: FixedTime") + log.Debug().Int("ancode", constraint.Ancode).Msg("checking fixed time") + fixed := constraint.FixedTime + if fixed.Day() != slot.Starttime.Day() || + fixed.Month() != slot.Starttime.Month() || + fixed.Local().Hour() != slot.Starttime.Local().Hour() || + fixed.Minute() != slot.Starttime.Minute() { + color.Red.Printf("Exams %d has fixed slot %s, is %s\n", constraint.Ancode, fixed.Format("02.01.06 15:04"), constraint.FixedTime.Format("02.01.06 15:04")) + } } for _, day := range constraint.ExcludeDays { @@ -171,6 +250,7 @@ func (p *Plexams) ValidateConstraints() error { color.Red.Printf("Exam #%d planned on day %s which is not a possible day\n", constraint.Ancode, dayPlanned.Format("02.01.06")) } } + } return nil From 498e7f5e0bcb00981bb556da23f2e47045232d35 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Sat, 2 Dec 2023 18:31:50 +0100 Subject: [PATCH 40/78] small changes --- cmd/info.go | 15 ++++++++++++--- plexams/prepare.go | 2 ++ plexams/validate.go | 3 ++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/cmd/info.go b/cmd/info.go index eebcbe9..9a04ea8 100644 --- a/cmd/info.go +++ b/cmd/info.go @@ -1,6 +1,7 @@ package cmd import ( + "context" "encoding/json" "fmt" "log" @@ -22,7 +23,7 @@ request-rooms --- which rooms to request stats --- get statistics student-regs ancode --- get student-reqs for ancode rooms-for-nta name --- get planned rooms for student -exams-for-student name --- get exams for student.`, +student name --- get info for student.`, Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { p := initPlexamsConfig() @@ -88,16 +89,24 @@ exams-for-student name --- get exams for student.`, fmt.Println(err) return } - case "exams-for-student": + case "student": if len(args) < 2 { log.Fatal("need name") } // FIXME - err := p.GetExamsForStudent(args[1]) // nolint + students, err := p.StudentsByName(context.TODO(), args[1]) // nolint if err != nil { fmt.Println(err) return } + for _, student := range students { + fmt.Printf("%s (%s, %s%s): regs %v", student.Name, student.Mtknr, student.Program, student.Group, student.Regs) + if student.Nta != nil { + fmt.Printf(", NTA: %s\n", student.Nta.Compensation) + } else { + fmt.Println() + } + } default: fmt.Println("info called with unknown sub command") } diff --git a/plexams/prepare.go b/plexams/prepare.go index 1a185d6..b87f8f2 100644 --- a/plexams/prepare.go +++ b/plexams/prepare.go @@ -52,6 +52,8 @@ func (p *Plexams) PrepareStudentRegs() error { studentRegsPerStudent := make(map[string][]*model.StudentReg) for _, program := range programs { + // TODO: ancodes in MUC.DAI which are available in ZPA also, are still in student regs, but should not! + // maybe filter zpa codes for program! studentRegs, err := p.dbClient.StudentRegsForProgram(ctx, program) if err != nil { log.Error().Err(err).Str("program", program).Msg("cannot get studentregs for program") diff --git a/plexams/validate.go b/plexams/validate.go index 5fe1f6f..ddb9281 100644 --- a/plexams/validate.go +++ b/plexams/validate.go @@ -157,7 +157,8 @@ func validateStudentReg(student *model.Student, planAncodeEntries []*model.PlanE // same day if p[i].DayNumber == p[j].DayNumber { count++ - color.Yellow.Printf("%3d. Same day: ancodes %d (%d, %d) and %d (%d,%d) for student %s (%s/%s)\n", count, + color.Yellow.Printf(" - [\"%s\", \"%d\", \"%d\"] # %3d. Same day: ancodes %d (%d, %d) and %d (%d,%d) for student %s (%s/%s)\n", + student.Mtknr, p[i].Ancode, p[j].Ancode, count, p[i].Ancode, p[i].DayNumber, p[i].SlotNumber, p[j].Ancode, p[j].DayNumber, p[j].SlotNumber, student.Name, student.Program, student.Mtknr, From 7ae46ab1c8b212245f4bc2ce6908d99eafadad3c Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Sat, 2 Dec 2023 22:40:27 +0100 Subject: [PATCH 41/78] improvements --- cmd/prepare.go | 17 +++++++++-------- plexams/plan.go | 9 --------- plexams/prepare.go | 22 ++++++++++++++++------ 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/cmd/prepare.go b/cmd/prepare.go index 6fcf1dd..040a678 100644 --- a/cmd/prepare.go +++ b/cmd/prepare.go @@ -22,8 +22,9 @@ var ( generated-exams --- generate exams from connected-exams, external-exams and primuss-data --- step 2 - studentregs --- regs per exam & regs per student --- step 2 - nta --- find NTAs for semester --- step 3 + studentregs --- regs per exam & regs per student (needs connected-exams) --- step 2 + + # nta --- find NTAs for semester --- step 3 # exams-with-regs --- exams from connected-exams and studentregs --- step 4 # exam-groups --- group of exams in the same slot --- step 5 -- according to constraints? @@ -115,12 +116,6 @@ var ( os.Exit(1) } - case "studentregs": - err := plexams.PrepareStudentRegs() - if err != nil { - os.Exit(1) - } - // case "exams-with-regs": // Deprecated: no longer needed // err := plexams.PrepareExamsWithRegs() // if err != nil { @@ -133,6 +128,12 @@ var ( os.Exit(1) } + case "studentregs": + err := plexams.PrepareStudentRegs() + if err != nil { + os.Exit(1) + } + // case "exam-groups": // err := plexams.PrepareExamGroups() // if err != nil { diff --git a/plexams/plan.go b/plexams/plan.go index 4ed80a6..b10f8c4 100644 --- a/plexams/plan.go +++ b/plexams/plan.go @@ -63,15 +63,6 @@ func (p *Plexams) AddExamToSlot(ctx context.Context, ancode int, dayNumber int, } func (p *Plexams) AllowedSlots(ctx context.Context, ancode int) ([]*model.Slot, error) { - if p.dbClient.ExamIsLocked(ctx, ancode) { - slot, err := p.SlotForAncode(ctx, ancode) - if err != nil { - log.Error().Err(err).Int("ancode", ancode).Msg("exam is locked, but got an error on getting slot") - return nil, err - } - return []*model.Slot{slot}, nil - } - exam, err := p.GeneratedExam(ctx, ancode) if err != nil { log.Error().Err(err).Int("ancode", ancode).Msg("exam does not exist") diff --git a/plexams/prepare.go b/plexams/prepare.go index b87f8f2..1348ce5 100644 --- a/plexams/prepare.go +++ b/plexams/prepare.go @@ -2,6 +2,7 @@ package plexams import ( "context" + "fmt" "sort" set "github.com/deckarep/golang-set/v2" @@ -29,21 +30,32 @@ func (p *Plexams) PrepareStudentRegs() error { Ancode int `json:"ancode,omitempty"` } - plannedZpaAncodes := set.NewSet[int]() + plannedZpaAncodes := make(map[string]set.Set[int]) // program -> set of ancodes primussAncodesToZpaAncodes := make(map[programmAndAncode]int) for _, connectedExam := range connectedExams { ancode := connectedExam.ZpaExam.AnCode - plannedZpaAncodes.Add(ancode) - for _, primussExam := range connectedExam.PrimussExams { + plannedZpaAncodesForProgram, ok := plannedZpaAncodes[primussExam.Program] + if !ok { + plannedZpaAncodesForProgram = set.NewSet[int]() + } + plannedZpaAncodesForProgram.Add(ancode) + plannedZpaAncodes[primussExam.Program] = plannedZpaAncodesForProgram + if primussExam.AnCode != ancode { primussAncodesToZpaAncodes[programmAndAncode{primussExam.Program, primussExam.AnCode}] = ancode } } } + // TODO: rm me + for program, ancodes := range plannedZpaAncodes { + fmt.Printf(">>> %s <<<\n", program) + fmt.Printf(" %v\n\n", ancodes) + } + for k, v := range primussAncodesToZpaAncodes { log.Debug().Interface("primussAncode", k).Int("zpa ancode", v).Msg("primuss ancodes with different zpa ancodes") } @@ -52,8 +64,6 @@ func (p *Plexams) PrepareStudentRegs() error { studentRegsPerStudent := make(map[string][]*model.StudentReg) for _, program := range programs { - // TODO: ancodes in MUC.DAI which are available in ZPA also, are still in student regs, but should not! - // maybe filter zpa codes for program! studentRegs, err := p.dbClient.StudentRegsForProgram(ctx, program) if err != nil { log.Error().Err(err).Str("program", program).Msg("cannot get studentregs for program") @@ -68,7 +78,7 @@ func (p *Plexams) PrepareStudentRegs() error { studentReg.AnCode = zpaAncode } - if !plannedZpaAncodes.Contains(studentReg.AnCode) { + if !plannedZpaAncodes[program].Contains(studentReg.AnCode) { continue } From e5b39b2cc7e911aeb81041c97be915fa1c239649 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Mon, 4 Dec 2023 20:07:16 +0100 Subject: [PATCH 42/78] ntas and maxduration in generated and planned exam --- db/plan.go | 2 + graph/exam.graphqls | 4 + graph/generated/generated.go | 300 +++++++++++++++++++++++++++++++++++ graph/model/models_gen.go | 4 + plexams/generatedExams.go | 18 ++- plexams/plannedExams.go | 4 + 6 files changed, 330 insertions(+), 2 deletions(-) diff --git a/db/plan.go b/db/plan.go index 9bcc219..67dded9 100644 --- a/db/plan.go +++ b/db/plan.go @@ -92,6 +92,8 @@ func (db *DB) GetExamsInSlot(ctx context.Context, day int, time int) ([]*model.P Constraints: exam.Constraints, Conflicts: exam.Conflicts, StudentRegsCount: exam.StudentRegsCount, + Ntas: exam.Ntas, + MaxDuration: exam.MaxDuration, PlanEntry: planEntry, }) } diff --git a/graph/exam.graphqls b/graph/exam.graphqls index ed83763..6b26d36 100644 --- a/graph/exam.graphqls +++ b/graph/exam.graphqls @@ -117,6 +117,8 @@ type GeneratedExam { constraints: Constraints conflicts: [ZPAConflict!]! studentRegsCount: Int! + ntas: [NTA!]! + maxDuration: Int! } type ZPAConflict { @@ -132,6 +134,8 @@ type PlannedExam { constraints: Constraints conflicts: [ZPAConflict!]! studentRegsCount: Int! + ntas: [NTA!]! + maxDuration: Int! planEntry: PlanEntry } diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 7ba8593..8a2a91a 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -203,6 +203,8 @@ type ComplexityRoot struct { Ancode func(childComplexity int) int Conflicts func(childComplexity int) int Constraints func(childComplexity int) int + MaxDuration func(childComplexity int) int + Ntas func(childComplexity int) int PrimussExams func(childComplexity int) int StudentRegsCount func(childComplexity int) int ZpaExam func(childComplexity int) int @@ -345,6 +347,8 @@ type ComplexityRoot struct { Ancode func(childComplexity int) int Conflicts func(childComplexity int) int Constraints func(childComplexity int) int + MaxDuration func(childComplexity int) int + Ntas func(childComplexity int) int PlanEntry func(childComplexity int) int PrimussExams func(childComplexity int) int StudentRegsCount func(childComplexity int) int @@ -1410,6 +1414,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.GeneratedExam.Constraints(childComplexity), true + case "GeneratedExam.maxDuration": + if e.complexity.GeneratedExam.MaxDuration == nil { + break + } + + return e.complexity.GeneratedExam.MaxDuration(childComplexity), true + + case "GeneratedExam.ntas": + if e.complexity.GeneratedExam.Ntas == nil { + break + } + + return e.complexity.GeneratedExam.Ntas(childComplexity), true + case "GeneratedExam.primussExams": if e.complexity.GeneratedExam.PrimussExams == nil { break @@ -2173,6 +2191,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PlannedExam.Constraints(childComplexity), true + case "PlannedExam.maxDuration": + if e.complexity.PlannedExam.MaxDuration == nil { + break + } + + return e.complexity.PlannedExam.MaxDuration(childComplexity), true + + case "PlannedExam.ntas": + if e.complexity.PlannedExam.Ntas == nil { + break + } + + return e.complexity.PlannedExam.Ntas(childComplexity), true + case "PlannedExam.planEntry": if e.complexity.PlannedExam.PlanEntry == nil { break @@ -3960,6 +3992,8 @@ type GeneratedExam { constraints: Constraints conflicts: [ZPAConflict!]! studentRegsCount: Int! + ntas: [NTA!]! + maxDuration: Int! } type ZPAConflict { @@ -3975,6 +4009,8 @@ type PlannedExam { constraints: Constraints conflicts: [ZPAConflict!]! studentRegsCount: Int! + ntas: [NTA!]! + maxDuration: Int! planEntry: PlanEntry } @@ -10238,6 +10274,116 @@ func (ec *executionContext) fieldContext_GeneratedExam_studentRegsCount(ctx cont return fc, nil } +func (ec *executionContext) _GeneratedExam_ntas(ctx context.Context, field graphql.CollectedField, obj *model.GeneratedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_GeneratedExam_ntas(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Ntas, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.NTA) + fc.Result = res + return ec.marshalNNTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_GeneratedExam_ntas(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "GeneratedExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext_NTA_name(ctx, field) + case "mtknr": + return ec.fieldContext_NTA_mtknr(ctx, field) + case "compensation": + return ec.fieldContext_NTA_compensation(ctx, field) + case "deltaDurationPercent": + return ec.fieldContext_NTA_deltaDurationPercent(ctx, field) + case "needsRoomAlone": + return ec.fieldContext_NTA_needsRoomAlone(ctx, field) + case "program": + return ec.fieldContext_NTA_program(ctx, field) + case "from": + return ec.fieldContext_NTA_from(ctx, field) + case "until": + return ec.fieldContext_NTA_until(ctx, field) + case "lastSemester": + return ec.fieldContext_NTA_lastSemester(ctx, field) + case "exams": + return ec.fieldContext_NTA_exams(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type NTA", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _GeneratedExam_maxDuration(ctx context.Context, field graphql.CollectedField, obj *model.GeneratedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_GeneratedExam_maxDuration(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.MaxDuration, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_GeneratedExam_maxDuration(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "GeneratedExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _Invigilation_roomName(ctx context.Context, field graphql.CollectedField, obj *model.Invigilation) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Invigilation_roomName(ctx, field) if err != nil { @@ -14950,6 +15096,116 @@ func (ec *executionContext) fieldContext_PlannedExam_studentRegsCount(ctx contex return fc, nil } +func (ec *executionContext) _PlannedExam_ntas(ctx context.Context, field graphql.CollectedField, obj *model.PlannedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedExam_ntas(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Ntas, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.NTA) + fc.Result = res + return ec.marshalNNTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedExam_ntas(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext_NTA_name(ctx, field) + case "mtknr": + return ec.fieldContext_NTA_mtknr(ctx, field) + case "compensation": + return ec.fieldContext_NTA_compensation(ctx, field) + case "deltaDurationPercent": + return ec.fieldContext_NTA_deltaDurationPercent(ctx, field) + case "needsRoomAlone": + return ec.fieldContext_NTA_needsRoomAlone(ctx, field) + case "program": + return ec.fieldContext_NTA_program(ctx, field) + case "from": + return ec.fieldContext_NTA_from(ctx, field) + case "until": + return ec.fieldContext_NTA_until(ctx, field) + case "lastSemester": + return ec.fieldContext_NTA_lastSemester(ctx, field) + case "exams": + return ec.fieldContext_NTA_exams(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type NTA", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _PlannedExam_maxDuration(ctx context.Context, field graphql.CollectedField, obj *model.PlannedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedExam_maxDuration(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.MaxDuration, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedExam_maxDuration(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _PlannedExam_planEntry(ctx context.Context, field graphql.CollectedField, obj *model.PlannedExam) (ret graphql.Marshaler) { fc, err := ec.fieldContext_PlannedExam_planEntry(ctx, field) if err != nil { @@ -17971,6 +18227,10 @@ func (ec *executionContext) fieldContext_Query_generatedExams(ctx context.Contex return ec.fieldContext_GeneratedExam_conflicts(ctx, field) case "studentRegsCount": return ec.fieldContext_GeneratedExam_studentRegsCount(ctx, field) + case "ntas": + return ec.fieldContext_GeneratedExam_ntas(ctx, field) + case "maxDuration": + return ec.fieldContext_GeneratedExam_maxDuration(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type GeneratedExam", field.Name) }, @@ -18026,6 +18286,10 @@ func (ec *executionContext) fieldContext_Query_generatedExam(ctx context.Context return ec.fieldContext_GeneratedExam_conflicts(ctx, field) case "studentRegsCount": return ec.fieldContext_GeneratedExam_studentRegsCount(ctx, field) + case "ntas": + return ec.fieldContext_GeneratedExam_ntas(ctx, field) + case "maxDuration": + return ec.fieldContext_GeneratedExam_maxDuration(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type GeneratedExam", field.Name) }, @@ -18095,6 +18359,10 @@ func (ec *executionContext) fieldContext_Query_plannedExams(ctx context.Context, return ec.fieldContext_PlannedExam_conflicts(ctx, field) case "studentRegsCount": return ec.fieldContext_PlannedExam_studentRegsCount(ctx, field) + case "ntas": + return ec.fieldContext_PlannedExam_ntas(ctx, field) + case "maxDuration": + return ec.fieldContext_PlannedExam_maxDuration(ctx, field) case "planEntry": return ec.fieldContext_PlannedExam_planEntry(ctx, field) } @@ -18152,6 +18420,10 @@ func (ec *executionContext) fieldContext_Query_plannedExam(ctx context.Context, return ec.fieldContext_PlannedExam_conflicts(ctx, field) case "studentRegsCount": return ec.fieldContext_PlannedExam_studentRegsCount(ctx, field) + case "ntas": + return ec.fieldContext_PlannedExam_ntas(ctx, field) + case "maxDuration": + return ec.fieldContext_PlannedExam_maxDuration(ctx, field) case "planEntry": return ec.fieldContext_PlannedExam_planEntry(ctx, field) } @@ -18673,6 +18945,10 @@ func (ec *executionContext) fieldContext_Query_examsInSlot(ctx context.Context, return ec.fieldContext_PlannedExam_conflicts(ctx, field) case "studentRegsCount": return ec.fieldContext_PlannedExam_studentRegsCount(ctx, field) + case "ntas": + return ec.fieldContext_PlannedExam_ntas(ctx, field) + case "maxDuration": + return ec.fieldContext_PlannedExam_maxDuration(ctx, field) case "planEntry": return ec.fieldContext_PlannedExam_planEntry(ctx, field) } @@ -18744,6 +19020,10 @@ func (ec *executionContext) fieldContext_Query_examsWithoutSlot(ctx context.Cont return ec.fieldContext_PlannedExam_conflicts(ctx, field) case "studentRegsCount": return ec.fieldContext_PlannedExam_studentRegsCount(ctx, field) + case "ntas": + return ec.fieldContext_PlannedExam_ntas(ctx, field) + case "maxDuration": + return ec.fieldContext_PlannedExam_maxDuration(ctx, field) case "planEntry": return ec.fieldContext_PlannedExam_planEntry(ctx, field) } @@ -28460,6 +28740,16 @@ func (ec *executionContext) _GeneratedExam(ctx context.Context, sel ast.Selectio if out.Values[i] == graphql.Null { out.Invalids++ } + case "ntas": + out.Values[i] = ec._GeneratedExam_ntas(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "maxDuration": + out.Values[i] = ec._GeneratedExam_maxDuration(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -29485,6 +29775,16 @@ func (ec *executionContext) _PlannedExam(ctx context.Context, sel ast.SelectionS if out.Values[i] == graphql.Null { out.Invalids++ } + case "ntas": + out.Values[i] = ec._PlannedExam_ntas(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "maxDuration": + out.Values[i] = ec._PlannedExam_maxDuration(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } case "planEntry": out.Values[i] = ec._PlannedExam_planEntry(ctx, field, obj) default: diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index 5f5cd90..735d634 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -163,6 +163,8 @@ type GeneratedExam struct { Constraints *Constraints `json:"constraints,omitempty"` Conflicts []*ZPAConflict `json:"conflicts"` StudentRegsCount int `json:"studentRegsCount"` + Ntas []*NTA `json:"ntas"` + MaxDuration int `json:"maxDuration"` } type Invigilation struct { @@ -272,6 +274,8 @@ type PlannedExam struct { Constraints *Constraints `json:"constraints,omitempty"` Conflicts []*ZPAConflict `json:"conflicts"` StudentRegsCount int `json:"studentRegsCount"` + Ntas []*NTA `json:"ntas"` + MaxDuration int `json:"maxDuration"` PlanEntry *PlanEntry `json:"planEntry,omitempty"` } diff --git a/plexams/generatedExams.go b/plexams/generatedExams.go index 322ebb8..928f1b9 100644 --- a/plexams/generatedExams.go +++ b/plexams/generatedExams.go @@ -29,14 +29,14 @@ func (p *Plexams) PrepareGeneratedExams() error { return err } - ntas, err := p.Ntas(ctx) + allNtas, err := p.Ntas(ctx) if err != nil { log.Error().Err(err).Msg("cannot get ntas") return err } ntaMap := make(map[string]*model.NTA) - for _, nta := range ntas { + for _, nta := range allNtas { ntaMap[nta.Mtknr] = nta } @@ -83,6 +83,8 @@ func (p *Plexams) PrepareGeneratedExams() error { spinner.Message("adding primuss data") studentRegsCount := 0 + ntas := make([]*model.NTA, 0) + enhancedPrimussExams := make([]*model.EnhancedPrimussExam, 0, len(connectedExam.PrimussExams)) for _, primussExam := range connectedExam.PrimussExams { enhanced, err := p.primussToEnhanced(ctx, primussExam, ntaMap) @@ -92,6 +94,7 @@ func (p *Plexams) PrepareGeneratedExams() error { return err } + ntas = append(ntas, enhanced.Ntas...) studentRegsCount += len(enhanced.StudentRegs) enhancedPrimussExams = append(enhancedPrimussExams, enhanced) } @@ -144,6 +147,15 @@ func (p *Plexams) PrepareGeneratedExams() error { conflicts = append(conflicts, conflictsMap[key]) } + duration := connectedExam.ZpaExam.Duration + maxDuration := duration + for _, nta := range ntas { + ntaDuration := (duration * (100 + nta.DeltaDurationPercent)) / 100 + if ntaDuration > maxDuration { + maxDuration = ntaDuration + } + } + exams = append(exams, &model.GeneratedExam{ Ancode: connectedExam.ZpaExam.AnCode, ZpaExam: connectedExam.ZpaExam, @@ -151,6 +163,8 @@ func (p *Plexams) PrepareGeneratedExams() error { Constraints: constraints[connectedExam.ZpaExam.AnCode], Conflicts: conflicts, StudentRegsCount: studentRegsCount, + Ntas: ntas, + MaxDuration: maxDuration, }) err = spinner.Stop() diff --git a/plexams/plannedExams.go b/plexams/plannedExams.go index 88c0f28..619af68 100644 --- a/plexams/plannedExams.go +++ b/plexams/plannedExams.go @@ -32,6 +32,8 @@ func (p *Plexams) PlannedExam(ctx context.Context, ancode int) (*model.PlannedEx Constraints: exam.Constraints, Conflicts: exam.Conflicts, StudentRegsCount: exam.StudentRegsCount, + Ntas: exam.Ntas, + MaxDuration: exam.MaxDuration, PlanEntry: planEntry, }, err } @@ -65,6 +67,8 @@ func (p *Plexams) PlannedExams(ctx context.Context) ([]*model.PlannedExam, error Constraints: exam.Constraints, Conflicts: exam.Conflicts, StudentRegsCount: exam.StudentRegsCount, + Ntas: exam.Ntas, + MaxDuration: exam.MaxDuration, PlanEntry: planEntryMap[exam.Ancode], }) } From 204f5c9e4c720861dfd9fe3dd5483e6e6ea86a56 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Mon, 4 Dec 2023 21:24:41 +0100 Subject: [PATCH 43/78] fix zpa validation --- plexams/validate_zpa.go | 31 +++++++-- plexams/zpa_post.go | 139 ++++++++++++++++++++-------------------- 2 files changed, 95 insertions(+), 75 deletions(-) diff --git a/plexams/validate_zpa.go b/plexams/validate_zpa.go index 42fb1a6..8b4a50f 100644 --- a/plexams/validate_zpa.go +++ b/plexams/validate_zpa.go @@ -21,32 +21,49 @@ func (p *Plexams) ValidateZPADateTimes() error { examsMap[exam.AnCode] = exam } - plannedExams, err := p.ExamsInPlan(context.Background()) + plannedExams, err := p.PlannedExams(context.Background()) if err != nil { return err } problems := 0 + notPlannedByMe := 0 for _, plannedExam := range plannedExams { - zpaExam := examsMap[plannedExam.Exam.Ancode] - delete(examsMap, plannedExam.Exam.Ancode) + zpaExam := examsMap[plannedExam.ZpaExam.AnCode] + delete(examsMap, plannedExam.ZpaExam.AnCode) + + shouldHaveNoTimeAndDate := false + if plannedExam.Constraints != nil && plannedExam.Constraints.NotPlannedByMe { + shouldHaveNoTimeAndDate = true + notPlannedByMe++ + } - plannedExamDate := plannedExam.Slot.Starttime.Local().Format("2006-01-02") - plannedExamStarttime := plannedExam.Slot.Starttime.Local().Format("15:04:05") + if zpaExam == nil { + log.Error().Int("ancode", plannedExam.ZpaExam.AnCode).Str("examer", plannedExam.ZpaExam.MainExamer). + Str("module", plannedExam.ZpaExam.Module).Msg("zpa exam not found") + continue + } + + plannedExamDate := "-" + plannedExamStarttime := "-" + if !shouldHaveNoTimeAndDate && plannedExam.PlanEntry != nil { + plannedExamDate = plannedExam.PlanEntry.Starttime.Local().Format("2006-01-02") + plannedExamStarttime = plannedExam.PlanEntry.Starttime.Local().Format("15:04:05") + } if zpaExam.Date != plannedExamDate || zpaExam.Starttime != plannedExamStarttime { problems++ color.Red.Printf("wrong date for %d. %s: %s\nwant: %s %s\ngot: %s %s\n", - plannedExam.Exam.Ancode, plannedExam.Exam.ZpaExam.MainExamer, plannedExam.Exam.ZpaExam.Module, + plannedExam.ZpaExam.AnCode, plannedExam.ZpaExam.MainExamer, plannedExam.ZpaExam.Module, plannedExamDate, plannedExamStarttime, zpaExam.Date, zpaExam.Starttime) } } if problems == 0 { - color.Green.Printf("all %d planned exams in zpa with correct date/time\n", len(plannedExams)) + color.Green.Printf("all %d planned exams in zpa with correct date/time (%d not planned by me)\n", len(plannedExams), notPlannedByMe) } problems = 0 diff --git a/plexams/zpa_post.go b/plexams/zpa_post.go index 887bf6f..abe7fa3 100644 --- a/plexams/zpa_post.go +++ b/plexams/zpa_post.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "fmt" - "strings" set "github.com/deckarep/golang-set/v2" "github.com/obcode/plexams.go/graph/model" @@ -108,7 +107,7 @@ func (p *Plexams) UploadPlan(ctx context.Context, withRooms, withInvigilators, u return nil, err } - examsInPlan, err := p.ExamsInPlan(ctx) + plannedExams, err := p.PlannedExams(ctx) if err != nil { log.Error().Err(err).Msg("cannot get exam groups") return nil, err @@ -120,84 +119,88 @@ func (p *Plexams) UploadPlan(ctx context.Context, withRooms, withInvigilators, u } exams := make([]*model.ZPAExamPlan, 0) - for _, exam := range examsInPlan { + for _, exam := range plannedExams { + if exam.PlanEntry == nil { + continue + } if exam.Constraints != nil && exam.Constraints.NotPlannedByMe { continue } for _, ancodeNotToPublish := range doNotPublish { - if exam.Exam.Ancode == ancodeNotToPublish { + if exam.ZpaExam.AnCode == ancodeNotToPublish { continue } } - slot, err := p.SlotForAncode(ctx, exam.Exam.Ancode) - if err != nil { - log.Error().Err(err).Int("ancode", exam.Exam.Ancode).Msg("cannot get slot for ancode") - } - timeForAncode := p.getSlotTime(slot.DayNumber, slot.SlotNumber) - studentCount := 0 - for _, studentRegs := range exam.Exam.StudentRegs { - studentCount += len(studentRegs.StudentRegs) - } - + // slot, err := p.SlotForAncode(ctx, exam.Exam.Ancode) + // if err != nil { + // log.Error().Err(err).Int("ancode", exam.Exam.Ancode).Msg("cannot get slot for ancode") + // } + // timeForAncode := p.getSlotTime(slot.DayNumber, slot.SlotNumber) + // studentCount := 0 + // for _, studentRegs := range exam.Exam.StudentRegs { + // studentCount += len(studentRegs.StudentRegs) + // } + + // FIXME: with rooms -> zpa var rooms []*model.ZPAExamPlanRoom reserveInvigilatorID := 0 - if withInvigilators { - invigilator, err := p.GetInvigilatorInSlot(ctx, "reserve", slot.DayNumber, slot.SlotNumber) - if err != nil { - log.Error().Err(err).Int("ancode", exam.Exam.Ancode).Int("day", slot.DayNumber).Int("slot", slot.SlotNumber). - Msg("cannot get reserve invigilator for slot") - return nil, err - } - reserveInvigilatorID = invigilator.ID - } - - if withRooms { - roomsForAncode, err := p.dbClient.RoomsForAncode(ctx, exam.Exam.Ancode) - if err != nil { - log.Error().Err(err).Int("ancode", exam.Exam.Ancode).Msg("cannot get rooms for ancode") - } else { - if len(roomsForAncode) > 0 { - rooms = make([]*model.ZPAExamPlanRoom, 0, len(roomsForAncode)) - for _, roomForAncode := range roomsForAncode { - if roomForAncode.RoomName == "No Room" { - continue - } - - invigilatorID := 0 - if withInvigilators { - invigilator, err := p.GetInvigilatorInSlot(ctx, roomForAncode.RoomName, slot.DayNumber, slot.SlotNumber) - if err != nil { - log.Error().Err(err).Int("ancode", exam.Exam.Ancode).Str("room", roomForAncode.RoomName). - Msg("cannot get invigilator for room") - return nil, err - } - invigilatorID = invigilator.ID - } - - roomName := roomForAncode.RoomName - if strings.HasPrefix(roomName, "ONLINE") { - roomName = "ONLINE" - } - - rooms = append(rooms, &model.ZPAExamPlanRoom{ - RoomName: roomName, - InvigilatorID: invigilatorID, - Duration: roomForAncode.Duration, - IsReserve: roomForAncode.Reserve, - StudentCount: roomForAncode.SeatsPlanned, - IsHandicap: roomForAncode.Handicap, - }) - } - } - } - } + // if withInvigilators { + // invigilator, err := p.GetInvigilatorInSlot(ctx, "reserve", slot.DayNumber, slot.SlotNumber) + // if err != nil { + // log.Error().Err(err).Int("ancode", exam.Exam.Ancode).Int("day", slot.DayNumber).Int("slot", slot.SlotNumber). + // Msg("cannot get reserve invigilator for slot") + // return nil, err + // } + // reserveInvigilatorID = invigilator.ID + // } + + // if withRooms { + // roomsForAncode, err := p.dbClient.RoomsForAncode(ctx, exam.Exam.Ancode) + // if err != nil { + // log.Error().Err(err).Int("ancode", exam.Exam.Ancode).Msg("cannot get rooms for ancode") + // } else { + // if len(roomsForAncode) > 0 { + // rooms = make([]*model.ZPAExamPlanRoom, 0, len(roomsForAncode)) + // for _, roomForAncode := range roomsForAncode { + // if roomForAncode.RoomName == "No Room" { + // continue + // } + + // invigilatorID := 0 + // if withInvigilators { + // invigilator, err := p.GetInvigilatorInSlot(ctx, roomForAncode.RoomName, slot.DayNumber, slot.SlotNumber) + // if err != nil { + // log.Error().Err(err).Int("ancode", exam.Exam.Ancode).Str("room", roomForAncode.RoomName). + // Msg("cannot get invigilator for room") + // return nil, err + // } + // invigilatorID = invigilator.ID + // } + + // roomName := roomForAncode.RoomName + // if strings.HasPrefix(roomName, "ONLINE") { + // roomName = "ONLINE" + // } + + // rooms = append(rooms, &model.ZPAExamPlanRoom{ + // RoomName: roomName, + // InvigilatorID: invigilatorID, + // Duration: roomForAncode.Duration, + // IsReserve: roomForAncode.Reserve, + // StudentCount: roomForAncode.SeatsPlanned, + // IsHandicap: roomForAncode.Handicap, + // }) + // } + // } + // } + // } exams = append(exams, &model.ZPAExamPlan{ Semester: p.semester, - AnCode: exam.Exam.Ancode, - Date: timeForAncode.Format("02.01.2006"), - Time: timeForAncode.Format("15:04"), - StudentCount: studentCount, + AnCode: exam.ZpaExam.AnCode, + Date: exam.PlanEntry.Starttime.Local().Format("02.01.2006"), + Time: exam.PlanEntry.Starttime.Local().Format("15:04"), + StudentCount: exam.StudentRegsCount, ReserveInvigilatorID: reserveInvigilatorID, Rooms: rooms, }) From 4ec730300cee34191c530b109d5cbcc296c23dad Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Tue, 5 Dec 2023 20:24:58 +0100 Subject: [PATCH 44/78] csv export for MUC.DAI --- cmd/csv.go | 45 ++++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 2 ++ plexams/csv.go | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 cmd/csv.go create mode 100644 plexams/csv.go diff --git a/cmd/csv.go b/cmd/csv.go new file mode 100644 index 0000000..f2456f5 --- /dev/null +++ b/cmd/csv.go @@ -0,0 +1,45 @@ +package cmd + +import ( + "fmt" + "log" + "os" + + "github.com/spf13/cobra" +) + +var ( + csvCmd = &cobra.Command{ + Use: "csv", + Short: "csv [subcommand]", + Long: `Generate various CSVs. + draft [program] - generate csv for program`, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + plexams := initPlexamsConfig() + switch args[0] { + case "draft": + if len(args) < 2 { + log.Fatal("need program") + } + program := args[1] + if len(Outfile) == 0 { + Outfile = fmt.Sprintf("VorläufigePrüfungsplanung_FK07_%s.csv", program) + } + fmt.Printf("generating %s\n", Outfile) + err := plexams.CsvForProgram(program, Outfile) + if err != nil { + os.Exit(1) + } + + default: + fmt.Println("pdf called with unknown sub command") + } + }, + } + Csvfile string +) + +func init() { + rootCmd.AddCommand(csvCmd) +} diff --git a/go.mod b/go.mod index d97a89a..4d8d9b5 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/gookit/color v1.5.3 github.com/johnfercher/maroto v0.42.0 github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible + github.com/jszwec/csvutil v1.8.0 github.com/logrusorgru/aurora v2.0.3+incompatible github.com/mitchellh/go-homedir v1.1.0 github.com/rs/cors v1.9.0 diff --git a/go.sum b/go.sum index 93c726e..49cbcbd 100644 --- a/go.sum +++ b/go.sum @@ -164,6 +164,8 @@ github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jszwec/csvutil v1.8.0 h1:G7vS2LGdpZZDH1HmHeNbxOaJ/ZnJlpwGFvOkTkJzzNk= +github.com/jszwec/csvutil v1.8.0/go.mod h1:/E4ONrmGkwmWsk9ae9jpXnv9QT8pLHEPcCirMFhxG9I= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jung-kurt/gofpdf v1.16.2 h1:jgbatWHfRlPYiK85qgevsZTHviWXKwB1TTiKdz5PtRc= github.com/jung-kurt/gofpdf v1.16.2/go.mod h1:1hl7y57EsiPAkLbOwzpzqgx1A30nQCk/YmFV8S2vmK0= diff --git a/plexams/csv.go b/plexams/csv.go new file mode 100644 index 0000000..8df3515 --- /dev/null +++ b/plexams/csv.go @@ -0,0 +1,70 @@ +package plexams + +import ( + "context" + "os" + "sort" + + "github.com/jszwec/csvutil" + "github.com/rs/zerolog/log" +) + +type CsvExam struct { + Ancode int `csv:"Ancode"` + Module string `csv:"Modul"` + MainExamer string `csv:"Erstprüfer:in"` + ExamDate string `csv:"Termin"` +} + +func (p *Plexams) CsvForProgram(program, filename string) error { + ctx := context.Background() + exams, err := p.PlannedExamsForProgram(ctx, program, true) + if err != nil { + log.Error().Err(err).Str("program", program).Msg("cannot get planned exams for program") + return err + } + + csvExams := make(map[int]CsvExam, 0) + ancodes := make([]int, 0, len(exams)) + + for _, exam := range exams { + primussAncode := 0 + for _, primussExam := range exam.PrimussExams { + if primussExam.Exam.Program == program { + primussAncode = primussExam.Exam.AnCode + ancodes = append(ancodes, primussAncode) + break + } + } + + if primussAncode == 0 { + log.Error().Int("zpa ancode", exam.Ancode).Msg("primuss ancode not found") + } + + examDate := "fehlt" + if exam.PlanEntry != nil { + examDate = exam.PlanEntry.Starttime.Local().Format("02.01.06, 15:04 Uhr") + } + + csvExams[primussAncode] = CsvExam{ + Ancode: primussAncode, + Module: exam.ZpaExam.Module, + MainExamer: exam.ZpaExam.MainExamer, + ExamDate: examDate, + } + } + + sort.Ints(ancodes) + + csvExamsSlice := make([]CsvExam, 0, len(exams)) + for _, ancode := range ancodes { + csvExamsSlice = append(csvExamsSlice, csvExams[ancode]) + } + + b, err := csvutil.Marshal(csvExamsSlice) + if err != nil { + log.Error().Err(err).Msg("error when marshaling to csv") + } + + return os.WriteFile(filename, b, 0644) +} From af12e572f38dd28503c6d097eaf521f525145567 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Mon, 11 Dec 2023 21:31:36 +0100 Subject: [PATCH 45/78] exahm rooms from booked entries --- cmd/prepare.go | 10 +-- plexams/rooms.go | 155 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 153 insertions(+), 12 deletions(-) diff --git a/cmd/prepare.go b/cmd/prepare.go index 040a678..b846ead 100644 --- a/cmd/prepare.go +++ b/cmd/prepare.go @@ -171,11 +171,11 @@ var ( // os.Exit(1) // } - case "exams-in-plan": - err := plexams.PreparePlannedExams() - if err != nil { - os.Exit(1) - } + // case "exams-in-plan": + // err := plexams.PreparePlannedExams() + // if err != nil { + // os.Exit(1) + // } case "rooms-for-semester": err := plexams.PrepareRoomsForSemester() diff --git a/plexams/rooms.go b/plexams/rooms.go index 63bda1e..3307221 100644 --- a/plexams/rooms.go +++ b/plexams/rooms.go @@ -5,6 +5,7 @@ import ( "fmt" "math" "sort" + "time" set "github.com/deckarep/golang-set/v2" "github.com/obcode/plexams.go/db" @@ -13,6 +14,134 @@ import ( "github.com/spf13/viper" ) +type SlotNumber struct { + day, slot int +} + +/* +roomConstraints: + booked: + - date: 2024-01-22 + from: "14:00" + until: "17:00" + rooms: + - T3.015 + - T3.016 + - T3.017 + - T3.023 +*/ + +type BookedEntry struct { + From time.Time + Until time.Time + Rooms []string +} + +func (p *Plexams) ExahmRoomsFromBooked() ([]BookedEntry, error) { + bookedInfo := viper.Get("roomconstraints.booked") + + bookedInfoSlice, ok := bookedInfo.([]interface{}) + if !ok { + log.Error().Interface("booked info", bookedInfo).Msg("cannot convert booked info to slice") + return nil, fmt.Errorf("cannot convert booked info to slice") + } + + entries := make([]BookedEntry, 0, len(bookedInfoSlice)) + for _, bookedEntry := range bookedInfoSlice { + entry, ok := bookedEntry.(map[string]interface{}) + if !ok { + log.Error().Interface("booked entry", bookedEntry).Msg("cannot convert booked entry to map") + return nil, fmt.Errorf("cannot convert booked entry to map") + } + + rawDate, ok := entry["date"].(time.Time) + if !ok { + log.Error().Interface("date entry", entry["date"]).Msg("cannot convert date entry to string") + return nil, fmt.Errorf("cannot convert date entry to string") + } + rawFrom, ok := entry["from"].(string) + if !ok { + log.Error().Interface("date entry", entry["from"]).Msg("cannot convert from entry to string") + return nil, fmt.Errorf("cannot convert from entry to string") + } + rawUntil, ok := entry["until"].(string) + if !ok { + log.Error().Interface("date entry", entry["until"]).Msg("cannot convert until entry to string") + return nil, fmt.Errorf("cannot convert until entry to string") + } + + from, err := time.ParseInLocation("2006-01-02 15:04", fmt.Sprintf("%s %s", rawDate.Format("2006-01-02"), rawFrom), time.Local) + if err != nil { + log.Error().Err(err).Interface("date", rawDate).Str("time", rawFrom).Msg("cannot parse to time") + return nil, err + } + until, err := time.ParseInLocation("2006-01-02 15:04", fmt.Sprintf("%s %s", rawDate.Format("2006-01-02"), rawUntil), time.Local) + if err != nil { + log.Error().Err(err).Interface("date", rawDate).Str("time", rawFrom).Msg("cannot parse to time") + return nil, err + } + + rawRooms, ok := entry["rooms"].([]interface{}) + if !ok { + log.Error().Interface("rooms entry", entry["rooms"]).Msg("cannot convert rooms entry to []string") + return nil, fmt.Errorf("cannot convert rooms entry to []string") + } + + rooms := make([]string, 0, len(rawRooms)) + for _, rawRoom := range rawRooms { + room, ok := rawRoom.(string) + if !ok { + log.Error().Interface("room entry", rawRoom).Msg("cannot convert room entry to string") + return nil, fmt.Errorf("cannot convert room entry to string") + } + rooms = append(rooms, room) + } + + entries = append(entries, BookedEntry{ + From: from, + Until: until, + Rooms: rooms, + }) + + } + + return entries, nil +} + +func (p *Plexams) SlotsWithRoomsFromBookedEntries(bookedEntries []BookedEntry) (map[SlotNumber][]*model.Room, error) { + globalRooms, err := p.dbClient.GlobalRooms(context.Background()) + if err != nil { + log.Error().Err(err).Msg("cannot get global rooms") + return nil, err + } + + globalRoomsMap := make(map[string]*model.Room) + for _, room := range globalRooms { + globalRoomsMap[room.Name] = room + } + + slotsWithRooms := make(map[SlotNumber][]*model.Room) + + for _, slot := range p.semesterConfig.Slots { + for _, entry := range bookedEntries { + if entry.From.Before(slot.Starttime.Local()) && entry.Until.After(slot.Starttime.Local().Add(89*time.Minute)) { + rooms := make([]*model.Room, 0, len(entry.Rooms)) + for _, roomName := range entry.Rooms { + room, ok := globalRoomsMap[roomName] + if !ok { + log.Error().Str("room name", roomName).Msg("room not found") + return nil, fmt.Errorf("room %s not found", roomName) + } + rooms = append(rooms, room) + } + slotsWithRooms[SlotNumber{slot.DayNumber, slot.SlotNumber}] = rooms + } + } + } + + return slotsWithRooms, nil +} + func (p *Plexams) PrepareRoomsForSemester() error { globalRooms, err := p.dbClient.GlobalRooms(context.Background()) if err != nil { @@ -20,16 +149,16 @@ func (p *Plexams) PrepareRoomsForSemester() error { return err } - roomsForSlots := make(map[int][]*model.Room) + roomsForSlots := make(map[SlotNumber][]*model.Room) for _, room := range globalRooms { - if room.Name == "No Room" { + if room.Name == "No Room" || room.Exahm { continue } roomConstraints := viper.Get(fmt.Sprintf("roomConstraints.%s", room.Name)) if roomConstraints == nil { fmt.Printf("%s: no constraints found\n", room.Name) for _, slot := range p.semesterConfig.Slots { - slotNumber := slot.DayNumber*10 + slot.SlotNumber + slotNumber := SlotNumber{slot.DayNumber, slot.SlotNumber} slotEntry, ok := roomsForSlots[slotNumber] if !ok { slotEntry = []*model.Room{room} @@ -45,7 +174,7 @@ func (p *Plexams) PrepareRoomsForSemester() error { allowedSlotsSlice := allowedSlots.([]interface{}) for _, allowedSlot := range allowedSlotsSlice { allowedSlotSlice := allowedSlot.([]interface{}) - slotNumber := allowedSlotSlice[0].(int)*10 + allowedSlotSlice[1].(int) + slotNumber := SlotNumber{allowedSlotSlice[0].(int), allowedSlotSlice[1].(int)} slotEntry, ok := roomsForSlots[slotNumber] if !ok { slotEntry = []*model.Room{room} @@ -60,12 +189,24 @@ func (p *Plexams) PrepareRoomsForSemester() error { } } + bookedEntries, err := p.ExahmRoomsFromBooked() + if err != nil { + log.Error().Err(err).Msg("cannot get exahm rooms from booked") + return err + } + bookedRoomsMap, err := p.SlotsWithRoomsFromBookedEntries(bookedEntries) + if err != nil { + log.Error().Err(err).Msg("cannot get booked rooms map from booked entries") + return err + } + slotsWithRooms := make([]*model.SlotWithRooms, 0, len(roomsForSlots)) for slot, rooms := range roomsForSlots { - normalRooms, exahmRooms, labRooms, ntaRooms := splitRooms(rooms) + normalRooms, _, labRooms, ntaRooms := splitRooms(rooms) + exahmRooms := bookedRoomsMap[slot] slotsWithRooms = append(slotsWithRooms, &model.SlotWithRooms{ - DayNumber: slot / 10, - SlotNumber: slot % 10, + DayNumber: slot.day, + SlotNumber: slot.slot, NormalRooms: normalRooms, ExahmRooms: exahmRooms, LabRooms: labRooms, From 95d87e2f072bfa6954f42981cec04fde0a2d7e6b Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Fri, 15 Dec 2023 09:15:17 +0100 Subject: [PATCH 46/78] booked and room reservations --- plexams/rooms.go | 131 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 95 insertions(+), 36 deletions(-) diff --git a/plexams/rooms.go b/plexams/rooms.go index 3307221..74e0299 100644 --- a/plexams/rooms.go +++ b/plexams/rooms.go @@ -48,39 +48,18 @@ func (p *Plexams) ExahmRoomsFromBooked() ([]BookedEntry, error) { entries := make([]BookedEntry, 0, len(bookedInfoSlice)) for _, bookedEntry := range bookedInfoSlice { + from, until, err := fromUntil(bookedEntry) + if err != nil { + log.Error().Err(err).Interface("entry", bookedEntry).Msg("cannot convert entry to time") + return nil, err + } + entry, ok := bookedEntry.(map[string]interface{}) if !ok { log.Error().Interface("booked entry", bookedEntry).Msg("cannot convert booked entry to map") return nil, fmt.Errorf("cannot convert booked entry to map") } - rawDate, ok := entry["date"].(time.Time) - if !ok { - log.Error().Interface("date entry", entry["date"]).Msg("cannot convert date entry to string") - return nil, fmt.Errorf("cannot convert date entry to string") - } - rawFrom, ok := entry["from"].(string) - if !ok { - log.Error().Interface("date entry", entry["from"]).Msg("cannot convert from entry to string") - return nil, fmt.Errorf("cannot convert from entry to string") - } - rawUntil, ok := entry["until"].(string) - if !ok { - log.Error().Interface("date entry", entry["until"]).Msg("cannot convert until entry to string") - return nil, fmt.Errorf("cannot convert until entry to string") - } - - from, err := time.ParseInLocation("2006-01-02 15:04", fmt.Sprintf("%s %s", rawDate.Format("2006-01-02"), rawFrom), time.Local) - if err != nil { - log.Error().Err(err).Interface("date", rawDate).Str("time", rawFrom).Msg("cannot parse to time") - return nil, err - } - until, err := time.ParseInLocation("2006-01-02 15:04", fmt.Sprintf("%s %s", rawDate.Format("2006-01-02"), rawUntil), time.Local) - if err != nil { - log.Error().Err(err).Interface("date", rawDate).Str("time", rawFrom).Msg("cannot parse to time") - return nil, err - } - rawRooms, ok := entry["rooms"].([]interface{}) if !ok { log.Error().Interface("rooms entry", entry["rooms"]).Msg("cannot convert rooms entry to []string") @@ -168,13 +147,29 @@ func (p *Plexams) PrepareRoomsForSemester() error { roomsForSlots[slotNumber] = slotEntry } } else { - allowedSlots := viper.Get(fmt.Sprintf("roomConstraints.%s.allowedSlots", room.Name)) - if allowedSlots != nil { - fmt.Printf("%s: allowed slots found\n", room.Name) - allowedSlotsSlice := allowedSlots.([]interface{}) - for _, allowedSlot := range allowedSlotsSlice { - allowedSlotSlice := allowedSlot.([]interface{}) - slotNumber := SlotNumber{allowedSlotSlice[0].(int), allowedSlotSlice[1].(int)} + // R1.046: + // reservations: + // - date: 2024-01-24 + // from: 10:15 + // until: 12:15 + // - date: 2024-01-24 + // from: 14:15 + // until: 16:15 + reservations := viper.Get(fmt.Sprintf("roomConstraints.%s.reservations", room.Name)) + if reservations != nil { + fmt.Printf("%s: reservations found\n", room.Name) + reservationsSlice, ok := reservations.([]interface{}) + if !ok { + log.Error().Interface("reservations", reservations).Msg("cannot convert reservations to slice") + return fmt.Errorf("cannot convert reservations to slice") + } + reservedSlots, err := p.reservations2Slots(reservationsSlice) + if err != nil { + log.Error().Err(err).Msg("cannot convert reservations to slots") + return err + } + for _, slot := range reservedSlots.ToSlice() { + slotNumber := SlotNumber{slot.day, slot.slot} slotEntry, ok := roomsForSlots[slotNumber] if !ok { slotEntry = []*model.Room{room} @@ -183,8 +178,6 @@ func (p *Plexams) PrepareRoomsForSemester() error { } roomsForSlots[slotNumber] = slotEntry } - // } else { - // TODO: forbiddenSlots := viper.Get(fmt.Sprintf("roomConstraints.%s.forbiddenSlots", room.Name)) } } } @@ -217,6 +210,71 @@ func (p *Plexams) PrepareRoomsForSemester() error { return p.dbClient.SaveRooms(context.Background(), slotsWithRooms) } +func (p *Plexams) reservations2Slots(reservations []interface{}) (set.Set[SlotNumber], error) { + slots := set.NewSet[SlotNumber]() + for _, reservation := range reservations { + from, until, err := fromUntil(reservation) + if err != nil { + log.Error().Err(err).Interface("reservation", reservation).Msg("cannot convert reservation to time") + return nil, err + } + + fmt.Printf(" From: %v Until: %v\n", from, until) + + for _, slot := range p.semesterConfig.Slots { + if (from.Before(slot.Starttime.Local()) || from.Equal(slot.Starttime.Local())) && until.After(slot.Starttime.Local().Add(89*time.Minute)) { + fmt.Printf(" ---> add (%d, %d)\n", slot.DayNumber, slot.SlotNumber) + slots.Add(SlotNumber{slot.DayNumber, slot.SlotNumber}) + } + } + } + return slots, nil +} + +func fromUntil(dateEntry interface{}) (from time.Time, until time.Time, err error) { + from = time.Now() + until = time.Now() + + entry, ok := dateEntry.(map[string]interface{}) + if !ok { + err = fmt.Errorf("cannot convert date entry to map") + log.Error().Interface("date entry", dateEntry).Msg("cannot convert date entry to map") + return + } + + rawDate, ok := entry["date"].(time.Time) + if !ok { + err = fmt.Errorf("cannot convert date entry to string") + log.Error().Interface("date entry", entry["date"]).Msg("cannot convert date entry to string") + return + } + rawFrom, ok := entry["from"].(string) + if !ok { + err = fmt.Errorf("cannot convert from entry to string") + log.Error().Interface("date entry", entry["from"]).Msg("cannot convert from entry to string") + return + } + rawUntil, ok := entry["until"].(string) + if !ok { + err = fmt.Errorf("cannot convert until entry to string") + log.Error().Interface("date entry", entry["until"]).Msg("cannot convert until entry to string") + return + } + + from, err = time.ParseInLocation("2006-01-02 15:04", fmt.Sprintf("%s %s", rawDate.Format("2006-01-02"), rawFrom), time.Local) + if err != nil { + log.Error().Err(err).Interface("date", rawDate).Str("time", rawFrom).Msg("cannot parse to time") + return + } + until, err = time.ParseInLocation("2006-01-02 15:04", fmt.Sprintf("%s %s", rawDate.Format("2006-01-02"), rawUntil), time.Local) + if err != nil { + log.Error().Err(err).Interface("date", rawDate).Str("time", rawFrom).Msg("cannot parse to time") + return + } + + return +} + func splitRooms(rooms []*model.Room) ([]*model.Room, []*model.Room, []*model.Room, []*model.Room) { normalRooms := make([]*model.Room, 0) exahmRooms := make([]*model.Room, 0) @@ -313,6 +371,7 @@ func (p *Plexams) AddRoomToExam(ctx context.Context, input model.RoomForExamInpu // return room, nil // } +// TODO: rewrite me. func (p *Plexams) PrepareRoomForExams() error { ctx := context.Background() From 6e18cfbabf1ffaf5d5f86b3f8aae9122104c02f4 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Tue, 19 Dec 2023 21:08:32 +0100 Subject: [PATCH 47/78] rooms query --- db/rooms.go | 7 +- graph/generated/generated.go | 178 ++++++++++++++++++----------------- graph/query.graphqls | 2 +- graph/query.resolvers.go | 5 - graph/room.graphqls | 4 + graph/room.resolvers.go | 5 + plexams/plexams.go | 2 +- plexams/rooms.go | 4 +- 8 files changed, 105 insertions(+), 102 deletions(-) diff --git a/db/rooms.go b/db/rooms.go index d09148f..988b656 100644 --- a/db/rooms.go +++ b/db/rooms.go @@ -9,7 +9,7 @@ import ( "go.mongodb.org/mongo-driver/mongo/options" ) -func (db *DB) GlobalRooms(ctx context.Context) ([]*model.Room, error) { +func (db *DB) Rooms(ctx context.Context) ([]*model.Room, error) { collection := db.Client.Database("plexams").Collection(collectionRooms) findOptions := options.Find() @@ -32,11 +32,6 @@ func (db *DB) GlobalRooms(ctx context.Context) ([]*model.Room, error) { return rooms, nil } -func (db *DB) Rooms(ctx context.Context) ([]*model.Room, error) { - - return nil, nil -} - func (db *DB) SaveRooms(ctx context.Context, slotsWithRooms []*model.SlotWithRooms) error { collection := db.Client.Database(db.databaseName).Collection(collectionRooms) diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 8a2a91a..2fde245 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -698,7 +698,6 @@ type QueryResolver interface { PlannedExamsInSlot(ctx context.Context, day int, time int) ([]*model.PlannedExamWithNta, error) ExamsInPlan(ctx context.Context) ([]*model.ExamInPlan, error) ExamsInSlotWithRooms(ctx context.Context, day int, time int) ([]*model.ExamWithRegsAndRooms, error) - Rooms(ctx context.Context) ([]*model.Room, error) RoomsWithConstraints(ctx context.Context, handicap bool, lab bool, placesWithSocket bool, exahm *bool) ([]*model.Room, error) RoomsForSlot(ctx context.Context, day int, time int) (*model.SlotWithRooms, error) PlannedRoomNames(ctx context.Context) ([]string, error) @@ -728,6 +727,7 @@ type QueryResolver interface { AllowedSlots(ctx context.Context, ancode int) ([]*model.Slot, error) AwkwardSlots(ctx context.Context, ancode int) ([]*model.Slot, error) PrimussExams(ctx context.Context) ([]*model.PrimussExamByProgram, error) + Rooms(ctx context.Context) ([]*model.Room, error) StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, error) StudentsByName(ctx context.Context, regex string) ([]*model.Student, error) Students(ctx context.Context) ([]*model.Student, error) @@ -4385,7 +4385,7 @@ type ConflictsPerProgramAncode { # examsInSlot(day: Int!, time: Int!): [ExamInPlan!] # Rooms examsInSlotWithRooms(day: Int!, time: Int!): [ExamWithRegsAndRooms!] - rooms: [Room!]! + # rooms: [Room!]! roomsWithConstraints( handicap: Boolean! lab: Boolean! @@ -4403,7 +4403,11 @@ type ConflictsPerProgramAncode { dayOkForInvigilator(day: Int!, invigilatorID: Int!): Boolean } `, BuiltIn: false}, - {Name: "../room.graphqls", Input: `type Room { + {Name: "../room.graphqls", Input: `extend type Query { + rooms: [Room!]! +} + +type Room { name: String! seats: Int! handicap: Boolean! @@ -17431,68 +17435,6 @@ func (ec *executionContext) fieldContext_Query_examsInSlotWithRooms(ctx context. return fc, nil } -func (ec *executionContext) _Query_rooms(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_rooms(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Rooms(rctx) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.([]*model.Room) - fc.Result = res - return ec.marshalNRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomᚄ(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_rooms(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "name": - return ec.fieldContext_Room_name(ctx, field) - case "seats": - return ec.fieldContext_Room_seats(ctx, field) - case "handicap": - return ec.fieldContext_Room_handicap(ctx, field) - case "lab": - return ec.fieldContext_Room_lab(ctx, field) - case "placesWithSocket": - return ec.fieldContext_Room_placesWithSocket(ctx, field) - case "needsRequest": - return ec.fieldContext_Room_needsRequest(ctx, field) - case "exahm": - return ec.fieldContext_Room_exahm(ctx, field) - case "seb": - return ec.fieldContext_Room_seb(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type Room", field.Name) - }, - } - return fc, nil -} - func (ec *executionContext) _Query_roomsWithConstraints(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_roomsWithConstraints(ctx, field) if err != nil { @@ -19203,6 +19145,68 @@ func (ec *executionContext) fieldContext_Query_primussExams(ctx context.Context, return fc, nil } +func (ec *executionContext) _Query_rooms(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_rooms(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Rooms(rctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.Room) + fc.Result = res + return ec.marshalNRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_rooms(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext_Room_name(ctx, field) + case "seats": + return ec.fieldContext_Room_seats(ctx, field) + case "handicap": + return ec.fieldContext_Room_handicap(ctx, field) + case "lab": + return ec.fieldContext_Room_lab(ctx, field) + case "placesWithSocket": + return ec.fieldContext_Room_placesWithSocket(ctx, field) + case "needsRequest": + return ec.fieldContext_Room_needsRequest(ctx, field) + case "exahm": + return ec.fieldContext_Room_exahm(ctx, field) + case "seb": + return ec.fieldContext_Room_seb(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Room", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _Query_studentByMtknr(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_studentByMtknr(ctx, field) if err != nil { @@ -30520,28 +30524,6 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "rooms": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_rooms(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } - return res - } - - rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, - func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "roomsWithConstraints": field := field @@ -31120,6 +31102,28 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "rooms": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_rooms(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "studentByMtknr": field := field diff --git a/graph/query.graphqls b/graph/query.graphqls index 74fe3e8..ceaf825 100644 --- a/graph/query.graphqls +++ b/graph/query.graphqls @@ -33,7 +33,7 @@ type Query { # examsInSlot(day: Int!, time: Int!): [ExamInPlan!] # Rooms examsInSlotWithRooms(day: Int!, time: Int!): [ExamWithRegsAndRooms!] - rooms: [Room!]! + # rooms: [Room!]! roomsWithConstraints( handicap: Boolean! lab: Boolean! diff --git a/graph/query.resolvers.go b/graph/query.resolvers.go index 6431ed8..d797333 100644 --- a/graph/query.resolvers.go +++ b/graph/query.resolvers.go @@ -117,11 +117,6 @@ func (r *queryResolver) ExamsInSlotWithRooms(ctx context.Context, day int, time return r.plexams.ExamsInSlotWithRooms(ctx, day, time) } -// Rooms is the resolver for the rooms field. -func (r *queryResolver) Rooms(ctx context.Context) ([]*model.Room, error) { - return r.plexams.Rooms(ctx) -} - // RoomsWithConstraints is the resolver for the roomsWithConstraints field. func (r *queryResolver) RoomsWithConstraints(ctx context.Context, handicap bool, lab bool, placesWithSocket bool, exahm *bool) ([]*model.Room, error) { panic(fmt.Errorf("not implemented: RoomsWithConstraints - roomsWithConstraints")) diff --git a/graph/room.graphqls b/graph/room.graphqls index 5e91615..a0ca383 100644 --- a/graph/room.graphqls +++ b/graph/room.graphqls @@ -1,3 +1,7 @@ +extend type Query { + rooms: [Room!]! +} + type Room { name: String! seats: Int! diff --git a/graph/room.resolvers.go b/graph/room.resolvers.go index 37803e4..7243be2 100644 --- a/graph/room.resolvers.go +++ b/graph/room.resolvers.go @@ -11,6 +11,11 @@ import ( "github.com/obcode/plexams.go/graph/model" ) +// Rooms is the resolver for the rooms field. +func (r *queryResolver) Rooms(ctx context.Context) ([]*model.Room, error) { + return r.plexams.Rooms(ctx) +} + // Room is the resolver for the room field. func (r *roomForExamResolver) Room(ctx context.Context, obj *model.RoomForExam) (*model.Room, error) { return r.plexams.Room(ctx, obj) diff --git a/plexams/plexams.go b/plexams/plexams.go index 6ff6ae3..b338d2d 100644 --- a/plexams/plexams.go +++ b/plexams/plexams.go @@ -236,7 +236,7 @@ func (p *Plexams) PrintInfo() { } func (p *Plexams) setRoomInfo() { - rooms, err := p.dbClient.GlobalRooms(context.Background()) + rooms, err := p.dbClient.Rooms(context.Background()) if err != nil { log.Error().Err(err).Msg("cannot get global rooms") } diff --git a/plexams/rooms.go b/plexams/rooms.go index 74e0299..947649b 100644 --- a/plexams/rooms.go +++ b/plexams/rooms.go @@ -88,7 +88,7 @@ func (p *Plexams) ExahmRoomsFromBooked() ([]BookedEntry, error) { } func (p *Plexams) SlotsWithRoomsFromBookedEntries(bookedEntries []BookedEntry) (map[SlotNumber][]*model.Room, error) { - globalRooms, err := p.dbClient.GlobalRooms(context.Background()) + globalRooms, err := p.dbClient.Rooms(context.Background()) if err != nil { log.Error().Err(err).Msg("cannot get global rooms") return nil, err @@ -122,7 +122,7 @@ func (p *Plexams) SlotsWithRoomsFromBookedEntries(bookedEntries []BookedEntry) ( } func (p *Plexams) PrepareRoomsForSemester() error { - globalRooms, err := p.dbClient.GlobalRooms(context.Background()) + globalRooms, err := p.dbClient.Rooms(context.Background()) if err != nil { log.Error().Err(err).Msg("cannot get global rooms") return err From e4267a6310bc28d1248235ea0206ad2982dcd2a0 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Thu, 21 Dec 2023 20:00:50 +0100 Subject: [PATCH 48/78] ntas emails and rooms (WIP) --- cmd/email.go | 6 + cmd/prepare.go | 6 + db/collection.go | 8 +- db/plannedExams.go | 2 + graph/generated/generated.go | 599 +++++++++++++++++++++++++++ graph/model/models_gen.go | 12 + graph/room.graphqls | 15 + plexams/email.go | 72 ++++ plexams/plan.go | 1 + plexams/rooms.go | 56 +++ tmpl/handicapEmailRoomAlone.tmpl | 24 ++ tmpl/handicapEmailRoomAloneHTML.tmpl | 30 ++ 12 files changed, 827 insertions(+), 4 deletions(-) create mode 100644 tmpl/handicapEmailRoomAlone.tmpl create mode 100644 tmpl/handicapEmailRoomAloneHTML.tmpl diff --git a/cmd/email.go b/cmd/email.go index e92e455..35ec18a 100644 --- a/cmd/email.go +++ b/cmd/email.go @@ -14,6 +14,7 @@ var ( Short: "send email", Long: `Send emails. nta --- send emails to teachers about nta, +nta-with-room-alone --- send emails to students with room alone, primuss-data --- send emails to teachers about primuss data and nta.`, Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { @@ -24,6 +25,11 @@ primuss-data --- send emails to teachers about primuss data and nta.`, if err != nil { log.Fatalf("got error: %v\n", err) } + case "nta-with-room-alone": + err := plexams.SendHandicapsMailsNTARoomAlone(context.Background(), run) + if err != nil { + log.Fatalf("got error: %v\n", err) + } case "primuss-data": err := plexams.SendGeneratedExamMails(context.Background(), run) if err != nil { diff --git a/cmd/prepare.go b/cmd/prepare.go index b846ead..889a1ab 100644 --- a/cmd/prepare.go +++ b/cmd/prepare.go @@ -183,6 +183,12 @@ var ( os.Exit(1) } + case "rooms-for-ntas": + err := plexams.RoomsForNTAsWithRoomAlone() + if err != nil { + os.Exit(1) + } + case "rooms-for-exams": err := plexams.PrepareRoomForExams() if err != nil { diff --git a/db/collection.go b/db/collection.go index 9dc34e5..82d92d1 100644 --- a/db/collection.go +++ b/db/collection.go @@ -31,13 +31,13 @@ const ( collectionPrimussAncodes = "primuss_ancodes" - collectionExamsInPlan = "exams_in_plan" + collectionExamsInPlan = "exams_in_plan" // Deprecated: rm me - collectionCachedExams = "cached_exams" + collectionCachedExams = "cached_exams" // ? collectionGeneratedExams = "generated_exams" - collectionRooms = "rooms" - collectionRoomsPlanned = "rooms_planned" + collectionRooms = "rooms" + // collectionRoomsPlanned = "rooms_planned" collectionRoomsForExams = "rooms_for_exams" collectionInvigilatorRequirements = "invigilator_requirements" diff --git a/db/plannedExams.go b/db/plannedExams.go index 0c16821..8e6b888 100644 --- a/db/plannedExams.go +++ b/db/plannedExams.go @@ -8,6 +8,7 @@ import ( "go.mongodb.org/mongo-driver/bson" ) +// Deprecated: rm me func (db *DB) ExamsInSlot(ctx context.Context, day int, time int) ([]*model.ExamInPlan, error) { collection := db.getCollectionSemester(collectionExamsInPlan) @@ -34,6 +35,7 @@ func (db *DB) ExamsInSlot(ctx context.Context, day int, time int) ([]*model.Exam return exams, nil } +// TODO: rewrite me func (db *DB) PlannedExamsByMainExamer(ctx context.Context, examerID int) ([]*model.ExamInPlan, error) { collection := db.getCollectionSemester(collectionExamsInPlan) diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 2fde245..0a23613 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -361,6 +361,18 @@ type ComplexityRoot struct { Nta func(childComplexity int) int } + PlannedRoom struct { + Ancode func(childComplexity int) int + Duration func(childComplexity int) int + Handicap func(childComplexity int) int + HandicapRoomAlone func(childComplexity int) int + Ntas func(childComplexity int) int + Reserve func(childComplexity int) int + Room func(childComplexity int) int + SeatsPlanned func(childComplexity int) int + StudentCount func(childComplexity int) int + } + PrimussExam struct { AnCode func(childComplexity int) int ExamType func(childComplexity int) int @@ -2254,6 +2266,69 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PlannedExamWithNTA.Nta(childComplexity), true + case "PlannedRoom.ancode": + if e.complexity.PlannedRoom.Ancode == nil { + break + } + + return e.complexity.PlannedRoom.Ancode(childComplexity), true + + case "PlannedRoom.duration": + if e.complexity.PlannedRoom.Duration == nil { + break + } + + return e.complexity.PlannedRoom.Duration(childComplexity), true + + case "PlannedRoom.handicap": + if e.complexity.PlannedRoom.Handicap == nil { + break + } + + return e.complexity.PlannedRoom.Handicap(childComplexity), true + + case "PlannedRoom.handicapRoomAlone": + if e.complexity.PlannedRoom.HandicapRoomAlone == nil { + break + } + + return e.complexity.PlannedRoom.HandicapRoomAlone(childComplexity), true + + case "PlannedRoom.ntas": + if e.complexity.PlannedRoom.Ntas == nil { + break + } + + return e.complexity.PlannedRoom.Ntas(childComplexity), true + + case "PlannedRoom.reserve": + if e.complexity.PlannedRoom.Reserve == nil { + break + } + + return e.complexity.PlannedRoom.Reserve(childComplexity), true + + case "PlannedRoom.room": + if e.complexity.PlannedRoom.Room == nil { + break + } + + return e.complexity.PlannedRoom.Room(childComplexity), true + + case "PlannedRoom.seatsPlanned": + if e.complexity.PlannedRoom.SeatsPlanned == nil { + break + } + + return e.complexity.PlannedRoom.SeatsPlanned(childComplexity), true + + case "PlannedRoom.studentCount": + if e.complexity.PlannedRoom.StudentCount == nil { + break + } + + return e.complexity.PlannedRoom.StudentCount(childComplexity), true + case "PrimussExam.ancode": if e.complexity.PrimussExam.AnCode == nil { break @@ -4427,6 +4502,19 @@ type SlotWithRooms { ntaRooms: [Room!]! } +type PlannedRoom { + room: Room! + ancode: Int! + seatsPlanned: Int! + duration: Int! + handicap: Boolean! + handicapRoomAlone: Boolean! + reserve: Boolean! + studentCount: Int! + ntas: [NTA!] +} + +# Deprecated: rm me type RoomForExam { ancode: Int! room: Room @@ -4437,6 +4525,7 @@ type RoomForExam { students: [StudentReg!]! } +# Deprecated: rm me input RoomForExamInput { ancode: Int! day: Int! @@ -4448,6 +4537,7 @@ input RoomForExamInput { mktnrs: [String!] } +# Deprecated: rm me type RoomAndExam { room: RoomForExam! exam: ZPAExam! @@ -15429,6 +15519,439 @@ func (ec *executionContext) fieldContext_PlannedExamWithNTA_nta(ctx context.Cont return fc, nil } +func (ec *executionContext) _PlannedRoom_room(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedRoom_room(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Room, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Room) + fc.Result = res + return ec.marshalNRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoom(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedRoom_room(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedRoom", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext_Room_name(ctx, field) + case "seats": + return ec.fieldContext_Room_seats(ctx, field) + case "handicap": + return ec.fieldContext_Room_handicap(ctx, field) + case "lab": + return ec.fieldContext_Room_lab(ctx, field) + case "placesWithSocket": + return ec.fieldContext_Room_placesWithSocket(ctx, field) + case "needsRequest": + return ec.fieldContext_Room_needsRequest(ctx, field) + case "exahm": + return ec.fieldContext_Room_exahm(ctx, field) + case "seb": + return ec.fieldContext_Room_seb(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Room", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _PlannedRoom_ancode(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedRoom_ancode(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Ancode, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedRoom_ancode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedRoom", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PlannedRoom_seatsPlanned(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedRoom_seatsPlanned(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.SeatsPlanned, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedRoom_seatsPlanned(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedRoom", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PlannedRoom_duration(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedRoom_duration(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Duration, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedRoom_duration(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedRoom", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PlannedRoom_handicap(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedRoom_handicap(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Handicap, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedRoom_handicap(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedRoom", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PlannedRoom_handicapRoomAlone(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedRoom_handicapRoomAlone(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.HandicapRoomAlone, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedRoom_handicapRoomAlone(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedRoom", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PlannedRoom_reserve(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedRoom_reserve(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Reserve, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedRoom_reserve(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedRoom", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PlannedRoom_studentCount(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedRoom_studentCount(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.StudentCount, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedRoom_studentCount(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedRoom", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PlannedRoom_ntas(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedRoom_ntas(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Ntas, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.NTA) + fc.Result = res + return ec.marshalONTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedRoom_ntas(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedRoom", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext_NTA_name(ctx, field) + case "mtknr": + return ec.fieldContext_NTA_mtknr(ctx, field) + case "compensation": + return ec.fieldContext_NTA_compensation(ctx, field) + case "deltaDurationPercent": + return ec.fieldContext_NTA_deltaDurationPercent(ctx, field) + case "needsRoomAlone": + return ec.fieldContext_NTA_needsRoomAlone(ctx, field) + case "program": + return ec.fieldContext_NTA_program(ctx, field) + case "from": + return ec.fieldContext_NTA_from(ctx, field) + case "until": + return ec.fieldContext_NTA_until(ctx, field) + case "lastSemester": + return ec.fieldContext_NTA_lastSemester(ctx, field) + case "exams": + return ec.fieldContext_NTA_exams(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type NTA", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _PrimussExam_ancode(ctx context.Context, field graphql.CollectedField, obj *model.PrimussExam) (ret graphql.Marshaler) { fc, err := ec.fieldContext_PrimussExam_ancode(ctx, field) if err != nil { @@ -29857,6 +30380,82 @@ func (ec *executionContext) _PlannedExamWithNTA(ctx context.Context, sel ast.Sel return out } +var plannedRoomImplementors = []string{"PlannedRoom"} + +func (ec *executionContext) _PlannedRoom(ctx context.Context, sel ast.SelectionSet, obj *model.PlannedRoom) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, plannedRoomImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("PlannedRoom") + case "room": + out.Values[i] = ec._PlannedRoom_room(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "ancode": + out.Values[i] = ec._PlannedRoom_ancode(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "seatsPlanned": + out.Values[i] = ec._PlannedRoom_seatsPlanned(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "duration": + out.Values[i] = ec._PlannedRoom_duration(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "handicap": + out.Values[i] = ec._PlannedRoom_handicap(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "handicapRoomAlone": + out.Values[i] = ec._PlannedRoom_handicapRoomAlone(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "reserve": + out.Values[i] = ec._PlannedRoom_reserve(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "studentCount": + out.Values[i] = ec._PlannedRoom_studentCount(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "ntas": + out.Values[i] = ec._PlannedRoom_ntas(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var primussExamImplementors = []string{"PrimussExam"} func (ec *executionContext) _PrimussExam(ctx context.Context, sel ast.SelectionSet, obj *model.PrimussExam) graphql.Marshaler { diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index 735d634..f01ff86 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -285,6 +285,18 @@ type PlannedExamWithNta struct { Nta []*NTAWithRegs `json:"nta,omitempty"` } +type PlannedRoom struct { + Room *Room `json:"room"` + Ancode int `json:"ancode"` + SeatsPlanned int `json:"seatsPlanned"` + Duration int `json:"duration"` + Handicap bool `json:"handicap"` + HandicapRoomAlone bool `json:"handicapRoomAlone"` + Reserve bool `json:"reserve"` + StudentCount int `json:"studentCount"` + Ntas []*NTA `json:"ntas,omitempty"` +} + type PrimussExamAncode struct { Ancode int `json:"ancode"` Program string `json:"program"` diff --git a/graph/room.graphqls b/graph/room.graphqls index a0ca383..695dca5 100644 --- a/graph/room.graphqls +++ b/graph/room.graphqls @@ -22,6 +22,19 @@ type SlotWithRooms { ntaRooms: [Room!]! } +type PlannedRoom { + room: Room! + ancode: Int! + seatsPlanned: Int! + duration: Int! + handicap: Boolean! + handicapRoomAlone: Boolean! + reserve: Boolean! + studentCount: Int! + ntas: [NTA!] +} + +# Deprecated: rm me type RoomForExam { ancode: Int! room: Room @@ -32,6 +45,7 @@ type RoomForExam { students: [StudentReg!]! } +# Deprecated: rm me input RoomForExamInput { ancode: Int! day: Int! @@ -43,6 +57,7 @@ input RoomForExamInput { mktnrs: [String!] } +# Deprecated: rm me type RoomAndExam { room: RoomForExam! exam: ZPAExam! diff --git a/plexams/email.go b/plexams/email.go index 1a681b4..fec2282 100644 --- a/plexams/email.go +++ b/plexams/email.go @@ -263,6 +263,78 @@ func (p *Plexams) SendHandicapsMailToMainExamer(ctx context.Context, to []string ) } +type NTAEmail struct { + NTA *model.Student + Exams []*model.PlannedExam + PlanerName string +} + +func (p *Plexams) SendHandicapsMailsNTARoomAlone(ctx context.Context, run bool) error { + ntas, err := p.NtasWithRegs(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get ntas") + return err + } + for _, nta := range ntas { + if !nta.Nta.NeedsRoomAlone { + continue + } + + exams := make([]*model.PlannedExam, 0, len(nta.Regs)) + for _, ancode := range nta.Regs { + exam, err := p.PlannedExam(ctx, ancode) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("cannot get exam") + return err + } + if exam.Constraints == nil || !exam.Constraints.NotPlannedByMe { + exams = append(exams, exam) + } + } + + err = p.SendHandicapsMailToStudent(ctx, []string{p.planer.Email}, &NTAEmail{ + NTA: nta, + Exams: exams, + PlanerName: p.planer.Name, + }) + if err != nil { + return err + } + + } + return nil +} + +func (p *Plexams) SendHandicapsMailToStudent(ctx context.Context, to []string, handicapsEmail *NTAEmail) error { + log.Debug().Interface("to", to).Msg("sending email") + + tmpl, err := template.ParseFiles("tmpl/handicapEmailRoomAlone.tmpl") + if err != nil { + return err + } + bufText := new(bytes.Buffer) + err = tmpl.Execute(bufText, handicapsEmail) + if err != nil { + return err + } + + tmpl, err = template.ParseFiles("tmpl/handicapEmailRoomAloneHTML.tmpl") + if err != nil { + return err + } + bufHTML := new(bytes.Buffer) + err = tmpl.Execute(bufHTML, handicapsEmail) + if err != nil { + return err + } + + return p.sendMail(to, + fmt.Sprintf("[Prüfungsplanung %s] Eigener Raum für Ihre Prüfung(en)", p.semester), + bufText.Bytes(), + bufHTML.Bytes(), + ) +} + func (p *Plexams) sendMail(to []string, subject string, text []byte, html []byte) error { e := &email.Email{ To: to, diff --git a/plexams/plan.go b/plexams/plan.go index b10f8c4..7f2892b 100644 --- a/plexams/plan.go +++ b/plexams/plan.go @@ -258,6 +258,7 @@ func (p *Plexams) AncodesInPlan(ctx context.Context) ([]int, error) { return p.dbClient.AncodesInPlan(ctx) } +// Deprecated: rm me func (p *Plexams) ExamsInSlot(ctx context.Context, day int, time int) ([]*model.ExamInPlan, error) { return p.dbClient.ExamsInSlot(ctx, day, time) } diff --git a/plexams/rooms.go b/plexams/rooms.go index 947649b..02846cc 100644 --- a/plexams/rooms.go +++ b/plexams/rooms.go @@ -8,10 +8,12 @@ import ( "time" set "github.com/deckarep/golang-set/v2" + "github.com/logrusorgru/aurora" "github.com/obcode/plexams.go/db" "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" "github.com/spf13/viper" + "github.com/theckman/yacspin" ) type SlotNumber struct { @@ -135,7 +137,14 @@ func (p *Plexams) PrepareRoomsForSemester() error { } roomConstraints := viper.Get(fmt.Sprintf("roomConstraints.%s", room.Name)) if roomConstraints == nil { + + if room.NeedsRequest { + fmt.Printf("%s: no constraints found, but room needs request, ignoring room\n", room.Name) + continue + } + fmt.Printf("%s: no constraints found\n", room.Name) + for _, slot := range p.semesterConfig.Slots { slotNumber := SlotNumber{slot.DayNumber, slot.SlotNumber} slotEntry, ok := roomsForSlots[slotNumber] @@ -371,6 +380,53 @@ func (p *Plexams) AddRoomToExam(ctx context.Context, input model.RoomForExamInpu // return room, nil // } +func (p *Plexams) RoomsForNTAsWithRoomAlone() error { + ctx := context.Background() + ntas, err := p.NtasWithRegs(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get ntas") + return err + } + + for _, nta := range ntas { + if !nta.Nta.NeedsRoomAlone { + continue + } + + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Cyan(" finding rooms for %s with exams %v"), + aurora.Yellow(nta.Name), + aurora.Magenta(nta.Regs), + ), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + // TODO: finding rooms + + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + } + return nil +} + // TODO: rewrite me. func (p *Plexams) PrepareRoomForExams() error { ctx := context.Background() diff --git a/tmpl/handicapEmailRoomAlone.tmpl b/tmpl/handicapEmailRoomAlone.tmpl new file mode 100644 index 0000000..2690b1b --- /dev/null +++ b/tmpl/handicapEmailRoomAlone.tmpl @@ -0,0 +1,24 @@ +Sehr geehrte:r {{ .NTA.Name }}, + +Sie haben gemäß den mir vorliegenden Informationen Anspruch auf einen eigenen Raum +bei Ihren Prüfungen. + +Für folgende Prüfungen, für die Sie sich angemeldet haben, plane ich einen extra Raum ein: + +{{ range .Exams -}} +{{ .ZpaExam.MainExamer }}: {{ .ZpaExam.Module }} +{{ end }} + +Den Raum entnehmen Sie nach Abschluss der Raumplanung dem im ZPA veröffentlichten Prüfungsplan +unter https://zpa.cs.hm.edu/public/exam_plan/. +Im Zweifelsfall fragen Sie gerne bei mir nach. + +Wenn Sie frühzeitig wissen, dass Sie an einer der oben genannten Prüfungen nicht teilnehmen werden, +teilen Sie mir das bitte mit, damit ich die eingeteilte Aufsicht darüber informieren kann bzw. keinen extra +Raum mit Aufsicht planen muss. + +Mit freundlichen Grüßen +{{ .PlanerName }} + +-- +Diese E-Mail wurde generiert und gesendet von https://github.com/obcode/plexams.go diff --git a/tmpl/handicapEmailRoomAloneHTML.tmpl b/tmpl/handicapEmailRoomAloneHTML.tmpl new file mode 100644 index 0000000..8c983ee --- /dev/null +++ b/tmpl/handicapEmailRoomAloneHTML.tmpl @@ -0,0 +1,30 @@ +

Sehr geehrte:r {{ .NTA.Name }},

+ +

Sie haben gemäß den mir vorliegenden Informationen Anspruch auf einen eigenen Raum +bei Ihren Prüfungen.

+ +

Für folgende Prüfungen, für die Sie sich angemeldet haben, plane ich einen extra Raum ein:

+ +
    +{{ range .Exams -}} +
  • +{{ .ZpaExam.MainExamer }}: {{ .ZpaExam.Module }} +
  • +{{ end }} +
+ +

Den Raum entnehmen Sie nach Abschluss der Raumplanung dem im ZPA veröffentlichten Prüfungsplan +unter https://zpa.cs.hm.edu/public/exam_plan/. +Im Zweifelsfall fragen Sie gerne bei mir nach.

+ +

Wenn Sie frühzeitig wissen, dass Sie an einer der oben genannten Prüfungen nicht teilnehmen werden, +teilen Sie mir das bitte mit, damit ich die eingeteilte Aufsicht darüber informieren kann bzw. keinen extra +Raum mit Aufsicht planen muss.

+ +

Mit freundlichen Grüßen
+{{ .PlanerName }}

+ +
+-- 
+Diese E-Mail wurde generiert und gesendet von https://github.com/obcode/plexams.go
+
From ee9dac134d10d0129d0460fc9d88e3763994e9f8 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Thu, 21 Dec 2023 22:06:26 +0100 Subject: [PATCH 49/78] =?UTF-8?q?=F0=9F=9A=A7=20rooms=20for=20ntas=20with?= =?UTF-8?q?=20extra=20room?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- graph/generated/generated.go | 167 ++++++++++++++++++++++++----------- graph/model/models_gen.go | 3 +- graph/room.graphqls | 3 +- plexams/rooms.go | 154 +++++++++++++++++++++++++++++++- 4 files changed, 268 insertions(+), 59 deletions(-) diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 0a23613..372a843 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -363,6 +363,7 @@ type ComplexityRoot struct { PlannedRoom struct { Ancode func(childComplexity int) int + Day func(childComplexity int) int Duration func(childComplexity int) int Handicap func(childComplexity int) int HandicapRoomAlone func(childComplexity int) int @@ -370,7 +371,7 @@ type ComplexityRoot struct { Reserve func(childComplexity int) int Room func(childComplexity int) int SeatsPlanned func(childComplexity int) int - StudentCount func(childComplexity int) int + Slot func(childComplexity int) int } PrimussExam struct { @@ -2273,6 +2274,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PlannedRoom.Ancode(childComplexity), true + case "PlannedRoom.day": + if e.complexity.PlannedRoom.Day == nil { + break + } + + return e.complexity.PlannedRoom.Day(childComplexity), true + case "PlannedRoom.duration": if e.complexity.PlannedRoom.Duration == nil { break @@ -2322,12 +2330,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PlannedRoom.SeatsPlanned(childComplexity), true - case "PlannedRoom.studentCount": - if e.complexity.PlannedRoom.StudentCount == nil { + case "PlannedRoom.slot": + if e.complexity.PlannedRoom.Slot == nil { break } - return e.complexity.PlannedRoom.StudentCount(childComplexity), true + return e.complexity.PlannedRoom.Slot(childComplexity), true case "PrimussExam.ancode": if e.complexity.PrimussExam.AnCode == nil { @@ -4503,6 +4511,8 @@ type SlotWithRooms { } type PlannedRoom { + day: Int! + slot: Int! room: Room! ancode: Int! seatsPlanned: Int! @@ -4510,7 +4520,7 @@ type PlannedRoom { handicap: Boolean! handicapRoomAlone: Boolean! reserve: Boolean! - studentCount: Int! + # studentCount: Int! ntas: [NTA!] } @@ -15519,6 +15529,94 @@ func (ec *executionContext) fieldContext_PlannedExamWithNTA_nta(ctx context.Cont return fc, nil } +func (ec *executionContext) _PlannedRoom_day(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedRoom_day(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Day, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedRoom_day(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedRoom", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _PlannedRoom_slot(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedRoom_slot(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Slot, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedRoom_slot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedRoom", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _PlannedRoom_room(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { fc, err := ec.fieldContext_PlannedRoom_room(ctx, field) if err != nil { @@ -15845,50 +15943,6 @@ func (ec *executionContext) fieldContext_PlannedRoom_reserve(ctx context.Context return fc, nil } -func (ec *executionContext) _PlannedRoom_studentCount(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_PlannedRoom_studentCount(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.StudentCount, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int) - fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_PlannedRoom_studentCount(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "PlannedRoom", - Field: field, - IsMethod: false, - IsResolver: false, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") - }, - } - return fc, nil -} - func (ec *executionContext) _PlannedRoom_ntas(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { fc, err := ec.fieldContext_PlannedRoom_ntas(ctx, field) if err != nil { @@ -30391,6 +30445,16 @@ func (ec *executionContext) _PlannedRoom(ctx context.Context, sel ast.SelectionS switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("PlannedRoom") + case "day": + out.Values[i] = ec._PlannedRoom_day(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "slot": + out.Values[i] = ec._PlannedRoom_slot(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } case "room": out.Values[i] = ec._PlannedRoom_room(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -30426,11 +30490,6 @@ func (ec *executionContext) _PlannedRoom(ctx context.Context, sel ast.SelectionS if out.Values[i] == graphql.Null { out.Invalids++ } - case "studentCount": - out.Values[i] = ec._PlannedRoom_studentCount(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } case "ntas": out.Values[i] = ec._PlannedRoom_ntas(ctx, field, obj) default: diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index f01ff86..e46d353 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -286,6 +286,8 @@ type PlannedExamWithNta struct { } type PlannedRoom struct { + Day int `json:"day"` + Slot int `json:"slot"` Room *Room `json:"room"` Ancode int `json:"ancode"` SeatsPlanned int `json:"seatsPlanned"` @@ -293,7 +295,6 @@ type PlannedRoom struct { Handicap bool `json:"handicap"` HandicapRoomAlone bool `json:"handicapRoomAlone"` Reserve bool `json:"reserve"` - StudentCount int `json:"studentCount"` Ntas []*NTA `json:"ntas,omitempty"` } diff --git a/graph/room.graphqls b/graph/room.graphqls index 695dca5..e0b0d5f 100644 --- a/graph/room.graphqls +++ b/graph/room.graphqls @@ -23,6 +23,8 @@ type SlotWithRooms { } type PlannedRoom { + day: Int! + slot: Int! room: Room! ancode: Int! seatsPlanned: Int! @@ -30,7 +32,6 @@ type PlannedRoom { handicap: Boolean! handicapRoomAlone: Boolean! reserve: Boolean! - studentCount: Int! ntas: [NTA!] } diff --git a/plexams/rooms.go b/plexams/rooms.go index 02846cc..66927bc 100644 --- a/plexams/rooms.go +++ b/plexams/rooms.go @@ -388,6 +388,17 @@ func (p *Plexams) RoomsForNTAsWithRoomAlone() error { return err } + ntasMap := make(map[string]*model.Student) + type dayEntry struct { + slot int + ancode int + mtknr string + } + daysMap := make(map[int][]dayEntry) + examsMap := make(map[int]*model.PlannedExam) + + plannedRooms := make([]*model.PlannedRoom, 0) + for _, nta := range ntas { if !nta.Nta.NeedsRoomAlone { continue @@ -396,9 +407,9 @@ func (p *Plexams) RoomsForNTAsWithRoomAlone() error { cfg := yacspin.Config{ Frequency: 100 * time.Millisecond, CharSet: yacspin.CharSets[69], - Suffix: aurora.Sprintf(aurora.Cyan(" finding rooms for %s with exams %v"), + Suffix: aurora.Sprintf(aurora.Cyan("finding exams for %s (%s)"), aurora.Yellow(nta.Name), - aurora.Magenta(nta.Regs), + aurora.Green(nta.Mtknr), ), SuffixAutoColon: true, StopCharacter: "✓", @@ -417,13 +428,150 @@ func (p *Plexams) RoomsForNTAsWithRoomAlone() error { log.Debug().Err(err).Msg("cannot start spinner") } - // TODO: finding rooms + ntasMap[nta.Mtknr] = nta + + regsNew := make([]int, 0, len(nta.Regs)) + for _, ancode := range nta.Regs { + exam, err := p.PlannedExam(ctx, ancode) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("cannot get exam") + return err + } + if exam.Constraints == nil || !exam.Constraints.NotPlannedByMe { + examsMap[exam.Ancode] = exam + dayEntries, ok := daysMap[exam.PlanEntry.DayNumber] + if !ok { + dayEntries = make([]dayEntry, 0, 1) + } + daysMap[exam.PlanEntry.DayNumber] = append(dayEntries, dayEntry{ + slot: exam.PlanEntry.SlotNumber, + ancode: ancode, + mtknr: nta.Mtknr, + }) + regsNew = append(regsNew, ancode) + } + } + + nta.Regs = regsNew + + spinner.StopMessage(aurora.Sprintf(aurora.Cyan("found %v"), + aurora.Magenta(nta.Regs), + )) err = spinner.Stop() if err != nil { log.Debug().Err(err).Msg("cannot stop spinner") } } + + days := make([]int, 0, len(daysMap)) + for day := range daysMap { + days = append(days, day) + } + sort.Ints(days) + + for _, day := range days { + entries := daysMap[day] + if len(entries) == 1 { + fmt.Printf("day %2d: only one room needed: %v", day, entries[0]) + rooms, err := p.RoomsForSlot(ctx, day, entries[0].slot) + if err != nil { + log.Error().Err(err).Int("day", day).Int("slot", entries[0].slot).Msg("no rooms for slot found") + } + room := rooms.NtaRooms[0] + fmt.Printf(" -> using %s\n", room.Name) + + exam := examsMap[entries[0].ancode] + nta := ntasMap[entries[0].mtknr] + + ntaDuration := int(math.Ceil(float64(exam.ZpaExam.Duration*(100+nta.Nta.DeltaDurationPercent)) / 100)) + + plannedRooms = append(plannedRooms, &model.PlannedRoom{ + Day: day, + Slot: entries[0].slot, + Room: room, + Ancode: entries[0].ancode, + SeatsPlanned: 1, + Duration: ntaDuration, + Handicap: true, + HandicapRoomAlone: true, + Reserve: false, + Ntas: []*model.NTA{nta.Nta}, + }) + } else { + fmt.Printf("day %2d: more than one room needed: %v\n", day, entries) + slotsMap := make(map[int][]dayEntry) + for _, entry := range entries { + slotEntries, ok := slotsMap[entry.slot] + if !ok { + slotEntries = make([]dayEntry, 0, 1) + } + slotsMap[entry.slot] = append(slotEntries, entry) + } + + slots := make([]int, 0, len(slotsMap)) + for slot := range slotsMap { + slots = append(slots, slot) + } + sort.Ints(slots) + + prevSlot := -100 + roomsInPrevSlot := set.NewSet[string]() + for _, slot := range slots { + roomsInSlot := set.NewSet[string]() + if prevSlot+1 < slot { + roomsInPrevSlot = set.NewSet[string]() + } + + slotEntries := slotsMap[slot] + rooms, err := p.RoomsForSlot(ctx, day, slot) + if err != nil { + log.Error().Err(err).Int("day", day).Int("slot", slotEntries[0].slot).Msg("no rooms for slot found") + } + + fmt.Printf(" %d entries in slot %d\n", len(slotEntries), slot) + + for _, slotEntry := range slotEntries { + for _, room := range rooms.NtaRooms { + if roomsInPrevSlot.Contains(room.Name) || roomsInSlot.Contains(room.Name) { + continue + } + roomsInSlot.Add(room.Name) + fmt.Printf(" -> using %s for %v\n", room.Name, slotEntry) + exam := examsMap[slotEntry.ancode] + nta := ntasMap[slotEntry.mtknr] + + ntaDuration := int(math.Ceil(float64(exam.ZpaExam.Duration*(100+nta.Nta.DeltaDurationPercent)) / 100)) + + plannedRooms = append(plannedRooms, &model.PlannedRoom{ + Day: day, + Slot: slot, + Room: room, + Ancode: slotEntry.ancode, + SeatsPlanned: 1, + Duration: ntaDuration, + Handicap: true, + HandicapRoomAlone: true, + Reserve: false, + Ntas: []*model.NTA{nta.Nta}, + }) + break + } + } + + prevSlot = slot + roomsInPrevSlot = roomsInSlot + } + } + } + + for _, plannedRoom := range plannedRooms { + exam := examsMap[plannedRoom.Ancode] + fmt.Printf("[%d/%d] %d. %s (%s), Raum %s für %s (%d Minuten)\n", plannedRoom.Day, plannedRoom.Slot, + exam.Ancode, exam.ZpaExam.Module, exam.ZpaExam.MainExamer, + plannedRoom.Room.Name, plannedRoom.Ntas[0].Name, plannedRoom.Duration, + ) + } return nil } From 0994b5dbbc4ad009a3d582e8828bdda8fd3f74f9 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Fri, 22 Dec 2023 12:37:39 +0100 Subject: [PATCH 50/78] save and replace rooms for nta (alone) --- db/collection.go | 6 +-- db/rooms.go | 27 ++++++++++ graph/generated/generated.go | 97 +++++++++++------------------------- graph/model/models_gen.go | 20 ++++---- graph/room.graphqls | 4 +- plexams/rooms.go | 14 +++--- 6 files changed, 77 insertions(+), 91 deletions(-) diff --git a/db/collection.go b/db/collection.go index 82d92d1..1e248bd 100644 --- a/db/collection.go +++ b/db/collection.go @@ -36,9 +36,9 @@ const ( collectionCachedExams = "cached_exams" // ? collectionGeneratedExams = "generated_exams" - collectionRooms = "rooms" - // collectionRoomsPlanned = "rooms_planned" - collectionRoomsForExams = "rooms_for_exams" + collectionRooms = "rooms" + collectionRoomsPlanned = "rooms_planned" + collectionRoomsForExams = "rooms_for_exams" // Deprecated: ? collectionInvigilatorRequirements = "invigilator_requirements" collectionOtherInvigilations = "invigilations_other" diff --git a/db/rooms.go b/db/rooms.go index 988b656..630b511 100644 --- a/db/rooms.go +++ b/db/rooms.go @@ -190,3 +190,30 @@ func (db *DB) PlannedRoomNames(ctx context.Context) ([]string, error) { return names, nil } + +func (db *DB) ReplaceRoomsForNTA(ctx context.Context, plannedRooms []*model.PlannedRoom) error { + collection := db.getCollectionSemester(collectionRoomsPlanned) + + for _, room := range plannedRooms { + log.Debug().Int("day", room.Day).Int("slot", room.Slot).Int("ancode", room.Ancode). + Msg("replacing room") + + filter := bson.M{ + "$and": []bson.M{ + {"ancode": room.Ancode}, + {"ntamtknr": room.NtaMtknr}, + }, + } + opts := options.Replace().SetUpsert(true) + + _, err := collection.ReplaceOne(ctx, filter, room, opts) + + if err != nil { + log.Error().Err(err).Int("day", room.Day).Int("slot", room.Slot).Int("ancode", room.Ancode). + Msg("cannot replace room") + return err + } + } + + return nil +} diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 372a843..4a6f373 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -367,9 +367,9 @@ type ComplexityRoot struct { Duration func(childComplexity int) int Handicap func(childComplexity int) int HandicapRoomAlone func(childComplexity int) int - Ntas func(childComplexity int) int + NtaMtknr func(childComplexity int) int Reserve func(childComplexity int) int - Room func(childComplexity int) int + RoomName func(childComplexity int) int SeatsPlanned func(childComplexity int) int Slot func(childComplexity int) int } @@ -2302,12 +2302,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PlannedRoom.HandicapRoomAlone(childComplexity), true - case "PlannedRoom.ntas": - if e.complexity.PlannedRoom.Ntas == nil { + case "PlannedRoom.ntaMtknr": + if e.complexity.PlannedRoom.NtaMtknr == nil { break } - return e.complexity.PlannedRoom.Ntas(childComplexity), true + return e.complexity.PlannedRoom.NtaMtknr(childComplexity), true case "PlannedRoom.reserve": if e.complexity.PlannedRoom.Reserve == nil { @@ -2316,12 +2316,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PlannedRoom.Reserve(childComplexity), true - case "PlannedRoom.room": - if e.complexity.PlannedRoom.Room == nil { + case "PlannedRoom.roomName": + if e.complexity.PlannedRoom.RoomName == nil { break } - return e.complexity.PlannedRoom.Room(childComplexity), true + return e.complexity.PlannedRoom.RoomName(childComplexity), true case "PlannedRoom.seatsPlanned": if e.complexity.PlannedRoom.SeatsPlanned == nil { @@ -4513,15 +4513,14 @@ type SlotWithRooms { type PlannedRoom { day: Int! slot: Int! - room: Room! + roomName: String! ancode: Int! seatsPlanned: Int! duration: Int! handicap: Boolean! handicapRoomAlone: Boolean! reserve: Boolean! - # studentCount: Int! - ntas: [NTA!] + ntaMtknr: String } # Deprecated: rm me @@ -15617,8 +15616,8 @@ func (ec *executionContext) fieldContext_PlannedRoom_slot(ctx context.Context, f return fc, nil } -func (ec *executionContext) _PlannedRoom_room(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_PlannedRoom_room(ctx, field) +func (ec *executionContext) _PlannedRoom_roomName(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedRoom_roomName(ctx, field) if err != nil { return graphql.Null } @@ -15631,7 +15630,7 @@ func (ec *executionContext) _PlannedRoom_room(ctx context.Context, field graphql }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Room, nil + return obj.RoomName, nil }) if err != nil { ec.Error(ctx, err) @@ -15643,37 +15642,19 @@ func (ec *executionContext) _PlannedRoom_room(ctx context.Context, field graphql } return graphql.Null } - res := resTmp.(*model.Room) + res := resTmp.(string) fc.Result = res - return ec.marshalNRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoom(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_PlannedRoom_room(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_PlannedRoom_roomName(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "PlannedRoom", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "name": - return ec.fieldContext_Room_name(ctx, field) - case "seats": - return ec.fieldContext_Room_seats(ctx, field) - case "handicap": - return ec.fieldContext_Room_handicap(ctx, field) - case "lab": - return ec.fieldContext_Room_lab(ctx, field) - case "placesWithSocket": - return ec.fieldContext_Room_placesWithSocket(ctx, field) - case "needsRequest": - return ec.fieldContext_Room_needsRequest(ctx, field) - case "exahm": - return ec.fieldContext_Room_exahm(ctx, field) - case "seb": - return ec.fieldContext_Room_seb(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type Room", field.Name) + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil @@ -15943,8 +15924,8 @@ func (ec *executionContext) fieldContext_PlannedRoom_reserve(ctx context.Context return fc, nil } -func (ec *executionContext) _PlannedRoom_ntas(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_PlannedRoom_ntas(ctx, field) +func (ec *executionContext) _PlannedRoom_ntaMtknr(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedRoom_ntaMtknr(ctx, field) if err != nil { return graphql.Null } @@ -15957,7 +15938,7 @@ func (ec *executionContext) _PlannedRoom_ntas(ctx context.Context, field graphql }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Ntas, nil + return obj.NtaMtknr, nil }) if err != nil { ec.Error(ctx, err) @@ -15966,41 +15947,19 @@ func (ec *executionContext) _PlannedRoom_ntas(ctx context.Context, field graphql if resTmp == nil { return graphql.Null } - res := resTmp.([]*model.NTA) + res := resTmp.(*string) fc.Result = res - return ec.marshalONTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAᚄ(ctx, field.Selections, res) + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_PlannedRoom_ntas(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_PlannedRoom_ntaMtknr(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "PlannedRoom", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "name": - return ec.fieldContext_NTA_name(ctx, field) - case "mtknr": - return ec.fieldContext_NTA_mtknr(ctx, field) - case "compensation": - return ec.fieldContext_NTA_compensation(ctx, field) - case "deltaDurationPercent": - return ec.fieldContext_NTA_deltaDurationPercent(ctx, field) - case "needsRoomAlone": - return ec.fieldContext_NTA_needsRoomAlone(ctx, field) - case "program": - return ec.fieldContext_NTA_program(ctx, field) - case "from": - return ec.fieldContext_NTA_from(ctx, field) - case "until": - return ec.fieldContext_NTA_until(ctx, field) - case "lastSemester": - return ec.fieldContext_NTA_lastSemester(ctx, field) - case "exams": - return ec.fieldContext_NTA_exams(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type NTA", field.Name) + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil @@ -30455,8 +30414,8 @@ func (ec *executionContext) _PlannedRoom(ctx context.Context, sel ast.SelectionS if out.Values[i] == graphql.Null { out.Invalids++ } - case "room": - out.Values[i] = ec._PlannedRoom_room(ctx, field, obj) + case "roomName": + out.Values[i] = ec._PlannedRoom_roomName(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } @@ -30490,8 +30449,8 @@ func (ec *executionContext) _PlannedRoom(ctx context.Context, sel ast.SelectionS if out.Values[i] == graphql.Null { out.Invalids++ } - case "ntas": - out.Values[i] = ec._PlannedRoom_ntas(ctx, field, obj) + case "ntaMtknr": + out.Values[i] = ec._PlannedRoom_ntaMtknr(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index e46d353..1f8f319 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -286,16 +286,16 @@ type PlannedExamWithNta struct { } type PlannedRoom struct { - Day int `json:"day"` - Slot int `json:"slot"` - Room *Room `json:"room"` - Ancode int `json:"ancode"` - SeatsPlanned int `json:"seatsPlanned"` - Duration int `json:"duration"` - Handicap bool `json:"handicap"` - HandicapRoomAlone bool `json:"handicapRoomAlone"` - Reserve bool `json:"reserve"` - Ntas []*NTA `json:"ntas,omitempty"` + Day int `json:"day"` + Slot int `json:"slot"` + RoomName string `json:"roomName"` + Ancode int `json:"ancode"` + SeatsPlanned int `json:"seatsPlanned"` + Duration int `json:"duration"` + Handicap bool `json:"handicap"` + HandicapRoomAlone bool `json:"handicapRoomAlone"` + Reserve bool `json:"reserve"` + NtaMtknr *string `json:"ntaMtknr,omitempty"` } type PrimussExamAncode struct { diff --git a/graph/room.graphqls b/graph/room.graphqls index e0b0d5f..95a4eaa 100644 --- a/graph/room.graphqls +++ b/graph/room.graphqls @@ -25,14 +25,14 @@ type SlotWithRooms { type PlannedRoom { day: Int! slot: Int! - room: Room! + roomName: String! ancode: Int! seatsPlanned: Int! duration: Int! handicap: Boolean! handicapRoomAlone: Boolean! reserve: Boolean! - ntas: [NTA!] + ntaMtknr: String } # Deprecated: rm me diff --git a/plexams/rooms.go b/plexams/rooms.go index 66927bc..8e88007 100644 --- a/plexams/rooms.go +++ b/plexams/rooms.go @@ -489,14 +489,14 @@ func (p *Plexams) RoomsForNTAsWithRoomAlone() error { plannedRooms = append(plannedRooms, &model.PlannedRoom{ Day: day, Slot: entries[0].slot, - Room: room, + RoomName: room.Name, Ancode: entries[0].ancode, SeatsPlanned: 1, Duration: ntaDuration, Handicap: true, HandicapRoomAlone: true, Reserve: false, - Ntas: []*model.NTA{nta.Nta}, + NtaMtknr: &nta.Nta.Mtknr, }) } else { fmt.Printf("day %2d: more than one room needed: %v\n", day, entries) @@ -546,14 +546,14 @@ func (p *Plexams) RoomsForNTAsWithRoomAlone() error { plannedRooms = append(plannedRooms, &model.PlannedRoom{ Day: day, Slot: slot, - Room: room, + RoomName: room.Name, Ancode: slotEntry.ancode, SeatsPlanned: 1, Duration: ntaDuration, Handicap: true, HandicapRoomAlone: true, Reserve: false, - Ntas: []*model.NTA{nta.Nta}, + NtaMtknr: &nta.Nta.Mtknr, }) break } @@ -567,12 +567,12 @@ func (p *Plexams) RoomsForNTAsWithRoomAlone() error { for _, plannedRoom := range plannedRooms { exam := examsMap[plannedRoom.Ancode] - fmt.Printf("[%d/%d] %d. %s (%s), Raum %s für %s (%d Minuten)\n", plannedRoom.Day, plannedRoom.Slot, + fmt.Printf("(%d/%d) %d. %s (%s), Raum %s für %s (%d Minuten)\n", plannedRoom.Day, plannedRoom.Slot, exam.Ancode, exam.ZpaExam.Module, exam.ZpaExam.MainExamer, - plannedRoom.Room.Name, plannedRoom.Ntas[0].Name, plannedRoom.Duration, + plannedRoom.RoomName, ntasMap[*plannedRoom.NtaMtknr].Name, plannedRoom.Duration, ) } - return nil + return p.dbClient.ReplaceRoomsForNTA(ctx, plannedRooms) } // TODO: rewrite me. From af7ef75eaf705db6d50c220bee3497f7974ff56d Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Fri, 22 Dec 2023 13:18:52 +0100 Subject: [PATCH 51/78] emails for NTAs --- db/nta.go | 27 +++++++++++++ graph/generated/generated.go | 78 +++++++++++++++++++++++++++++++++++- graph/model/models_gen.go | 17 ++++---- graph/model/nta.go | 2 + graph/nta.graphqls | 2 + plexams/prepare.go | 5 +++ 6 files changed, 122 insertions(+), 9 deletions(-) diff --git a/db/nta.go b/db/nta.go index 83da035..144b725 100644 --- a/db/nta.go +++ b/db/nta.go @@ -64,6 +64,33 @@ func (db *DB) Ntas(ctx context.Context) ([]*model.NTA, error) { return ntas, nil } +func (db *DB) SetSemesterOnNTAs(ctx context.Context, studentRegs []interface{}) error { + collection := db.Client.Database("plexams").Collection(collectionNameNTAs) + + for _, regRaw := range studentRegs { + reg := regRaw.(*model.Student) + if reg.Nta == nil { + continue + } + + res := collection.FindOneAndUpdate(ctx, bson.D{{Key: "mtknr", Value: reg.Mtknr}}, + bson.M{"$set": bson.M{"lastSemester": db.semester}}) + + if res.Err() != nil { + if res.Err() == mongo.ErrNoDocuments { + log.Error().Err(res.Err()).Str("mtknr", reg.Mtknr).Msg("nta with mtknr not found") + } else { + log.Error().Err(res.Err()).Str("mtknr", reg.Mtknr).Msg("error when setting semester on nta") + return res.Err() + } + } else { + log.Debug().Str("mtknr", reg.Mtknr).Str("last semester", db.semester).Msg("last semester set on nta") + } + } + + return nil +} + func (db *DB) NtasWithRegs(ctx context.Context) ([]*model.Student, error) { collection := db.Client.Database(db.databaseName).Collection(collectionStudentRegsPerStudentPlanned) diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 4a6f373..faaeaf0 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -298,6 +298,7 @@ type ComplexityRoot struct { NTA struct { Compensation func(childComplexity int) int DeltaDurationPercent func(childComplexity int) int + Email func(childComplexity int) int Exams func(childComplexity int) int From func(childComplexity int) int LastSemester func(childComplexity int) int @@ -2008,6 +2009,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.NTA.DeltaDurationPercent(childComplexity), true + case "NTA.email": + if e.complexity.NTA.Email == nil { + break + } + + return e.complexity.NTA.Email(childComplexity), true + case "NTA.exams": if e.complexity.NTA.Exams == nil { break @@ -4229,6 +4237,7 @@ type NTAExam { type NTA { name: String! + email: String mtknr: String! compensation: String! deltaDurationPercent: Int! @@ -4242,6 +4251,7 @@ type NTA { input NTAInput { name: String! + email: String mtknr: String! compensation: String! deltaDurationPercent: Int! @@ -7334,6 +7344,8 @@ func (ec *executionContext) fieldContext_EnhancedPrimussExam_ntas(ctx context.Co switch field.Name { case "name": return ec.fieldContext_NTA_name(ctx, field) + case "email": + return ec.fieldContext_NTA_email(ctx, field) case "mtknr": return ec.fieldContext_NTA_mtknr(ctx, field) case "compensation": @@ -10418,6 +10430,8 @@ func (ec *executionContext) fieldContext_GeneratedExam_ntas(ctx context.Context, switch field.Name { case "name": return ec.fieldContext_NTA_name(ctx, field) + case "email": + return ec.fieldContext_NTA_email(ctx, field) case "mtknr": return ec.fieldContext_NTA_mtknr(ctx, field) case "compensation": @@ -12782,6 +12796,8 @@ func (ec *executionContext) fieldContext_Mutation_addNTA(ctx context.Context, fi switch field.Name { case "name": return ec.fieldContext_NTA_name(ctx, field) + case "email": + return ec.fieldContext_NTA_email(ctx, field) case "mtknr": return ec.fieldContext_NTA_mtknr(ctx, field) case "compensation": @@ -13632,6 +13648,47 @@ func (ec *executionContext) fieldContext_NTA_name(ctx context.Context, field gra return fc, nil } +func (ec *executionContext) _NTA_email(ctx context.Context, field graphql.CollectedField, obj *model.NTA) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_NTA_email(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Email, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_NTA_email(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "NTA", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _NTA_mtknr(ctx context.Context, field graphql.CollectedField, obj *model.NTA) (ret graphql.Marshaler) { fc, err := ec.fieldContext_NTA_mtknr(ctx, field) if err != nil { @@ -14252,6 +14309,8 @@ func (ec *executionContext) fieldContext_NTAWithRegs_nta(ctx context.Context, fi switch field.Name { case "name": return ec.fieldContext_NTA_name(ctx, field) + case "email": + return ec.fieldContext_NTA_email(ctx, field) case "mtknr": return ec.fieldContext_NTA_mtknr(ctx, field) case "compensation": @@ -15240,6 +15299,8 @@ func (ec *executionContext) fieldContext_PlannedExam_ntas(ctx context.Context, f switch field.Name { case "name": return ec.fieldContext_NTA_name(ctx, field) + case "email": + return ec.fieldContext_NTA_email(ctx, field) case "mtknr": return ec.fieldContext_NTA_mtknr(ctx, field) case "compensation": @@ -19166,6 +19227,8 @@ func (ec *executionContext) fieldContext_Query_ntas(ctx context.Context, field g switch field.Name { case "name": return ec.fieldContext_NTA_name(ctx, field) + case "email": + return ec.fieldContext_NTA_email(ctx, field) case "mtknr": return ec.fieldContext_NTA_mtknr(ctx, field) case "compensation": @@ -23537,6 +23600,8 @@ func (ec *executionContext) fieldContext_Student_nta(ctx context.Context, field switch field.Name { case "name": return ec.fieldContext_NTA_name(ctx, field) + case "email": + return ec.fieldContext_NTA_email(ctx, field) case "mtknr": return ec.fieldContext_NTA_mtknr(ctx, field) case "compensation": @@ -27933,7 +27998,7 @@ func (ec *executionContext) unmarshalInputNTAInput(ctx context.Context, obj inte asMap[k] = v } - fieldsInOrder := [...]string{"name", "mtknr", "compensation", "deltaDurationPercent", "needsRoomAlone", "program", "from", "until"} + fieldsInOrder := [...]string{"name", "email", "mtknr", "compensation", "deltaDurationPercent", "needsRoomAlone", "program", "from", "until"} for _, k := range fieldsInOrder { v, ok := asMap[k] if !ok { @@ -27949,6 +28014,15 @@ func (ec *executionContext) unmarshalInputNTAInput(ctx context.Context, obj inte return it, err } it.Name = data + case "email": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.Email = data case "mtknr": var err error @@ -29938,6 +30012,8 @@ func (ec *executionContext) _NTA(ctx context.Context, sel ast.SelectionSet, obj if out.Values[i] == graphql.Null { out.Invalids++ } + case "email": + out.Values[i] = ec._NTA_email(ctx, field, obj) case "mtknr": out.Values[i] = ec._NTA_mtknr(ctx, field, obj) if out.Values[i] == graphql.Null { diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index 1f8f319..7cc3ab9 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -229,14 +229,15 @@ type InvigilatorsForDay struct { } type NTAInput struct { - Name string `json:"name"` - Mtknr string `json:"mtknr"` - Compensation string `json:"compensation"` - DeltaDurationPercent int `json:"deltaDurationPercent"` - NeedsRoomAlone bool `json:"needsRoomAlone"` - Program string `json:"program"` - From string `json:"from"` - Until string `json:"until"` + Name string `json:"name"` + Email *string `json:"email,omitempty"` + Mtknr string `json:"mtknr"` + Compensation string `json:"compensation"` + DeltaDurationPercent int `json:"deltaDurationPercent"` + NeedsRoomAlone bool `json:"needsRoomAlone"` + Program string `json:"program"` + From string `json:"from"` + Until string `json:"until"` } type NTAWithRegs struct { diff --git a/graph/model/nta.go b/graph/model/nta.go index ca46f94..0b0a890 100644 --- a/graph/model/nta.go +++ b/graph/model/nta.go @@ -9,6 +9,7 @@ type NTAExam struct { type NTA struct { Name string `bson:"name"` + Email *string `bson:"email"` Mtknr string `bson:"mtknr"` Compensation string `bson:"compensation"` DeltaDurationPercent int `bson:"deltaDurationPercent"` @@ -23,6 +24,7 @@ type NTA struct { func NtaInputToNta(ntaInput NTAInput) *NTA { return &NTA{ Name: ntaInput.Name, + Email: ntaInput.Email, Mtknr: ntaInput.Mtknr, Compensation: ntaInput.Compensation, DeltaDurationPercent: ntaInput.DeltaDurationPercent, diff --git a/graph/nta.graphqls b/graph/nta.graphqls index 9958caa..ef8fece 100644 --- a/graph/nta.graphqls +++ b/graph/nta.graphqls @@ -12,6 +12,7 @@ type NTAExam { type NTA { name: String! + email: String mtknr: String! compensation: String! deltaDurationPercent: Int! @@ -25,6 +26,7 @@ type NTA { input NTAInput { name: String! + email: String mtknr: String! compensation: String! deltaDurationPercent: Int! diff --git a/plexams/prepare.go b/plexams/prepare.go index 1348ce5..b19f2de 100644 --- a/plexams/prepare.go +++ b/plexams/prepare.go @@ -124,6 +124,11 @@ func (p *Plexams) PrepareStudentRegs() error { } } + err = p.dbClient.SetSemesterOnNTAs(ctx, studentRegsSlice) + if err != nil { + log.Error().Err(err).Msg("cannot set last semester on ntas") + } + return p.dbClient.SaveStudentRegs(ctx, studentRegsSlice) } From f61bef6e57f2fb13576e9cda67a33c4596837887 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Fri, 22 Dec 2023 22:00:40 +0100 Subject: [PATCH 52/78] =?UTF-8?q?=F0=9F=9A=A7=20prepare=20rooms=20for=20ex?= =?UTF-8?q?ams?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- graph/exam.graphqls | 9 +- graph/generated/generated.go | 367 +++++++++++++++++------------------ graph/model/models_gen.go | 28 +-- graph/room.graphqls | 2 +- plexams/plan_examgroups.go | 46 ++--- plexams/rooms.go | 308 +++++++++++++++++++---------- 6 files changed, 426 insertions(+), 334 deletions(-) diff --git a/graph/exam.graphqls b/graph/exam.graphqls index 6b26d36..e1d991e 100644 --- a/graph/exam.graphqls +++ b/graph/exam.graphqls @@ -87,12 +87,11 @@ type ExamInPlan { slot: Slot } -# Deprecated: remove me type ExamWithRegsAndRooms { - exam: ExamInPlan! - normalRegs: [StudentReg!]! - ntaRegs: [NTAWithRegs!]! - rooms: [RoomForExam!]! + exam: PlannedExam! + normalRegsMtknr: [String!]! + ntas: [NTA!]! + rooms: [PlannedRoom!]! } type ExternalExam { diff --git a/graph/generated/generated.go b/graph/generated/generated.go index faaeaf0..1d6c692 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -176,10 +176,10 @@ type ComplexityRoot struct { } ExamWithRegsAndRooms struct { - Exam func(childComplexity int) int - NormalRegs func(childComplexity int) int - NtaRegs func(childComplexity int) int - Rooms func(childComplexity int) int + Exam func(childComplexity int) int + NormalRegsMtknr func(childComplexity int) int + Ntas func(childComplexity int) int + Rooms func(childComplexity int) int } ExamerInPlan struct { @@ -371,8 +371,8 @@ type ComplexityRoot struct { NtaMtknr func(childComplexity int) int Reserve func(childComplexity int) int RoomName func(childComplexity int) int - SeatsPlanned func(childComplexity int) int Slot func(childComplexity int) int + StudentsInRoom func(childComplexity int) int } PrimussExam struct { @@ -1330,19 +1330,19 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.ExamWithRegsAndRooms.Exam(childComplexity), true - case "ExamWithRegsAndRooms.normalRegs": - if e.complexity.ExamWithRegsAndRooms.NormalRegs == nil { + case "ExamWithRegsAndRooms.normalRegsMtknr": + if e.complexity.ExamWithRegsAndRooms.NormalRegsMtknr == nil { break } - return e.complexity.ExamWithRegsAndRooms.NormalRegs(childComplexity), true + return e.complexity.ExamWithRegsAndRooms.NormalRegsMtknr(childComplexity), true - case "ExamWithRegsAndRooms.ntaRegs": - if e.complexity.ExamWithRegsAndRooms.NtaRegs == nil { + case "ExamWithRegsAndRooms.ntas": + if e.complexity.ExamWithRegsAndRooms.Ntas == nil { break } - return e.complexity.ExamWithRegsAndRooms.NtaRegs(childComplexity), true + return e.complexity.ExamWithRegsAndRooms.Ntas(childComplexity), true case "ExamWithRegsAndRooms.rooms": if e.complexity.ExamWithRegsAndRooms.Rooms == nil { @@ -2331,19 +2331,19 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PlannedRoom.RoomName(childComplexity), true - case "PlannedRoom.seatsPlanned": - if e.complexity.PlannedRoom.SeatsPlanned == nil { + case "PlannedRoom.slot": + if e.complexity.PlannedRoom.Slot == nil { break } - return e.complexity.PlannedRoom.SeatsPlanned(childComplexity), true + return e.complexity.PlannedRoom.Slot(childComplexity), true - case "PlannedRoom.slot": - if e.complexity.PlannedRoom.Slot == nil { + case "PlannedRoom.studentsInRoom": + if e.complexity.PlannedRoom.StudentsInRoom == nil { break } - return e.complexity.PlannedRoom.Slot(childComplexity), true + return e.complexity.PlannedRoom.StudentsInRoom(childComplexity), true case "PrimussExam.ancode": if e.complexity.PrimussExam.AnCode == nil { @@ -4053,12 +4053,11 @@ type ExamInPlan { slot: Slot } -# Deprecated: remove me type ExamWithRegsAndRooms { - exam: ExamInPlan! - normalRegs: [StudentReg!]! - ntaRegs: [NTAWithRegs!]! - rooms: [RoomForExam!]! + exam: PlannedExam! + normalRegsMtknr: [String!]! + ntas: [NTA!]! + rooms: [PlannedRoom!]! } type ExternalExam { @@ -4525,11 +4524,11 @@ type PlannedRoom { slot: Int! roomName: String! ancode: Int! - seatsPlanned: Int! duration: Int! handicap: Boolean! handicapRoomAlone: Boolean! reserve: Boolean! + studentsInRoom: [String!]! ntaMtknr: String } @@ -9516,9 +9515,9 @@ func (ec *executionContext) _ExamWithRegsAndRooms_exam(ctx context.Context, fiel } return graphql.Null } - res := resTmp.(*model.ExamInPlan) + res := resTmp.(*model.PlannedExam) fc.Result = res - return ec.marshalNExamInPlan2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamInPlan(ctx, field.Selections, res) + return ec.marshalNPlannedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExam(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_ExamWithRegsAndRooms_exam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -9529,23 +9528,33 @@ func (ec *executionContext) fieldContext_ExamWithRegsAndRooms_exam(ctx context.C IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "exam": - return ec.fieldContext_ExamInPlan_exam(ctx, field) + case "ancode": + return ec.fieldContext_PlannedExam_ancode(ctx, field) + case "zpaExam": + return ec.fieldContext_PlannedExam_zpaExam(ctx, field) + case "primussExams": + return ec.fieldContext_PlannedExam_primussExams(ctx, field) case "constraints": - return ec.fieldContext_ExamInPlan_constraints(ctx, field) - case "nta": - return ec.fieldContext_ExamInPlan_nta(ctx, field) - case "slot": - return ec.fieldContext_ExamInPlan_slot(ctx, field) + return ec.fieldContext_PlannedExam_constraints(ctx, field) + case "conflicts": + return ec.fieldContext_PlannedExam_conflicts(ctx, field) + case "studentRegsCount": + return ec.fieldContext_PlannedExam_studentRegsCount(ctx, field) + case "ntas": + return ec.fieldContext_PlannedExam_ntas(ctx, field) + case "maxDuration": + return ec.fieldContext_PlannedExam_maxDuration(ctx, field) + case "planEntry": + return ec.fieldContext_PlannedExam_planEntry(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type ExamInPlan", field.Name) + return nil, fmt.Errorf("no field named %q was found under type PlannedExam", field.Name) }, } return fc, nil } -func (ec *executionContext) _ExamWithRegsAndRooms_normalRegs(ctx context.Context, field graphql.CollectedField, obj *model.ExamWithRegsAndRooms) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_ExamWithRegsAndRooms_normalRegs(ctx, field) +func (ec *executionContext) _ExamWithRegsAndRooms_normalRegsMtknr(ctx context.Context, field graphql.CollectedField, obj *model.ExamWithRegsAndRooms) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ExamWithRegsAndRooms_normalRegsMtknr(ctx, field) if err != nil { return graphql.Null } @@ -9558,7 +9567,7 @@ func (ec *executionContext) _ExamWithRegsAndRooms_normalRegs(ctx context.Context }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.NormalRegs, nil + return obj.NormalRegsMtknr, nil }) if err != nil { ec.Error(ctx, err) @@ -9570,40 +9579,26 @@ func (ec *executionContext) _ExamWithRegsAndRooms_normalRegs(ctx context.Context } return graphql.Null } - res := resTmp.([]*model.StudentReg) + res := resTmp.([]string) fc.Result = res - return ec.marshalNStudentReg2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentRegᚄ(ctx, field.Selections, res) + return ec.marshalNString2ᚕstringᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ExamWithRegsAndRooms_normalRegs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ExamWithRegsAndRooms_normalRegsMtknr(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ExamWithRegsAndRooms", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "mtknr": - return ec.fieldContext_StudentReg_mtknr(ctx, field) - case "ancode": - return ec.fieldContext_StudentReg_ancode(ctx, field) - case "program": - return ec.fieldContext_StudentReg_program(ctx, field) - case "group": - return ec.fieldContext_StudentReg_group(ctx, field) - case "name": - return ec.fieldContext_StudentReg_name(ctx, field) - case "presence": - return ec.fieldContext_StudentReg_presence(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type StudentReg", field.Name) + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil } -func (ec *executionContext) _ExamWithRegsAndRooms_ntaRegs(ctx context.Context, field graphql.CollectedField, obj *model.ExamWithRegsAndRooms) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_ExamWithRegsAndRooms_ntaRegs(ctx, field) +func (ec *executionContext) _ExamWithRegsAndRooms_ntas(ctx context.Context, field graphql.CollectedField, obj *model.ExamWithRegsAndRooms) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ExamWithRegsAndRooms_ntas(ctx, field) if err != nil { return graphql.Null } @@ -9616,7 +9611,7 @@ func (ec *executionContext) _ExamWithRegsAndRooms_ntaRegs(ctx context.Context, f }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.NtaRegs, nil + return obj.Ntas, nil }) if err != nil { ec.Error(ctx, err) @@ -9628,12 +9623,12 @@ func (ec *executionContext) _ExamWithRegsAndRooms_ntaRegs(ctx context.Context, f } return graphql.Null } - res := resTmp.([]*model.NTAWithRegs) + res := resTmp.([]*model.NTA) fc.Result = res - return ec.marshalNNTAWithRegs2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsᚄ(ctx, field.Selections, res) + return ec.marshalNNTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_ExamWithRegsAndRooms_ntaRegs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_ExamWithRegsAndRooms_ntas(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "ExamWithRegsAndRooms", Field: field, @@ -9641,12 +9636,30 @@ func (ec *executionContext) fieldContext_ExamWithRegsAndRooms_ntaRegs(ctx contex IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "nta": - return ec.fieldContext_NTAWithRegs_nta(ctx, field) - case "regs": - return ec.fieldContext_NTAWithRegs_regs(ctx, field) + case "name": + return ec.fieldContext_NTA_name(ctx, field) + case "email": + return ec.fieldContext_NTA_email(ctx, field) + case "mtknr": + return ec.fieldContext_NTA_mtknr(ctx, field) + case "compensation": + return ec.fieldContext_NTA_compensation(ctx, field) + case "deltaDurationPercent": + return ec.fieldContext_NTA_deltaDurationPercent(ctx, field) + case "needsRoomAlone": + return ec.fieldContext_NTA_needsRoomAlone(ctx, field) + case "program": + return ec.fieldContext_NTA_program(ctx, field) + case "from": + return ec.fieldContext_NTA_from(ctx, field) + case "until": + return ec.fieldContext_NTA_until(ctx, field) + case "lastSemester": + return ec.fieldContext_NTA_lastSemester(ctx, field) + case "exams": + return ec.fieldContext_NTA_exams(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type NTAWithRegs", field.Name) + return nil, fmt.Errorf("no field named %q was found under type NTA", field.Name) }, } return fc, nil @@ -9678,9 +9691,9 @@ func (ec *executionContext) _ExamWithRegsAndRooms_rooms(ctx context.Context, fie } return graphql.Null } - res := resTmp.([]*model.RoomForExam) + res := resTmp.([]*model.PlannedRoom) fc.Result = res - return ec.marshalNRoomForExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomForExamᚄ(ctx, field.Selections, res) + return ec.marshalNPlannedRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedRoomᚄ(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_ExamWithRegsAndRooms_rooms(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -9691,22 +9704,28 @@ func (ec *executionContext) fieldContext_ExamWithRegsAndRooms_rooms(ctx context. IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { + case "day": + return ec.fieldContext_PlannedRoom_day(ctx, field) + case "slot": + return ec.fieldContext_PlannedRoom_slot(ctx, field) + case "roomName": + return ec.fieldContext_PlannedRoom_roomName(ctx, field) case "ancode": - return ec.fieldContext_RoomForExam_ancode(ctx, field) - case "room": - return ec.fieldContext_RoomForExam_room(ctx, field) - case "seatsPlanned": - return ec.fieldContext_RoomForExam_seatsPlanned(ctx, field) + return ec.fieldContext_PlannedRoom_ancode(ctx, field) case "duration": - return ec.fieldContext_RoomForExam_duration(ctx, field) + return ec.fieldContext_PlannedRoom_duration(ctx, field) case "handicap": - return ec.fieldContext_RoomForExam_handicap(ctx, field) + return ec.fieldContext_PlannedRoom_handicap(ctx, field) + case "handicapRoomAlone": + return ec.fieldContext_PlannedRoom_handicapRoomAlone(ctx, field) case "reserve": - return ec.fieldContext_RoomForExam_reserve(ctx, field) - case "students": - return ec.fieldContext_RoomForExam_students(ctx, field) + return ec.fieldContext_PlannedRoom_reserve(ctx, field) + case "studentsInRoom": + return ec.fieldContext_PlannedRoom_studentsInRoom(ctx, field) + case "ntaMtknr": + return ec.fieldContext_PlannedRoom_ntaMtknr(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type RoomForExam", field.Name) + return nil, fmt.Errorf("no field named %q was found under type PlannedRoom", field.Name) }, } return fc, nil @@ -15765,8 +15784,8 @@ func (ec *executionContext) fieldContext_PlannedRoom_ancode(ctx context.Context, return fc, nil } -func (ec *executionContext) _PlannedRoom_seatsPlanned(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_PlannedRoom_seatsPlanned(ctx, field) +func (ec *executionContext) _PlannedRoom_duration(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedRoom_duration(ctx, field) if err != nil { return graphql.Null } @@ -15779,7 +15798,7 @@ func (ec *executionContext) _PlannedRoom_seatsPlanned(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.SeatsPlanned, nil + return obj.Duration, nil }) if err != nil { ec.Error(ctx, err) @@ -15796,7 +15815,7 @@ func (ec *executionContext) _PlannedRoom_seatsPlanned(ctx context.Context, field return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_PlannedRoom_seatsPlanned(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_PlannedRoom_duration(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "PlannedRoom", Field: field, @@ -15809,8 +15828,8 @@ func (ec *executionContext) fieldContext_PlannedRoom_seatsPlanned(ctx context.Co return fc, nil } -func (ec *executionContext) _PlannedRoom_duration(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_PlannedRoom_duration(ctx, field) +func (ec *executionContext) _PlannedRoom_handicap(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedRoom_handicap(ctx, field) if err != nil { return graphql.Null } @@ -15823,7 +15842,7 @@ func (ec *executionContext) _PlannedRoom_duration(ctx context.Context, field gra }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Duration, nil + return obj.Handicap, nil }) if err != nil { ec.Error(ctx, err) @@ -15835,26 +15854,26 @@ func (ec *executionContext) _PlannedRoom_duration(ctx context.Context, field gra } return graphql.Null } - res := resTmp.(int) + res := resTmp.(bool) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_PlannedRoom_duration(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_PlannedRoom_handicap(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "PlannedRoom", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") + return nil, errors.New("field of type Boolean does not have child fields") }, } return fc, nil } -func (ec *executionContext) _PlannedRoom_handicap(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_PlannedRoom_handicap(ctx, field) +func (ec *executionContext) _PlannedRoom_handicapRoomAlone(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedRoom_handicapRoomAlone(ctx, field) if err != nil { return graphql.Null } @@ -15867,7 +15886,7 @@ func (ec *executionContext) _PlannedRoom_handicap(ctx context.Context, field gra }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Handicap, nil + return obj.HandicapRoomAlone, nil }) if err != nil { ec.Error(ctx, err) @@ -15884,7 +15903,7 @@ func (ec *executionContext) _PlannedRoom_handicap(ctx context.Context, field gra return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_PlannedRoom_handicap(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_PlannedRoom_handicapRoomAlone(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "PlannedRoom", Field: field, @@ -15897,8 +15916,8 @@ func (ec *executionContext) fieldContext_PlannedRoom_handicap(ctx context.Contex return fc, nil } -func (ec *executionContext) _PlannedRoom_handicapRoomAlone(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_PlannedRoom_handicapRoomAlone(ctx, field) +func (ec *executionContext) _PlannedRoom_reserve(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedRoom_reserve(ctx, field) if err != nil { return graphql.Null } @@ -15911,7 +15930,7 @@ func (ec *executionContext) _PlannedRoom_handicapRoomAlone(ctx context.Context, }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.HandicapRoomAlone, nil + return obj.Reserve, nil }) if err != nil { ec.Error(ctx, err) @@ -15928,7 +15947,7 @@ func (ec *executionContext) _PlannedRoom_handicapRoomAlone(ctx context.Context, return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_PlannedRoom_handicapRoomAlone(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_PlannedRoom_reserve(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "PlannedRoom", Field: field, @@ -15941,8 +15960,8 @@ func (ec *executionContext) fieldContext_PlannedRoom_handicapRoomAlone(ctx conte return fc, nil } -func (ec *executionContext) _PlannedRoom_reserve(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_PlannedRoom_reserve(ctx, field) +func (ec *executionContext) _PlannedRoom_studentsInRoom(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedRoom_studentsInRoom(ctx, field) if err != nil { return graphql.Null } @@ -15955,7 +15974,7 @@ func (ec *executionContext) _PlannedRoom_reserve(ctx context.Context, field grap }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Reserve, nil + return obj.StudentsInRoom, nil }) if err != nil { ec.Error(ctx, err) @@ -15967,19 +15986,19 @@ func (ec *executionContext) _PlannedRoom_reserve(ctx context.Context, field grap } return graphql.Null } - res := resTmp.(bool) + res := resTmp.([]string) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalNString2ᚕstringᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_PlannedRoom_reserve(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_PlannedRoom_studentsInRoom(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "PlannedRoom", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Boolean does not have child fields") + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil @@ -18008,10 +18027,10 @@ func (ec *executionContext) fieldContext_Query_examsInSlotWithRooms(ctx context. switch field.Name { case "exam": return ec.fieldContext_ExamWithRegsAndRooms_exam(ctx, field) - case "normalRegs": - return ec.fieldContext_ExamWithRegsAndRooms_normalRegs(ctx, field) - case "ntaRegs": - return ec.fieldContext_ExamWithRegsAndRooms_ntaRegs(ctx, field) + case "normalRegsMtknr": + return ec.fieldContext_ExamWithRegsAndRooms_normalRegsMtknr(ctx, field) + case "ntas": + return ec.fieldContext_ExamWithRegsAndRooms_ntas(ctx, field) case "rooms": return ec.fieldContext_ExamWithRegsAndRooms_rooms(ctx, field) } @@ -29136,13 +29155,13 @@ func (ec *executionContext) _ExamWithRegsAndRooms(ctx context.Context, sel ast.S if out.Values[i] == graphql.Null { out.Invalids++ } - case "normalRegs": - out.Values[i] = ec._ExamWithRegsAndRooms_normalRegs(ctx, field, obj) + case "normalRegsMtknr": + out.Values[i] = ec._ExamWithRegsAndRooms_normalRegsMtknr(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } - case "ntaRegs": - out.Values[i] = ec._ExamWithRegsAndRooms_ntaRegs(ctx, field, obj) + case "ntas": + out.Values[i] = ec._ExamWithRegsAndRooms_ntas(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } @@ -30500,11 +30519,6 @@ func (ec *executionContext) _PlannedRoom(ctx context.Context, sel ast.SelectionS if out.Values[i] == graphql.Null { out.Invalids++ } - case "seatsPlanned": - out.Values[i] = ec._PlannedRoom_seatsPlanned(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } case "duration": out.Values[i] = ec._PlannedRoom_duration(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -30525,6 +30539,11 @@ func (ec *executionContext) _PlannedRoom(ctx context.Context, sel ast.SelectionS if out.Values[i] == graphql.Null { out.Invalids++ } + case "studentsInRoom": + out.Values[i] = ec._PlannedRoom_studentsInRoom(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } case "ntaMtknr": out.Values[i] = ec._PlannedRoom_ntaMtknr(ctx, field, obj) default: @@ -34981,50 +35000,6 @@ func (ec *executionContext) unmarshalNNTAInput2githubᚗcomᚋobcodeᚋplexams return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalNNTAWithRegs2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.NTAWithRegs) graphql.Marshaler { - ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } - for i := range v { - i := i - fc := &graphql.FieldContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithFieldContext(ctx, fc) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalNNTAWithRegs2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegs(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - - } - wg.Wait() - - for _, e := range ret { - if e == graphql.Null { - return graphql.Null - } - } - - return ret -} - func (ec *executionContext) marshalNNTAWithRegs2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegs(ctx context.Context, sel ast.SelectionSet, v *model.NTAWithRegs) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -35119,11 +35094,7 @@ func (ec *executionContext) marshalNPlannedExamWithNTA2ᚖgithubᚗcomᚋobcode return ec._PlannedExamWithNTA(ctx, sel, v) } -func (ec *executionContext) marshalNPrimussExam2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx context.Context, sel ast.SelectionSet, v model.PrimussExam) graphql.Marshaler { - return ec._PrimussExam(ctx, sel, &v) -} - -func (ec *executionContext) marshalNPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PrimussExam) graphql.Marshaler { +func (ec *executionContext) marshalNPlannedRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedRoomᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PlannedRoom) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35147,7 +35118,7 @@ func (ec *executionContext) marshalNPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋpl if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx, sel, v[i]) + ret[i] = ec.marshalNPlannedRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedRoom(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35167,17 +35138,21 @@ func (ec *executionContext) marshalNPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋpl return ret } -func (ec *executionContext) marshalNPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx context.Context, sel ast.SelectionSet, v *model.PrimussExam) graphql.Marshaler { +func (ec *executionContext) marshalNPlannedRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedRoom(ctx context.Context, sel ast.SelectionSet, v *model.PlannedRoom) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._PrimussExam(ctx, sel, v) + return ec._PlannedRoom(ctx, sel, v) } -func (ec *executionContext) marshalNPrimussExamAncode2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncodeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PrimussExamAncode) graphql.Marshaler { +func (ec *executionContext) marshalNPrimussExam2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx context.Context, sel ast.SelectionSet, v model.PrimussExam) graphql.Marshaler { + return ec._PrimussExam(ctx, sel, &v) +} + +func (ec *executionContext) marshalNPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PrimussExam) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35201,7 +35176,7 @@ func (ec *executionContext) marshalNPrimussExamAncode2ᚕᚖgithubᚗcomᚋobcod if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNPrimussExamAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncode(ctx, sel, v[i]) + ret[i] = ec.marshalNPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35221,17 +35196,17 @@ func (ec *executionContext) marshalNPrimussExamAncode2ᚕᚖgithubᚗcomᚋobcod return ret } -func (ec *executionContext) marshalNPrimussExamAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncode(ctx context.Context, sel ast.SelectionSet, v *model.PrimussExamAncode) graphql.Marshaler { +func (ec *executionContext) marshalNPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx context.Context, sel ast.SelectionSet, v *model.PrimussExam) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._PrimussExamAncode(ctx, sel, v) + return ec._PrimussExam(ctx, sel, v) } -func (ec *executionContext) marshalNPrimussExamWithCount2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamWithCountᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PrimussExamWithCount) graphql.Marshaler { +func (ec *executionContext) marshalNPrimussExamAncode2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncodeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PrimussExamAncode) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35255,7 +35230,7 @@ func (ec *executionContext) marshalNPrimussExamWithCount2ᚕᚖgithubᚗcomᚋob if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNPrimussExamWithCount2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamWithCount(ctx, sel, v[i]) + ret[i] = ec.marshalNPrimussExamAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncode(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35275,17 +35250,17 @@ func (ec *executionContext) marshalNPrimussExamWithCount2ᚕᚖgithubᚗcomᚋob return ret } -func (ec *executionContext) marshalNPrimussExamWithCount2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamWithCount(ctx context.Context, sel ast.SelectionSet, v *model.PrimussExamWithCount) graphql.Marshaler { +func (ec *executionContext) marshalNPrimussExamAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncode(ctx context.Context, sel ast.SelectionSet, v *model.PrimussExamAncode) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._PrimussExamWithCount(ctx, sel, v) + return ec._PrimussExamAncode(ctx, sel, v) } -func (ec *executionContext) marshalNRegWithError2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRegWithErrorᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.RegWithError) graphql.Marshaler { +func (ec *executionContext) marshalNPrimussExamWithCount2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamWithCountᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PrimussExamWithCount) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35309,7 +35284,7 @@ func (ec *executionContext) marshalNRegWithError2ᚕᚖgithubᚗcomᚋobcodeᚋp if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNRegWithError2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRegWithError(ctx, sel, v[i]) + ret[i] = ec.marshalNPrimussExamWithCount2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamWithCount(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35329,17 +35304,17 @@ func (ec *executionContext) marshalNRegWithError2ᚕᚖgithubᚗcomᚋobcodeᚋp return ret } -func (ec *executionContext) marshalNRegWithError2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRegWithError(ctx context.Context, sel ast.SelectionSet, v *model.RegWithError) graphql.Marshaler { +func (ec *executionContext) marshalNPrimussExamWithCount2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamWithCount(ctx context.Context, sel ast.SelectionSet, v *model.PrimussExamWithCount) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._RegWithError(ctx, sel, v) + return ec._PrimussExamWithCount(ctx, sel, v) } -func (ec *executionContext) marshalNRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Room) graphql.Marshaler { +func (ec *executionContext) marshalNRegWithError2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRegWithErrorᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.RegWithError) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35363,7 +35338,7 @@ func (ec *executionContext) marshalNRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexams if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoom(ctx, sel, v[i]) + ret[i] = ec.marshalNRegWithError2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRegWithError(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35383,17 +35358,17 @@ func (ec *executionContext) marshalNRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexams return ret } -func (ec *executionContext) marshalNRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoom(ctx context.Context, sel ast.SelectionSet, v *model.Room) graphql.Marshaler { +func (ec *executionContext) marshalNRegWithError2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRegWithError(ctx context.Context, sel ast.SelectionSet, v *model.RegWithError) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._Room(ctx, sel, v) + return ec._RegWithError(ctx, sel, v) } -func (ec *executionContext) marshalNRoomAndExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomAndExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.RoomAndExam) graphql.Marshaler { +func (ec *executionContext) marshalNRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Room) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35417,7 +35392,7 @@ func (ec *executionContext) marshalNRoomAndExam2ᚕᚖgithubᚗcomᚋobcodeᚋpl if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNRoomAndExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomAndExam(ctx, sel, v[i]) + ret[i] = ec.marshalNRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoom(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35437,17 +35412,17 @@ func (ec *executionContext) marshalNRoomAndExam2ᚕᚖgithubᚗcomᚋobcodeᚋpl return ret } -func (ec *executionContext) marshalNRoomAndExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomAndExam(ctx context.Context, sel ast.SelectionSet, v *model.RoomAndExam) graphql.Marshaler { +func (ec *executionContext) marshalNRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoom(ctx context.Context, sel ast.SelectionSet, v *model.Room) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._RoomAndExam(ctx, sel, v) + return ec._Room(ctx, sel, v) } -func (ec *executionContext) marshalNRoomForExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomForExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.RoomForExam) graphql.Marshaler { +func (ec *executionContext) marshalNRoomAndExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomAndExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.RoomAndExam) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35471,7 +35446,7 @@ func (ec *executionContext) marshalNRoomForExam2ᚕᚖgithubᚗcomᚋobcodeᚋpl if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNRoomForExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomForExam(ctx, sel, v[i]) + ret[i] = ec.marshalNRoomAndExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomAndExam(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35491,6 +35466,16 @@ func (ec *executionContext) marshalNRoomForExam2ᚕᚖgithubᚗcomᚋobcodeᚋpl return ret } +func (ec *executionContext) marshalNRoomAndExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomAndExam(ctx context.Context, sel ast.SelectionSet, v *model.RoomAndExam) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._RoomAndExam(ctx, sel, v) +} + func (ec *executionContext) marshalNRoomForExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomForExam(ctx context.Context, sel ast.SelectionSet, v *model.RoomForExam) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index 7cc3ab9..7b0570a 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -133,10 +133,10 @@ type ExamWithRegs struct { } type ExamWithRegsAndRooms struct { - Exam *ExamInPlan `json:"exam"` - NormalRegs []*StudentReg `json:"normalRegs"` - NtaRegs []*NTAWithRegs `json:"ntaRegs"` - Rooms []*RoomForExam `json:"rooms"` + Exam *PlannedExam `json:"exam"` + NormalRegsMtknr []string `json:"normalRegsMtknr"` + Ntas []*NTA `json:"ntas"` + Rooms []*PlannedRoom `json:"rooms"` } type ExamerInPlan struct { @@ -287,16 +287,16 @@ type PlannedExamWithNta struct { } type PlannedRoom struct { - Day int `json:"day"` - Slot int `json:"slot"` - RoomName string `json:"roomName"` - Ancode int `json:"ancode"` - SeatsPlanned int `json:"seatsPlanned"` - Duration int `json:"duration"` - Handicap bool `json:"handicap"` - HandicapRoomAlone bool `json:"handicapRoomAlone"` - Reserve bool `json:"reserve"` - NtaMtknr *string `json:"ntaMtknr,omitempty"` + Day int `json:"day"` + Slot int `json:"slot"` + RoomName string `json:"roomName"` + Ancode int `json:"ancode"` + Duration int `json:"duration"` + Handicap bool `json:"handicap"` + HandicapRoomAlone bool `json:"handicapRoomAlone"` + Reserve bool `json:"reserve"` + StudentsInRoom []string `json:"studentsInRoom"` + NtaMtknr *string `json:"ntaMtknr,omitempty"` } type PrimussExamAncode struct { diff --git a/graph/room.graphqls b/graph/room.graphqls index 95a4eaa..e16d854 100644 --- a/graph/room.graphqls +++ b/graph/room.graphqls @@ -27,11 +27,11 @@ type PlannedRoom { slot: Int! roomName: String! ancode: Int! - seatsPlanned: Int! duration: Int! handicap: Boolean! handicapRoomAlone: Boolean! reserve: Boolean! + studentsInRoom: [String!]! ntaMtknr: String } diff --git a/plexams/plan_examgroups.go b/plexams/plan_examgroups.go index 53a87be..675a0bc 100644 --- a/plexams/plan_examgroups.go +++ b/plexams/plan_examgroups.go @@ -385,31 +385,33 @@ func (p *Plexams) ExamsInPlan(ctx context.Context) ([]*model.ExamInPlan, error) return p.dbClient.ExamsInPlan(ctx) } +// TODO: rewrite me or delete me func (p *Plexams) ExamsInSlotWithRooms(ctx context.Context, day int, time int) ([]*model.ExamWithRegsAndRooms, error) { - examsInSlot, err := p.ExamsInSlot(ctx, day, time) - if err != nil { - log.Error().Err(err).Int("day", day).Int("time", time). - Msg("cannot get exams in slot") - return nil, err - } + // examsInSlot, err := p.ExamsInSlot(ctx, day, time) + // if err != nil { + // log.Error().Err(err).Int("day", day).Int("time", time). + // Msg("cannot get exams in slot") + // return nil, err + // } - examsInSlotWithRooms := make([]*model.ExamWithRegsAndRooms, 0, len(examsInSlot)) - for _, exam := range examsInSlot { - rooms, err := p.dbClient.RoomsForAncode(ctx, exam.Exam.Ancode) - if err != nil { - log.Error().Err(err).Int("day", day).Int("time", time).Int("ancode", exam.Exam.Ancode). - Msg("cannot get rooms for ancode") - return nil, err - } + // examsInSlotWithRooms := make([]*model.ExamWithRegsAndRooms, 0, len(examsInSlot)) + // for _, exam := range examsInSlot { + // rooms, err := p.dbClient.RoomsForAncode(ctx, exam.Exam.Ancode) + // if err != nil { + // log.Error().Err(err).Int("day", day).Int("time", time).Int("ancode", exam.Exam.Ancode). + // Msg("cannot get rooms for ancode") + // return nil, err + // } - examsInSlotWithRooms = append(examsInSlotWithRooms, &model.ExamWithRegsAndRooms{ - Exam: exam, - NormalRegs: []*model.StudentReg{}, - NtaRegs: []*model.NTAWithRegs{}, - Rooms: rooms, - }) + // examsInSlotWithRooms = append(examsInSlotWithRooms, &model.ExamWithRegsAndRooms{ + // Exam: exam, + // NormalRegs: []*model.StudentReg{}, + // NtaRegs: []*model.NTAWithRegs{}, + // Rooms: rooms, + // }) - } + // } - return examsInSlotWithRooms, nil + // return examsInSlotWithRooms, nil + return nil, nil } diff --git a/plexams/rooms.go b/plexams/rooms.go index 8e88007..fee2205 100644 --- a/plexams/rooms.go +++ b/plexams/rooms.go @@ -9,7 +9,6 @@ import ( set "github.com/deckarep/golang-set/v2" "github.com/logrusorgru/aurora" - "github.com/obcode/plexams.go/db" "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" "github.com/spf13/viper" @@ -491,11 +490,11 @@ func (p *Plexams) RoomsForNTAsWithRoomAlone() error { Slot: entries[0].slot, RoomName: room.Name, Ancode: entries[0].ancode, - SeatsPlanned: 1, Duration: ntaDuration, Handicap: true, HandicapRoomAlone: true, Reserve: false, + StudentsInRoom: []string{nta.Nta.Mtknr}, NtaMtknr: &nta.Nta.Mtknr, }) } else { @@ -548,11 +547,11 @@ func (p *Plexams) RoomsForNTAsWithRoomAlone() error { Slot: slot, RoomName: room.Name, Ancode: slotEntry.ancode, - SeatsPlanned: 1, Duration: ntaDuration, Handicap: true, HandicapRoomAlone: true, Reserve: false, + StudentsInRoom: []string{nta.Nta.Mtknr}, NtaMtknr: &nta.Nta.Mtknr, }) break @@ -581,9 +580,40 @@ func (p *Plexams) PrepareRoomForExams() error { examRooms := make([]interface{}, 0) + // only if room is needed more than 100 Minutes + roomsNotUsableInSlot := set.NewSet[string]() + for _, slot := range p.semesterConfig.Slots { + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Black("finding rooms for slot (%d/%d)"), + aurora.Yellow(slot.DayNumber), + aurora.Yellow(slot.SlotNumber), + ), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + log.Debug().Int("day", slot.DayNumber).Int("slot", slot.SlotNumber).Msg("preparing rooms for slot") // get exams - examsInPlan, err := p.ExamsInSlot(ctx, slot.DayNumber, slot.SlotNumber) + if slot.SlotNumber == 1 { + roomsNotUsableInSlot = set.NewSet[string]() + } + examsInPlan, err := p.GetExamsInSlot(ctx, slot.DayNumber, slot.SlotNumber) if err != nil { log.Error().Err(err).Int("day", slot.DayNumber).Int("time", slot.SlotNumber). @@ -591,31 +621,73 @@ func (p *Plexams) PrepareRoomForExams() error { return err } + // no exams in slot + if len(examsInPlan) == 0 { + spinner.StopMessage(aurora.Sprintf(aurora.Blue("no exams in slot"))) + err := spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + roomsNotUsableInSlot = set.NewSet[string]() + continue + } + + // no exams for me to plan in slot + needRooms := false + for _, exam := range examsInPlan { + if exam.Constraints == nil || !exam.Constraints.NotPlannedByMe { + needRooms = true + break + } + } + + if !needRooms { + spinner.StopMessage(aurora.Sprintf(aurora.Blue("no exams for me to plan in slot"))) + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + roomsNotUsableInSlot = set.NewSet[string]() + continue + } + + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + + // planning for each exam starts here exams := make([]*model.ExamWithRegsAndRooms, 0, len(examsInPlan)) for _, examInPlan := range examsInPlan { - ntas := examInPlan.Nta - isNTA := func(studReg *model.StudentReg) bool { - for _, nta := range ntas { - if studReg.Mtknr == nta.Nta.Mtknr { - return true - } + + if examInPlan.Constraints != nil && examInPlan.Constraints.NotPlannedByMe { + continue + } + + ntas := examInPlan.Ntas + ntaMtknrs := set.NewSet[string]() + ntasInNormalRooms := make([]*model.NTA, 0) + for _, nta := range ntas { + ntaMtknrs.Add(nta.Mtknr) + if !nta.NeedsRoomAlone { + ntasInNormalRooms = append(ntasInNormalRooms, nta) // nolint } - return false } - regs := make([]*model.StudentReg, 0) - for _, registrations := range examInPlan.Exam.StudentRegs { - for _, studReg := range registrations.StudentRegs { - if !isNTA(studReg) { - regs = append(regs, studReg) + + normalRegs := make([]string, 0) + for _, primussExam := range examInPlan.PrimussExams { + for _, studentRegs := range primussExam.StudentRegs { + if !ntaMtknrs.Contains(studentRegs.Mtknr) { + normalRegs = append(normalRegs, studentRegs.Mtknr) } } } exams = append(exams, &model.ExamWithRegsAndRooms{ - Exam: examInPlan, - NormalRegs: regs, - NtaRegs: ntas, - Rooms: make([]*model.RoomForExam, 0), + Exam: examInPlan, + NormalRegsMtknr: normalRegs, + Ntas: ntas, + Rooms: make([]*model.PlannedRoom, 0), }) } @@ -634,18 +706,31 @@ func (p *Plexams) PrepareRoomForExams() error { } sort.Slice(exams, func(i, j int) bool { - return len(exams[i].NormalRegs) > len(exams[j].NormalRegs) + return len(exams[i].NormalRegsMtknr)+len(exams[i].Ntas) > len(exams[j].NormalRegsMtknr)+len(exams[j].Ntas) }) - if len(exams[0].NormalRegs) == 0 { + if len(exams[0].NormalRegsMtknr) == 0 { break } exam := exams[0] exams = exams[1:] + cfg.Suffix = aurora.Sprintf(aurora.Magenta(" ↪ %d. %s (%s): %d of %d studs left"), + exam.Exam.Ancode, exam.Exam.ZpaExam.Module, exam.Exam.ZpaExam.MainExamer, + len(exam.NormalRegsMtknr), exam.Exam.StudentRegsCount) + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + var room *model.Room + // TODO: room used to long in previous slot if exam.Exam.Constraints != nil { if exam.Exam.Constraints.Online { room = &model.Room{ @@ -690,7 +775,7 @@ func (p *Plexams) PrepareRoomForExams() error { } if room == nil { - log.Error().Int("ancode", exam.Exam.Exam.Ancode). + log.Error().Int("ancode", exam.Exam.Ancode). Msg("no room found for exam") room = &model.Room{ Name: "No Room", @@ -700,91 +785,110 @@ func (p *Plexams) PrepareRoomForExams() error { reserveRoom := false studentCountInRoom := room.Seats - if studentCountInRoom > len(exam.NormalRegs) { - studentCountInRoom = len(exam.NormalRegs) + if studentCountInRoom > len(exam.NormalRegsMtknr) { + studentCountInRoom = len(exam.NormalRegsMtknr) if len(exam.Rooms) > 0 && studentCountInRoom < 10 { reserveRoom = true } } - studentsInRoom := exam.NormalRegs[:studentCountInRoom] - exam.NormalRegs = exam.NormalRegs[studentCountInRoom:] - - examRoom := model.RoomForExam{ - Ancode: exam.Exam.Exam.Ancode, - RoomName: room.Name, - SeatsPlanned: len(studentsInRoom), - Duration: exam.Exam.Exam.ZpaExam.Duration, - Handicap: false, - Reserve: reserveRoom, - Students: studentsInRoom, + studentsInRoom := exam.NormalRegsMtknr[:studentCountInRoom] + exam.NormalRegsMtknr = exam.NormalRegsMtknr[studentCountInRoom:] + + examRoom := model.PlannedRoom{ + Day: slot.DayNumber, + Slot: slot.SlotNumber, + RoomName: room.Name, + Ancode: exam.Exam.Ancode, + Duration: exam.Exam.ZpaExam.Duration, + Handicap: false, + HandicapRoomAlone: false, + Reserve: reserveRoom, + StudentsInRoom: studentsInRoom, + NtaMtknr: nil, } exam.Rooms = append(exam.Rooms, &examRoom) - examRooms = append(examRooms, &examRoom) + examRooms = append(examRooms, &examRoom) // nolint exams = append(exams, exam) - } // for exams - // NTAs - for _, exam := range exams { - if len(exam.NtaRegs) == 0 { - continue + spinner.StopMessage(aurora.Sprintf(aurora.Green("added %s for %d students (max. %d)"), + examRoom.RoomName, len(examRoom.StudentsInRoom), room.Seats)) + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") } + } // for exams - ntaRooms := slotWithRooms.NtaRooms - - for _, nta := range exam.NtaRegs { - - ntaDuration := int(math.Ceil(float64(exam.Exam.Exam.ZpaExam.Duration*(100+nta.Nta.DeltaDurationPercent)) / 100)) - - if nta.Nta.NeedsRoomAlone { - examRooms = append(examRooms, &model.RoomForExam{ - Ancode: exam.Exam.Exam.Ancode, - RoomName: ntaRooms[0].Name, - SeatsPlanned: 1, - Duration: ntaDuration, - Handicap: true, - Reserve: false, - Students: []*model.StudentReg{ - { - Mtknr: nta.Nta.Mtknr, - Name: nta.Nta.Name, - }, - }, - }) - ntaRooms = ntaRooms[1:] - } else { - // find room with a seat left - for _, room := range exam.Rooms { - if room.SeatsPlanned < p.GetRoomInfo(room.RoomName).Seats { - examRooms = append(examRooms, &model.RoomForExam{ - Ancode: exam.Exam.Exam.Ancode, - RoomName: room.RoomName, - SeatsPlanned: 1, - Duration: ntaDuration, - Handicap: true, - Reserve: false, - Students: []*model.StudentReg{ - { - Mtknr: nta.Nta.Mtknr, - Name: nta.Nta.Name, - }, - }, - }) - break - } - } - } - } + if roomsNotUsableInSlot.Cardinality() > 0 { + log.Debug().Interface("rooms", roomsNotUsableInSlot).Msg("rooms not usable in slot") + } + + // // NTAs + // for _, exam := range exams { + // if len(exam.NtaRegs) == 0 { + // continue + // } + + // ntaRooms := slotWithRooms.NtaRooms + + // for _, nta := range exam.NtaRegs { + + // ntaDuration := int(math.Ceil(float64(exam.Exam.Exam.ZpaExam.Duration*(100+nta.Nta.DeltaDurationPercent)) / 100)) + + // if nta.Nta.NeedsRoomAlone { + // examRooms = append(examRooms, &model.RoomForExam{ + // Ancode: exam.Exam.Exam.Ancode, + // RoomName: ntaRooms[0].Name, + // SeatsPlanned: 1, + // Duration: ntaDuration, + // Handicap: true, + // Reserve: false, + // Students: []*model.StudentReg{ + // { + // Mtknr: nta.Nta.Mtknr, + // Name: nta.Nta.Name, + // }, + // }, + // }) + // ntaRooms = ntaRooms[1:] + // } else { + // // find room with a seat left + // for _, room := range exam.Rooms { + // if room.SeatsPlanned < p.GetRoomInfo(room.RoomName).Seats { + // examRooms = append(examRooms, &model.RoomForExam{ + // Ancode: exam.Exam.Exam.Ancode, + // RoomName: room.RoomName, + // SeatsPlanned: 1, + // Duration: ntaDuration, + // Handicap: true, + // Reserve: false, + // Students: []*model.StudentReg{ + // { + // Mtknr: nta.Nta.Mtknr, + // Name: nta.Nta.Name, + // }, + // }, + // }) + // break + // } + // } + // } + // } + // } + + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") } } // for slot - err := p.dbClient.DropAndSave(context.WithValue(ctx, db.CollectionName("collectionName"), "rooms_for_exams"), examRooms) - if err != nil { - log.Error().Err(err).Msg("cannot save rooms for exams") - return err - } + // err := p.dbClient.DropAndSave(context.WithValue(ctx, db.CollectionName("collectionName"), "rooms_for_exams"), examRooms) + // if err != nil { + // log.Error().Err(err).Msg("cannot save rooms for exams") + // return err + // } return nil } @@ -855,18 +959,20 @@ func (p *Plexams) PlannedRoomNames(ctx context.Context) ([]string, error) { return p.dbClient.PlannedRoomNames(ctx) } +// TODO: rewrite me func (p *Plexams) PlannedRoomsInSlot(ctx context.Context, day int, time int) ([]*model.RoomForExam, error) { - exams, err := p.ExamsInSlotWithRooms(ctx, day, time) - if err != nil { - log.Error().Err(err).Int("day", day).Int("time", time).Msg("cannot get exams in slot") - } + // exams, err := p.ExamsInSlotWithRooms(ctx, day, time) + // if err != nil { + // log.Error().Err(err).Int("day", day).Int("time", time).Msg("cannot get exams in slot") + // } - rooms := make([]*model.RoomForExam, 0) - for _, exam := range exams { - rooms = append(rooms, exam.Rooms...) - } + // rooms := make([]*model.RoomForExam, 0) + // for _, exam := range exams { + // rooms = append(rooms, exam.Rooms...) + // } - return rooms, nil + // return rooms, nil + return nil, nil } func (p *Plexams) PlannedRoomNamesInSlot(ctx context.Context, day int, time int) ([]string, error) { From 75780986a48a50647e9b8f618c83d4d9ed4c6119 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Sat, 23 Dec 2023 16:36:42 +0100 Subject: [PATCH 53/78] planned rooms --- db/plan.go | 8 + db/rooms.go | 94 +- graph/exam.graphqls | 1 + graph/generated/generated.go | 3150 ++++++++++++++++++++++++---------- graph/model/models_gen.go | 1 + graph/model/rooms.go | 13 + graph/query.graphqls | 3 +- graph/query.resolvers.go | 10 - graph/room.graphqls | 19 + graph/room.resolvers.go | 46 + plexams/invigilators.go | 146 +- plexams/nta.go | 5 + plexams/plannedExams.go | 7 + plexams/rooms.go | 52 +- 14 files changed, 2510 insertions(+), 1045 deletions(-) diff --git a/db/plan.go b/db/plan.go index 67dded9..cf142bd 100644 --- a/db/plan.go +++ b/db/plan.go @@ -85,6 +85,13 @@ func (db *DB) GetExamsInSlot(ctx context.Context, day int, time int) ([]*model.P log.Error().Err(err).Int("ancode", planEntry.Ancode).Msg("cannot get exam") return nil, err } + + rooms, err := db.PlannedRoomsForAncode(ctx, planEntry.Ancode) + if err != nil { + log.Error().Err(err).Int("ancode", planEntry.Ancode).Msg("cannot get rooms") + return nil, err + } + exams = append(exams, &model.PlannedExam{ Ancode: exam.Ancode, ZpaExam: exam.ZpaExam, @@ -95,6 +102,7 @@ func (db *DB) GetExamsInSlot(ctx context.Context, day int, time int) ([]*model.P Ntas: exam.Ntas, MaxDuration: exam.MaxDuration, PlanEntry: planEntry, + PlannedRooms: rooms, }) } diff --git a/db/rooms.go b/db/rooms.go index 630b511..c38e9ab 100644 --- a/db/rooms.go +++ b/db/rooms.go @@ -2,13 +2,40 @@ package db import ( "context" + "fmt" "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) +func (db *DB) RoomFromName(ctx context.Context, roomName string) (*model.Room, error) { + collection := db.Client.Database("plexams").Collection(collectionRooms) + + res := collection.FindOne(ctx, bson.M{"name": roomName}) + if res.Err() != nil { + if res.Err() == mongo.ErrNoDocuments { + return nil, fmt.Errorf("cannot find room %s", roomName) + } + log.Error().Err(res.Err()).Str("room", roomName).Str("collection", collectionRooms). + Msg("cannot find room") + return nil, res.Err() + } + + var room model.Room + err := res.Decode(&room) + if err != nil { + log.Error().Err(res.Err()).Str("room", roomName).Str("collection", collectionRooms). + Msg("cannot decode room") + + return nil, err + } + + return &room, nil +} + func (db *DB) Rooms(ctx context.Context) ([]*model.Room, error) { collection := db.Client.Database("plexams").Collection(collectionRooms) @@ -172,7 +199,7 @@ func (db *DB) ChangeRoom(ctx context.Context, ancode int, oldRoom, newRoom *mode } func (db *DB) PlannedRoomNames(ctx context.Context) ([]string, error) { - collection := db.getCollectionSemester(collectionRoomsForExams) + collection := db.getCollectionSemester(collectionRoomsPlanned) rawNames, err := collection.Distinct(ctx, "roomname", bson.D{}) if err != nil { @@ -191,6 +218,71 @@ func (db *DB) PlannedRoomNames(ctx context.Context) ([]string, error) { return names, nil } +func (db *DB) PlannedRoomNamesInSlot(ctx context.Context, day, slot int) ([]string, error) { + collection := db.getCollectionSemester(collectionRoomsPlanned) + + filter := bson.M{"day": day, "slot": slot} + + rawNames, err := collection.Distinct(ctx, "roomname", filter) + if err != nil { + log.Error().Err(err).Int("day", day).Int("slot", slot).Msg("cannot find roomnames for slot") + return nil, err + } + + names := make([]string, 0, len(rawNames)) + for _, rawName := range rawNames { + name, ok := rawName.(string) + if !ok { + log.Debug().Interface("raw name", rawName).Msg("cannot convert to string") + } + names = append(names, name) + } + + return names, nil +} + +func (db *DB) PlannedRoomsInSlot(ctx context.Context, day, slot int) ([]*model.PlannedRoom, error) { + collection := db.getCollectionSemester(collectionRoomsPlanned) + + filter := bson.M{"day": day, "slot": slot} + + cur, err := collection.Find(ctx, filter) + if err != nil { + log.Error().Err(err).Int("day", day).Int("slot", slot).Msg("cannot find rooms for slot") + return nil, err + } + + plannedRooms := make([]*model.PlannedRoom, 0) + err = cur.All(ctx, &plannedRooms) + if err != nil { + log.Error().Err(err).Int("day", day).Int("slot", slot).Msg("cannot decode rooms for slot") + return nil, err + } + + return plannedRooms, nil +} + +func (db *DB) PlannedRoomsForAncode(ctx context.Context, ancode int) ([]*model.PlannedRoom, error) { + collection := db.getCollectionSemester(collectionRoomsPlanned) + + filter := bson.M{"ancode": ancode} + + cur, err := collection.Find(ctx, filter) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("cannot find rooms for ancode") + return nil, err + } + + plannedRooms := make([]*model.PlannedRoom, 0) + err = cur.All(ctx, &plannedRooms) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("cannot decode rooms for ancode") + return nil, err + } + + return plannedRooms, nil +} + func (db *DB) ReplaceRoomsForNTA(ctx context.Context, plannedRooms []*model.PlannedRoom) error { collection := db.getCollectionSemester(collectionRoomsPlanned) diff --git a/graph/exam.graphqls b/graph/exam.graphqls index e1d991e..8da75d7 100644 --- a/graph/exam.graphqls +++ b/graph/exam.graphqls @@ -136,6 +136,7 @@ type PlannedExam { ntas: [NTA!]! maxDuration: Int! planEntry: PlanEntry + plannedRooms: [PlannedRoom!] } type Exam { diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 1d6c692..252e972 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -37,6 +37,7 @@ type Config struct { } type ResolverRoot interface { + EnhancedPlannedRoom() EnhancedPlannedRoomResolver Mutation() MutationResolver Query() QueryResolver RoomForExam() RoomForExamResolver @@ -102,6 +103,22 @@ type ComplexityRoot struct { SameSlot func(childComplexity int) int } + EnhancedPlannedRoom struct { + Ancode func(childComplexity int) int + Day func(childComplexity int) int + Duration func(childComplexity int) int + Exam func(childComplexity int) int + Handicap func(childComplexity int) int + HandicapRoomAlone func(childComplexity int) int + NtaInRoom func(childComplexity int) int + NtaMtknr func(childComplexity int) int + Reserve func(childComplexity int) int + Room func(childComplexity int) int + RoomName func(childComplexity int) int + Slot func(childComplexity int) int + StudentsInRoom func(childComplexity int) int + } + EnhancedPrimussExam struct { Conflicts func(childComplexity int) int Exam func(childComplexity int) int @@ -351,6 +368,7 @@ type ComplexityRoot struct { MaxDuration func(childComplexity int) int Ntas func(childComplexity int) int PlanEntry func(childComplexity int) int + PlannedRooms func(childComplexity int) int PrimussExams func(childComplexity int) int StudentRegsCount func(childComplexity int) int ZpaExam func(childComplexity int) int @@ -447,6 +465,7 @@ type ComplexityRoot struct { PlannedExamsInSlot func(childComplexity int, day int, time int) int PlannedRoomNames func(childComplexity int) int PlannedRoomNamesInSlot func(childComplexity int, day int, time int) int + PlannedRoomsInSlot func(childComplexity int, day int, time int) int PrimussExam func(childComplexity int, program string, ancode int) int PrimussExams func(childComplexity int) int PrimussExamsForAnCode func(childComplexity int, ancode int) int @@ -667,6 +686,13 @@ type ComplexityRoot struct { } } +type EnhancedPlannedRoomResolver interface { + Room(ctx context.Context, obj *model.EnhancedPlannedRoom) (*model.Room, error) + + Exam(ctx context.Context, obj *model.EnhancedPlannedRoom) (*model.GeneratedExam, error) + + NtaInRoom(ctx context.Context, obj *model.EnhancedPlannedRoom) (*model.NTA, error) +} type MutationResolver interface { SetSemester(ctx context.Context, input string) (*model.Semester, error) ZpaExamsToPlan(ctx context.Context, input []int) ([]*model.ZPAExam, error) @@ -714,8 +740,6 @@ type QueryResolver interface { ExamsInSlotWithRooms(ctx context.Context, day int, time int) ([]*model.ExamWithRegsAndRooms, error) RoomsWithConstraints(ctx context.Context, handicap bool, lab bool, placesWithSocket bool, exahm *bool) ([]*model.Room, error) RoomsForSlot(ctx context.Context, day int, time int) (*model.SlotWithRooms, error) - PlannedRoomNames(ctx context.Context) ([]string, error) - PlannedRoomNamesInSlot(ctx context.Context, day int, time int) ([]string, error) InvigilatorsWithReq(ctx context.Context) ([]*model.Invigilator, error) InvigilatorTodos(ctx context.Context) (*model.InvigilationTodos, error) RoomsWithInvigilationsForSlot(ctx context.Context, day int, time int) (*model.InvigilationSlot, error) @@ -742,6 +766,9 @@ type QueryResolver interface { AwkwardSlots(ctx context.Context, ancode int) ([]*model.Slot, error) PrimussExams(ctx context.Context) ([]*model.PrimussExamByProgram, error) Rooms(ctx context.Context) ([]*model.Room, error) + PlannedRoomNames(ctx context.Context) ([]string, error) + PlannedRoomNamesInSlot(ctx context.Context, day int, time int) ([]string, error) + PlannedRoomsInSlot(ctx context.Context, day int, time int) ([]*model.EnhancedPlannedRoom, error) StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, error) StudentsByName(ctx context.Context, regex string) ([]*model.Student, error) Students(ctx context.Context) ([]*model.Student, error) @@ -1001,6 +1028,97 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Constraints.SameSlot(childComplexity), true + case "EnhancedPlannedRoom.ancode": + if e.complexity.EnhancedPlannedRoom.Ancode == nil { + break + } + + return e.complexity.EnhancedPlannedRoom.Ancode(childComplexity), true + + case "EnhancedPlannedRoom.day": + if e.complexity.EnhancedPlannedRoom.Day == nil { + break + } + + return e.complexity.EnhancedPlannedRoom.Day(childComplexity), true + + case "EnhancedPlannedRoom.duration": + if e.complexity.EnhancedPlannedRoom.Duration == nil { + break + } + + return e.complexity.EnhancedPlannedRoom.Duration(childComplexity), true + + case "EnhancedPlannedRoom.exam": + if e.complexity.EnhancedPlannedRoom.Exam == nil { + break + } + + return e.complexity.EnhancedPlannedRoom.Exam(childComplexity), true + + case "EnhancedPlannedRoom.handicap": + if e.complexity.EnhancedPlannedRoom.Handicap == nil { + break + } + + return e.complexity.EnhancedPlannedRoom.Handicap(childComplexity), true + + case "EnhancedPlannedRoom.handicapRoomAlone": + if e.complexity.EnhancedPlannedRoom.HandicapRoomAlone == nil { + break + } + + return e.complexity.EnhancedPlannedRoom.HandicapRoomAlone(childComplexity), true + + case "EnhancedPlannedRoom.ntaInRoom": + if e.complexity.EnhancedPlannedRoom.NtaInRoom == nil { + break + } + + return e.complexity.EnhancedPlannedRoom.NtaInRoom(childComplexity), true + + case "EnhancedPlannedRoom.ntaMtknr": + if e.complexity.EnhancedPlannedRoom.NtaMtknr == nil { + break + } + + return e.complexity.EnhancedPlannedRoom.NtaMtknr(childComplexity), true + + case "EnhancedPlannedRoom.reserve": + if e.complexity.EnhancedPlannedRoom.Reserve == nil { + break + } + + return e.complexity.EnhancedPlannedRoom.Reserve(childComplexity), true + + case "EnhancedPlannedRoom.room": + if e.complexity.EnhancedPlannedRoom.Room == nil { + break + } + + return e.complexity.EnhancedPlannedRoom.Room(childComplexity), true + + case "EnhancedPlannedRoom.roomName": + if e.complexity.EnhancedPlannedRoom.RoomName == nil { + break + } + + return e.complexity.EnhancedPlannedRoom.RoomName(childComplexity), true + + case "EnhancedPlannedRoom.slot": + if e.complexity.EnhancedPlannedRoom.Slot == nil { + break + } + + return e.complexity.EnhancedPlannedRoom.Slot(childComplexity), true + + case "EnhancedPlannedRoom.studentsInRoom": + if e.complexity.EnhancedPlannedRoom.StudentsInRoom == nil { + break + } + + return e.complexity.EnhancedPlannedRoom.StudentsInRoom(childComplexity), true + case "EnhancedPrimussExam.conflicts": if e.complexity.EnhancedPrimussExam.Conflicts == nil { break @@ -2233,6 +2351,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PlannedExam.PlanEntry(childComplexity), true + case "PlannedExam.plannedRooms": + if e.complexity.PlannedExam.PlannedRooms == nil { + break + } + + return e.complexity.PlannedExam.PlannedRooms(childComplexity), true + case "PlannedExam.primussExams": if e.complexity.PlannedExam.PrimussExams == nil { break @@ -2843,6 +2968,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.PlannedRoomNamesInSlot(childComplexity, args["day"].(int), args["time"].(int)), true + case "Query.plannedRoomsInSlot": + if e.complexity.Query.PlannedRoomsInSlot == nil { + break + } + + args, err := ec.field_Query_plannedRoomsInSlot_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.PlannedRoomsInSlot(childComplexity, args["day"].(int), args["time"].(int)), true + case "Query.primussExam": if e.complexity.Query.PrimussExam == nil { break @@ -4102,6 +4239,7 @@ type PlannedExam { ntas: [NTA!]! maxDuration: Int! planEntry: PlanEntry + plannedRooms: [PlannedRoom!] } type Exam { @@ -4485,8 +4623,7 @@ type ConflictsPerProgramAncode { exahm: Boolean ): [Room!]! roomsForSlot(day: Int!, time: Int!): SlotWithRooms - plannedRoomNames: [String!] - plannedRoomNamesInSlot(day: Int!, time: Int!): [String!] + # Invigilators invigilatorsWithReq: [Invigilator!]! invigilatorTodos: InvigilationTodos @@ -4497,6 +4634,9 @@ type ConflictsPerProgramAncode { `, BuiltIn: false}, {Name: "../room.graphqls", Input: `extend type Query { rooms: [Room!]! + plannedRoomNames: [String!] + plannedRoomNamesInSlot(day: Int!, time: Int!): [String!] + plannedRoomsInSlot(day: Int!, time: Int!): [EnhancedPlannedRoom!] } type Room { @@ -4532,6 +4672,22 @@ type PlannedRoom { ntaMtknr: String } +type EnhancedPlannedRoom { + day: Int! + slot: Int! + roomName: String! + room: Room! + ancode: Int! + exam: GeneratedExam! + duration: Int! + handicap: Boolean! + handicapRoomAlone: Boolean! + reserve: Boolean! + studentsInRoom: [String!]! + ntaMtknr: String + ntaInRoom: NTA +} + # Deprecated: rm me type RoomForExam { ancode: Int! @@ -5391,6 +5547,30 @@ func (ec *executionContext) field_Query_plannedRoomNamesInSlot_args(ctx context. return args, nil } +func (ec *executionContext) field_Query_plannedRoomsInSlot_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 int + if tmp, ok := rawArgs["day"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("day")) + arg0, err = ec.unmarshalNInt2int(ctx, tmp) + if err != nil { + return nil, err + } + } + args["day"] = arg0 + var arg1 int + if tmp, ok := rawArgs["time"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("time")) + arg1, err = ec.unmarshalNInt2int(ctx, tmp) + if err != nil { + return nil, err + } + } + args["time"] = arg1 + return args, nil +} + func (ec *executionContext) field_Query_primussExam_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -6779,9 +6959,591 @@ func (ec *executionContext) _Constraints_ancode(ctx context.Context, field graph return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Constraints_ancode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Constraints_ancode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Constraints", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Constraints_notPlannedByMe(ctx context.Context, field graphql.CollectedField, obj *model.Constraints) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Constraints_notPlannedByMe(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.NotPlannedByMe, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Constraints_notPlannedByMe(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Constraints", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Constraints_excludeDays(ctx context.Context, field graphql.CollectedField, obj *model.Constraints) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Constraints_excludeDays(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ExcludeDays, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*time.Time) + fc.Result = res + return ec.marshalOTime2ᚕᚖtimeᚐTimeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Constraints_excludeDays(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Constraints", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Time does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Constraints_possibleDays(ctx context.Context, field graphql.CollectedField, obj *model.Constraints) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Constraints_possibleDays(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PossibleDays, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*time.Time) + fc.Result = res + return ec.marshalOTime2ᚕᚖtimeᚐTimeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Constraints_possibleDays(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Constraints", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Time does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Constraints_fixedDay(ctx context.Context, field graphql.CollectedField, obj *model.Constraints) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Constraints_fixedDay(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.FixedDay, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*time.Time) + fc.Result = res + return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Constraints_fixedDay(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Constraints", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Time does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Constraints_fixedTime(ctx context.Context, field graphql.CollectedField, obj *model.Constraints) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Constraints_fixedTime(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.FixedTime, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*time.Time) + fc.Result = res + return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Constraints_fixedTime(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Constraints", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Time does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Constraints_sameSlot(ctx context.Context, field graphql.CollectedField, obj *model.Constraints) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Constraints_sameSlot(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.SameSlot, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]int) + fc.Result = res + return ec.marshalOInt2ᚕintᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Constraints_sameSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Constraints", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Constraints_online(ctx context.Context, field graphql.CollectedField, obj *model.Constraints) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Constraints_online(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Online, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Constraints_online(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Constraints", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Constraints_roomConstraints(ctx context.Context, field graphql.CollectedField, obj *model.Constraints) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Constraints_roomConstraints(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.RoomConstraints, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.RoomConstraints) + fc.Result = res + return ec.marshalORoomConstraints2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomConstraints(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Constraints_roomConstraints(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Constraints", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "placesWithSocket": + return ec.fieldContext_RoomConstraints_placesWithSocket(ctx, field) + case "lab": + return ec.fieldContext_RoomConstraints_lab(ctx, field) + case "exahmRooms": + return ec.fieldContext_RoomConstraints_exahmRooms(ctx, field) + case "seb": + return ec.fieldContext_RoomConstraints_seb(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type RoomConstraints", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _EnhancedPlannedRoom_day(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_EnhancedPlannedRoom_day(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Day, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_EnhancedPlannedRoom_day(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "EnhancedPlannedRoom", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _EnhancedPlannedRoom_slot(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_EnhancedPlannedRoom_slot(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Slot, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_EnhancedPlannedRoom_slot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "EnhancedPlannedRoom", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _EnhancedPlannedRoom_roomName(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_EnhancedPlannedRoom_roomName(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.RoomName, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_EnhancedPlannedRoom_roomName(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "EnhancedPlannedRoom", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _EnhancedPlannedRoom_room(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_EnhancedPlannedRoom_room(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.EnhancedPlannedRoom().Room(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Room) + fc.Result = res + return ec.marshalNRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoom(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_EnhancedPlannedRoom_room(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "EnhancedPlannedRoom", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext_Room_name(ctx, field) + case "seats": + return ec.fieldContext_Room_seats(ctx, field) + case "handicap": + return ec.fieldContext_Room_handicap(ctx, field) + case "lab": + return ec.fieldContext_Room_lab(ctx, field) + case "placesWithSocket": + return ec.fieldContext_Room_placesWithSocket(ctx, field) + case "needsRequest": + return ec.fieldContext_Room_needsRequest(ctx, field) + case "exahm": + return ec.fieldContext_Room_exahm(ctx, field) + case "seb": + return ec.fieldContext_Room_seb(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Room", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _EnhancedPlannedRoom_ancode(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_EnhancedPlannedRoom_ancode(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Ancode, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_EnhancedPlannedRoom_ancode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Constraints", + Object: "EnhancedPlannedRoom", Field: field, IsMethod: false, IsResolver: false, @@ -6792,8 +7554,8 @@ func (ec *executionContext) fieldContext_Constraints_ancode(ctx context.Context, return fc, nil } -func (ec *executionContext) _Constraints_notPlannedByMe(ctx context.Context, field graphql.CollectedField, obj *model.Constraints) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Constraints_notPlannedByMe(ctx, field) +func (ec *executionContext) _EnhancedPlannedRoom_exam(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_EnhancedPlannedRoom_exam(ctx, field) if err != nil { return graphql.Null } @@ -6806,7 +7568,7 @@ func (ec *executionContext) _Constraints_notPlannedByMe(ctx context.Context, fie }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.NotPlannedByMe, nil + return ec.resolvers.EnhancedPlannedRoom().Exam(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -6818,26 +7580,44 @@ func (ec *executionContext) _Constraints_notPlannedByMe(ctx context.Context, fie } return graphql.Null } - res := resTmp.(bool) + res := resTmp.(*model.GeneratedExam) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalNGeneratedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExam(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Constraints_notPlannedByMe(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EnhancedPlannedRoom_exam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Constraints", + Object: "EnhancedPlannedRoom", Field: field, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Boolean does not have child fields") + switch field.Name { + case "ancode": + return ec.fieldContext_GeneratedExam_ancode(ctx, field) + case "zpaExam": + return ec.fieldContext_GeneratedExam_zpaExam(ctx, field) + case "primussExams": + return ec.fieldContext_GeneratedExam_primussExams(ctx, field) + case "constraints": + return ec.fieldContext_GeneratedExam_constraints(ctx, field) + case "conflicts": + return ec.fieldContext_GeneratedExam_conflicts(ctx, field) + case "studentRegsCount": + return ec.fieldContext_GeneratedExam_studentRegsCount(ctx, field) + case "ntas": + return ec.fieldContext_GeneratedExam_ntas(ctx, field) + case "maxDuration": + return ec.fieldContext_GeneratedExam_maxDuration(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type GeneratedExam", field.Name) }, } return fc, nil } -func (ec *executionContext) _Constraints_excludeDays(ctx context.Context, field graphql.CollectedField, obj *model.Constraints) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Constraints_excludeDays(ctx, field) +func (ec *executionContext) _EnhancedPlannedRoom_duration(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_EnhancedPlannedRoom_duration(ctx, field) if err != nil { return graphql.Null } @@ -6850,35 +7630,38 @@ func (ec *executionContext) _Constraints_excludeDays(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.ExcludeDays, nil + return obj.Duration, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.([]*time.Time) + res := resTmp.(int) fc.Result = res - return ec.marshalOTime2ᚕᚖtimeᚐTimeᚄ(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Constraints_excludeDays(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EnhancedPlannedRoom_duration(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Constraints", + Object: "EnhancedPlannedRoom", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Time does not have child fields") + return nil, errors.New("field of type Int does not have child fields") }, } return fc, nil } -func (ec *executionContext) _Constraints_possibleDays(ctx context.Context, field graphql.CollectedField, obj *model.Constraints) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Constraints_possibleDays(ctx, field) +func (ec *executionContext) _EnhancedPlannedRoom_handicap(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_EnhancedPlannedRoom_handicap(ctx, field) if err != nil { return graphql.Null } @@ -6891,35 +7674,38 @@ func (ec *executionContext) _Constraints_possibleDays(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.PossibleDays, nil + return obj.Handicap, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.([]*time.Time) + res := resTmp.(bool) fc.Result = res - return ec.marshalOTime2ᚕᚖtimeᚐTimeᚄ(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Constraints_possibleDays(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EnhancedPlannedRoom_handicap(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Constraints", + Object: "EnhancedPlannedRoom", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Time does not have child fields") + return nil, errors.New("field of type Boolean does not have child fields") }, } return fc, nil } -func (ec *executionContext) _Constraints_fixedDay(ctx context.Context, field graphql.CollectedField, obj *model.Constraints) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Constraints_fixedDay(ctx, field) +func (ec *executionContext) _EnhancedPlannedRoom_handicapRoomAlone(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_EnhancedPlannedRoom_handicapRoomAlone(ctx, field) if err != nil { return graphql.Null } @@ -6932,35 +7718,38 @@ func (ec *executionContext) _Constraints_fixedDay(ctx context.Context, field gra }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.FixedDay, nil + return obj.HandicapRoomAlone, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*time.Time) + res := resTmp.(bool) fc.Result = res - return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Constraints_fixedDay(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EnhancedPlannedRoom_handicapRoomAlone(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Constraints", + Object: "EnhancedPlannedRoom", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Time does not have child fields") + return nil, errors.New("field of type Boolean does not have child fields") }, } return fc, nil } -func (ec *executionContext) _Constraints_fixedTime(ctx context.Context, field graphql.CollectedField, obj *model.Constraints) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Constraints_fixedTime(ctx, field) +func (ec *executionContext) _EnhancedPlannedRoom_reserve(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_EnhancedPlannedRoom_reserve(ctx, field) if err != nil { return graphql.Null } @@ -6973,35 +7762,38 @@ func (ec *executionContext) _Constraints_fixedTime(ctx context.Context, field gr }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.FixedTime, nil + return obj.Reserve, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*time.Time) + res := resTmp.(bool) fc.Result = res - return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Constraints_fixedTime(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EnhancedPlannedRoom_reserve(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Constraints", + Object: "EnhancedPlannedRoom", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Time does not have child fields") + return nil, errors.New("field of type Boolean does not have child fields") }, } return fc, nil } -func (ec *executionContext) _Constraints_sameSlot(ctx context.Context, field graphql.CollectedField, obj *model.Constraints) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Constraints_sameSlot(ctx, field) +func (ec *executionContext) _EnhancedPlannedRoom_studentsInRoom(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_EnhancedPlannedRoom_studentsInRoom(ctx, field) if err != nil { return graphql.Null } @@ -7014,35 +7806,38 @@ func (ec *executionContext) _Constraints_sameSlot(ctx context.Context, field gra }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.SameSlot, nil + return obj.StudentsInRoom, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.([]int) + res := resTmp.([]string) fc.Result = res - return ec.marshalOInt2ᚕintᚄ(ctx, field.Selections, res) + return ec.marshalNString2ᚕstringᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Constraints_sameSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EnhancedPlannedRoom_studentsInRoom(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Constraints", + Object: "EnhancedPlannedRoom", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil } -func (ec *executionContext) _Constraints_online(ctx context.Context, field graphql.CollectedField, obj *model.Constraints) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Constraints_online(ctx, field) +func (ec *executionContext) _EnhancedPlannedRoom_ntaMtknr(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_EnhancedPlannedRoom_ntaMtknr(ctx, field) if err != nil { return graphql.Null } @@ -7055,38 +7850,35 @@ func (ec *executionContext) _Constraints_online(ctx context.Context, field graph }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Online, nil + return obj.NtaMtknr, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(bool) + res := resTmp.(*string) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Constraints_online(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EnhancedPlannedRoom_ntaMtknr(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Constraints", + Object: "EnhancedPlannedRoom", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Boolean does not have child fields") + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil } -func (ec *executionContext) _Constraints_roomConstraints(ctx context.Context, field graphql.CollectedField, obj *model.Constraints) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Constraints_roomConstraints(ctx, field) +func (ec *executionContext) _EnhancedPlannedRoom_ntaInRoom(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_EnhancedPlannedRoom_ntaInRoom(ctx, field) if err != nil { return graphql.Null } @@ -7099,7 +7891,7 @@ func (ec *executionContext) _Constraints_roomConstraints(ctx context.Context, fi }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.RoomConstraints, nil + return ec.resolvers.EnhancedPlannedRoom().NtaInRoom(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -7108,29 +7900,43 @@ func (ec *executionContext) _Constraints_roomConstraints(ctx context.Context, fi if resTmp == nil { return graphql.Null } - res := resTmp.(*model.RoomConstraints) + res := resTmp.(*model.NTA) fc.Result = res - return ec.marshalORoomConstraints2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomConstraints(ctx, field.Selections, res) + return ec.marshalONTA2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTA(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Constraints_roomConstraints(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_EnhancedPlannedRoom_ntaInRoom(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Constraints", + Object: "EnhancedPlannedRoom", Field: field, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "placesWithSocket": - return ec.fieldContext_RoomConstraints_placesWithSocket(ctx, field) - case "lab": - return ec.fieldContext_RoomConstraints_lab(ctx, field) - case "exahmRooms": - return ec.fieldContext_RoomConstraints_exahmRooms(ctx, field) - case "seb": - return ec.fieldContext_RoomConstraints_seb(ctx, field) + case "name": + return ec.fieldContext_NTA_name(ctx, field) + case "email": + return ec.fieldContext_NTA_email(ctx, field) + case "mtknr": + return ec.fieldContext_NTA_mtknr(ctx, field) + case "compensation": + return ec.fieldContext_NTA_compensation(ctx, field) + case "deltaDurationPercent": + return ec.fieldContext_NTA_deltaDurationPercent(ctx, field) + case "needsRoomAlone": + return ec.fieldContext_NTA_needsRoomAlone(ctx, field) + case "program": + return ec.fieldContext_NTA_program(ctx, field) + case "from": + return ec.fieldContext_NTA_from(ctx, field) + case "until": + return ec.fieldContext_NTA_until(ctx, field) + case "lastSemester": + return ec.fieldContext_NTA_lastSemester(ctx, field) + case "exams": + return ec.fieldContext_NTA_exams(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type RoomConstraints", field.Name) + return nil, fmt.Errorf("no field named %q was found under type NTA", field.Name) }, } return fc, nil @@ -9546,6 +10352,8 @@ func (ec *executionContext) fieldContext_ExamWithRegsAndRooms_exam(ctx context.C return ec.fieldContext_PlannedExam_maxDuration(ctx, field) case "planEntry": return ec.fieldContext_PlannedExam_planEntry(ctx, field) + case "plannedRooms": + return ec.fieldContext_PlannedExam_plannedRooms(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type PlannedExam", field.Name) }, @@ -15442,6 +16250,69 @@ func (ec *executionContext) fieldContext_PlannedExam_planEntry(ctx context.Conte return fc, nil } +func (ec *executionContext) _PlannedExam_plannedRooms(ctx context.Context, field graphql.CollectedField, obj *model.PlannedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedExam_plannedRooms(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PlannedRooms, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.PlannedRoom) + fc.Result = res + return ec.marshalOPlannedRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedRoomᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedExam_plannedRooms(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedExam", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "day": + return ec.fieldContext_PlannedRoom_day(ctx, field) + case "slot": + return ec.fieldContext_PlannedRoom_slot(ctx, field) + case "roomName": + return ec.fieldContext_PlannedRoom_roomName(ctx, field) + case "ancode": + return ec.fieldContext_PlannedRoom_ancode(ctx, field) + case "duration": + return ec.fieldContext_PlannedRoom_duration(ctx, field) + case "handicap": + return ec.fieldContext_PlannedRoom_handicap(ctx, field) + case "handicapRoomAlone": + return ec.fieldContext_PlannedRoom_handicapRoomAlone(ctx, field) + case "reserve": + return ec.fieldContext_PlannedRoom_reserve(ctx, field) + case "studentsInRoom": + return ec.fieldContext_PlannedRoom_studentsInRoom(ctx, field) + case "ntaMtknr": + return ec.fieldContext_PlannedRoom_ntaMtknr(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type PlannedRoom", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _PlannedExamWithNTA_exam(ctx context.Context, field graphql.CollectedField, obj *model.PlannedExamWithNta) (ret graphql.Marshaler) { fc, err := ec.fieldContext_PlannedExamWithNTA_exam(ctx, field) if err != nil { @@ -18190,99 +19061,6 @@ func (ec *executionContext) fieldContext_Query_roomsForSlot(ctx context.Context, return fc, nil } -func (ec *executionContext) _Query_plannedRoomNames(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_plannedRoomNames(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().PlannedRoomNames(rctx) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.([]string) - fc.Result = res - return ec.marshalOString2ᚕstringᚄ(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_plannedRoomNames(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") - }, - } - return fc, nil -} - -func (ec *executionContext) _Query_plannedRoomNamesInSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_plannedRoomNamesInSlot(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().PlannedRoomNamesInSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.([]string) - fc.Result = res - return ec.marshalOString2ᚕstringᚄ(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_plannedRoomNamesInSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") - }, - } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_plannedRoomNamesInSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } - return fc, nil -} - func (ec *executionContext) _Query_invigilatorsWithReq(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_invigilatorsWithReq(ctx, field) if err != nil { @@ -18923,6 +19701,8 @@ func (ec *executionContext) fieldContext_Query_plannedExams(ctx context.Context, return ec.fieldContext_PlannedExam_maxDuration(ctx, field) case "planEntry": return ec.fieldContext_PlannedExam_planEntry(ctx, field) + case "plannedRooms": + return ec.fieldContext_PlannedExam_plannedRooms(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type PlannedExam", field.Name) }, @@ -18984,6 +19764,8 @@ func (ec *executionContext) fieldContext_Query_plannedExam(ctx context.Context, return ec.fieldContext_PlannedExam_maxDuration(ctx, field) case "planEntry": return ec.fieldContext_PlannedExam_planEntry(ctx, field) + case "plannedRooms": + return ec.fieldContext_PlannedExam_plannedRooms(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type PlannedExam", field.Name) }, @@ -19511,6 +20293,8 @@ func (ec *executionContext) fieldContext_Query_examsInSlot(ctx context.Context, return ec.fieldContext_PlannedExam_maxDuration(ctx, field) case "planEntry": return ec.fieldContext_PlannedExam_planEntry(ctx, field) + case "plannedRooms": + return ec.fieldContext_PlannedExam_plannedRooms(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type PlannedExam", field.Name) }, @@ -19586,6 +20370,8 @@ func (ec *executionContext) fieldContext_Query_examsWithoutSlot(ctx context.Cont return ec.fieldContext_PlannedExam_maxDuration(ctx, field) case "planEntry": return ec.fieldContext_PlannedExam_planEntry(ctx, field) + case "plannedRooms": + return ec.fieldContext_PlannedExam_plannedRooms(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type PlannedExam", field.Name) }, @@ -19825,6 +20611,179 @@ func (ec *executionContext) fieldContext_Query_rooms(ctx context.Context, field return fc, nil } +func (ec *executionContext) _Query_plannedRoomNames(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_plannedRoomNames(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().PlannedRoomNames(rctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]string) + fc.Result = res + return ec.marshalOString2ᚕstringᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_plannedRoomNames(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Query_plannedRoomNamesInSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_plannedRoomNamesInSlot(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().PlannedRoomNamesInSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]string) + fc.Result = res + return ec.marshalOString2ᚕstringᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_plannedRoomNamesInSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_plannedRoomNamesInSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_plannedRoomsInSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_plannedRoomsInSlot(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().PlannedRoomsInSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.EnhancedPlannedRoom) + fc.Result = res + return ec.marshalOEnhancedPlannedRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPlannedRoomᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_plannedRoomsInSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "day": + return ec.fieldContext_EnhancedPlannedRoom_day(ctx, field) + case "slot": + return ec.fieldContext_EnhancedPlannedRoom_slot(ctx, field) + case "roomName": + return ec.fieldContext_EnhancedPlannedRoom_roomName(ctx, field) + case "room": + return ec.fieldContext_EnhancedPlannedRoom_room(ctx, field) + case "ancode": + return ec.fieldContext_EnhancedPlannedRoom_ancode(ctx, field) + case "exam": + return ec.fieldContext_EnhancedPlannedRoom_exam(ctx, field) + case "duration": + return ec.fieldContext_EnhancedPlannedRoom_duration(ctx, field) + case "handicap": + return ec.fieldContext_EnhancedPlannedRoom_handicap(ctx, field) + case "handicapRoomAlone": + return ec.fieldContext_EnhancedPlannedRoom_handicapRoomAlone(ctx, field) + case "reserve": + return ec.fieldContext_EnhancedPlannedRoom_reserve(ctx, field) + case "studentsInRoom": + return ec.fieldContext_EnhancedPlannedRoom_studentsInRoom(ctx, field) + case "ntaMtknr": + return ec.fieldContext_EnhancedPlannedRoom_ntaMtknr(ctx, field) + case "ntaInRoom": + return ec.fieldContext_EnhancedPlannedRoom_ntaInRoom(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type EnhancedPlannedRoom", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_plannedRoomsInSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Query_studentByMtknr(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_studentByMtknr(ctx, field) if err != nil { @@ -28660,6 +29619,192 @@ func (ec *executionContext) _Constraints(ctx context.Context, sel ast.SelectionS return out } +var enhancedPlannedRoomImplementors = []string{"EnhancedPlannedRoom"} + +func (ec *executionContext) _EnhancedPlannedRoom(ctx context.Context, sel ast.SelectionSet, obj *model.EnhancedPlannedRoom) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, enhancedPlannedRoomImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("EnhancedPlannedRoom") + case "day": + out.Values[i] = ec._EnhancedPlannedRoom_day(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "slot": + out.Values[i] = ec._EnhancedPlannedRoom_slot(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "roomName": + out.Values[i] = ec._EnhancedPlannedRoom_roomName(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "room": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._EnhancedPlannedRoom_room(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "ancode": + out.Values[i] = ec._EnhancedPlannedRoom_ancode(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "exam": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._EnhancedPlannedRoom_exam(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "duration": + out.Values[i] = ec._EnhancedPlannedRoom_duration(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "handicap": + out.Values[i] = ec._EnhancedPlannedRoom_handicap(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "handicapRoomAlone": + out.Values[i] = ec._EnhancedPlannedRoom_handicapRoomAlone(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "reserve": + out.Values[i] = ec._EnhancedPlannedRoom_reserve(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "studentsInRoom": + out.Values[i] = ec._EnhancedPlannedRoom_studentsInRoom(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "ntaMtknr": + out.Values[i] = ec._EnhancedPlannedRoom_ntaMtknr(ctx, field, obj) + case "ntaInRoom": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._EnhancedPlannedRoom_ntaInRoom(ctx, field, obj) + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var enhancedPrimussExamImplementors = []string{"EnhancedPrimussExam"} func (ec *executionContext) _EnhancedPrimussExam(ctx context.Context, sel ast.SelectionSet, obj *model.EnhancedPrimussExam) graphql.Marshaler { @@ -30422,6 +31567,8 @@ func (ec *executionContext) _PlannedExam(ctx context.Context, sel ast.SelectionS } case "planEntry": out.Values[i] = ec._PlannedExam_planEntry(ctx, field, obj) + case "plannedRooms": + out.Values[i] = ec._PlannedExam_plannedRooms(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -31277,44 +32424,6 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "plannedRoomNames": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_plannedRoomNames(ctx, field) - return res - } - - rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, - func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - } - - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "plannedRoomNamesInSlot": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_plannedRoomNamesInSlot(ctx, field) - return res - } - - rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, - func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "invigilatorsWithReq": field := field @@ -31836,6 +32945,63 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "plannedRoomNames": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_plannedRoomNames(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "plannedRoomNamesInSlot": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_plannedRoomNamesInSlot(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "plannedRoomsInSlot": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_plannedRoomsInSlot(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "studentByMtknr": field := field @@ -34019,7 +35185,189 @@ func (ec *executionContext) marshalNAdditionalExam2ᚕᚖgithubᚗcomᚋobcode if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNAdditionalExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAdditionalExam(ctx, sel, v[i]) + ret[i] = ec.marshalNAdditionalExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAdditionalExam(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNAdditionalExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAdditionalExam(ctx context.Context, sel ast.SelectionSet, v *model.AdditionalExam) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._AdditionalExam(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNAdditionalExamInput2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAdditionalExamInput(ctx context.Context, v interface{}) (model.AdditionalExamInput, error) { + res, err := ec.unmarshalInputAdditionalExamInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v interface{}) (bool, error) { + res, err := graphql.UnmarshalBoolean(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { + res := graphql.MarshalBoolean(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) marshalNConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Conflict) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflict(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflict(ctx context.Context, sel ast.SelectionSet, v *model.Conflict) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._Conflict(ctx, sel, v) +} + +func (ec *executionContext) marshalNConflictPerProgram2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictPerProgramᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ConflictPerProgram) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNConflictPerProgram2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictPerProgram(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNConflictPerProgram2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictPerProgram(ctx context.Context, sel ast.SelectionSet, v *model.ConflictPerProgram) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._ConflictPerProgram(ctx, sel, v) +} + +func (ec *executionContext) marshalNConflictsPerProgramAncode2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictsPerProgramAncodeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ConflictsPerProgramAncode) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNConflictsPerProgramAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictsPerProgramAncode(ctx, sel, v[i]) } if isLen1 { f(i) @@ -34039,37 +35387,17 @@ func (ec *executionContext) marshalNAdditionalExam2ᚕᚖgithubᚗcomᚋobcode return ret } -func (ec *executionContext) marshalNAdditionalExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAdditionalExam(ctx context.Context, sel ast.SelectionSet, v *model.AdditionalExam) graphql.Marshaler { +func (ec *executionContext) marshalNConflictsPerProgramAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictsPerProgramAncode(ctx context.Context, sel ast.SelectionSet, v *model.ConflictsPerProgramAncode) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._AdditionalExam(ctx, sel, v) -} - -func (ec *executionContext) unmarshalNAdditionalExamInput2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAdditionalExamInput(ctx context.Context, v interface{}) (model.AdditionalExamInput, error) { - res, err := ec.unmarshalInputAdditionalExamInput(ctx, v) - return res, graphql.ErrorOnPath(ctx, err) -} - -func (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v interface{}) (bool, error) { - res, err := graphql.UnmarshalBoolean(v) - return res, graphql.ErrorOnPath(ctx, err) -} - -func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { - res := graphql.MarshalBoolean(v) - if res == graphql.Null { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - } - return res + return ec._ConflictsPerProgramAncode(ctx, sel, v) } -func (ec *executionContext) marshalNConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Conflict) graphql.Marshaler { +func (ec *executionContext) marshalNConnectedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ConnectedExam) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -34093,7 +35421,7 @@ func (ec *executionContext) marshalNConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexa if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflict(ctx, sel, v[i]) + ret[i] = ec.marshalNConnectedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExam(ctx, sel, v[i]) } if isLen1 { f(i) @@ -34113,17 +35441,27 @@ func (ec *executionContext) marshalNConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexa return ret } -func (ec *executionContext) marshalNConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflict(ctx context.Context, sel ast.SelectionSet, v *model.Conflict) graphql.Marshaler { +func (ec *executionContext) marshalNConnectedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExam(ctx context.Context, sel ast.SelectionSet, v *model.ConnectedExam) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._Conflict(ctx, sel, v) + return ec._ConnectedExam(ctx, sel, v) } -func (ec *executionContext) marshalNConflictPerProgram2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictPerProgramᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ConflictPerProgram) graphql.Marshaler { +func (ec *executionContext) marshalNEnhancedPlannedRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPlannedRoom(ctx context.Context, sel ast.SelectionSet, v *model.EnhancedPlannedRoom) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._EnhancedPlannedRoom(ctx, sel, v) +} + +func (ec *executionContext) marshalNEnhancedPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPrimussExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.EnhancedPrimussExam) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -34147,7 +35485,7 @@ func (ec *executionContext) marshalNConflictPerProgram2ᚕᚖgithubᚗcomᚋobco if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNConflictPerProgram2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictPerProgram(ctx, sel, v[i]) + ret[i] = ec.marshalNEnhancedPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPrimussExam(ctx, sel, v[i]) } if isLen1 { f(i) @@ -34167,17 +35505,17 @@ func (ec *executionContext) marshalNConflictPerProgram2ᚕᚖgithubᚗcomᚋobco return ret } -func (ec *executionContext) marshalNConflictPerProgram2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictPerProgram(ctx context.Context, sel ast.SelectionSet, v *model.ConflictPerProgram) graphql.Marshaler { +func (ec *executionContext) marshalNEnhancedPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPrimussExam(ctx context.Context, sel ast.SelectionSet, v *model.EnhancedPrimussExam) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._ConflictPerProgram(ctx, sel, v) + return ec._EnhancedPrimussExam(ctx, sel, v) } -func (ec *executionContext) marshalNConflictsPerProgramAncode2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictsPerProgramAncodeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ConflictsPerProgramAncode) graphql.Marshaler { +func (ec *executionContext) marshalNExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Exam) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -34201,7 +35539,7 @@ func (ec *executionContext) marshalNConflictsPerProgramAncode2ᚕᚖgithubᚗcom if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNConflictsPerProgramAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictsPerProgramAncode(ctx, sel, v[i]) + ret[i] = ec.marshalNExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExam(ctx, sel, v[i]) } if isLen1 { f(i) @@ -34221,17 +35559,17 @@ func (ec *executionContext) marshalNConflictsPerProgramAncode2ᚕᚖgithubᚗcom return ret } -func (ec *executionContext) marshalNConflictsPerProgramAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictsPerProgramAncode(ctx context.Context, sel ast.SelectionSet, v *model.ConflictsPerProgramAncode) graphql.Marshaler { +func (ec *executionContext) marshalNExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExam(ctx context.Context, sel ast.SelectionSet, v *model.Exam) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._ConflictsPerProgramAncode(ctx, sel, v) + return ec._Exam(ctx, sel, v) } -func (ec *executionContext) marshalNConnectedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ConnectedExam) graphql.Marshaler { +func (ec *executionContext) marshalNExamDay2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamDayᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExamDay) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -34255,7 +35593,7 @@ func (ec *executionContext) marshalNConnectedExam2ᚕᚖgithubᚗcomᚋobcodeᚋ if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNConnectedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExam(ctx, sel, v[i]) + ret[i] = ec.marshalNExamDay2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamDay(ctx, sel, v[i]) } if isLen1 { f(i) @@ -34275,17 +35613,17 @@ func (ec *executionContext) marshalNConnectedExam2ᚕᚖgithubᚗcomᚋobcodeᚋ return ret } -func (ec *executionContext) marshalNConnectedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExam(ctx context.Context, sel ast.SelectionSet, v *model.ConnectedExam) graphql.Marshaler { +func (ec *executionContext) marshalNExamDay2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamDay(ctx context.Context, sel ast.SelectionSet, v *model.ExamDay) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._ConnectedExam(ctx, sel, v) + return ec._ExamDay(ctx, sel, v) } -func (ec *executionContext) marshalNEnhancedPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPrimussExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.EnhancedPrimussExam) graphql.Marshaler { +func (ec *executionContext) marshalNExamGroup2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExamGroup) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -34309,7 +35647,7 @@ func (ec *executionContext) marshalNEnhancedPrimussExam2ᚕᚖgithubᚗcomᚋobc if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNEnhancedPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPrimussExam(ctx, sel, v[i]) + ret[i] = ec.marshalNExamGroup2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroup(ctx, sel, v[i]) } if isLen1 { f(i) @@ -34329,17 +35667,27 @@ func (ec *executionContext) marshalNEnhancedPrimussExam2ᚕᚖgithubᚗcomᚋobc return ret } -func (ec *executionContext) marshalNEnhancedPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPrimussExam(ctx context.Context, sel ast.SelectionSet, v *model.EnhancedPrimussExam) graphql.Marshaler { +func (ec *executionContext) marshalNExamGroup2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroup(ctx context.Context, sel ast.SelectionSet, v *model.ExamGroup) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._EnhancedPrimussExam(ctx, sel, v) + return ec._ExamGroup(ctx, sel, v) } -func (ec *executionContext) marshalNExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Exam) graphql.Marshaler { +func (ec *executionContext) marshalNExamInPlan2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamInPlan(ctx context.Context, sel ast.SelectionSet, v *model.ExamInPlan) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._ExamInPlan(ctx, sel, v) +} + +func (ec *executionContext) marshalNExamToPlan2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamToPlanᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExamToPlan) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -34363,7 +35711,7 @@ func (ec *executionContext) marshalNExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexams if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExam(ctx, sel, v[i]) + ret[i] = ec.marshalNExamToPlan2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamToPlan(ctx, sel, v[i]) } if isLen1 { f(i) @@ -34383,17 +35731,47 @@ func (ec *executionContext) marshalNExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexams return ret } -func (ec *executionContext) marshalNExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExam(ctx context.Context, sel ast.SelectionSet, v *model.Exam) graphql.Marshaler { +func (ec *executionContext) marshalNExamToPlan2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamToPlan(ctx context.Context, sel ast.SelectionSet, v *model.ExamToPlan) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._Exam(ctx, sel, v) + return ec._ExamToPlan(ctx, sel, v) } -func (ec *executionContext) marshalNExamDay2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamDayᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExamDay) graphql.Marshaler { +func (ec *executionContext) marshalNExamWithRegs2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegs(ctx context.Context, sel ast.SelectionSet, v *model.ExamWithRegs) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._ExamWithRegs(ctx, sel, v) +} + +func (ec *executionContext) marshalNExamWithRegsAndRooms2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegsAndRooms(ctx context.Context, sel ast.SelectionSet, v *model.ExamWithRegsAndRooms) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._ExamWithRegsAndRooms(ctx, sel, v) +} + +func (ec *executionContext) marshalNExamerInPlan2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamerInPlan(ctx context.Context, sel ast.SelectionSet, v *model.ExamerInPlan) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._ExamerInPlan(ctx, sel, v) +} + +func (ec *executionContext) marshalNExternalExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExternalExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExternalExam) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -34417,7 +35795,7 @@ func (ec *executionContext) marshalNExamDay2ᚕᚖgithubᚗcomᚋobcodeᚋplexam if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNExamDay2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamDay(ctx, sel, v[i]) + ret[i] = ec.marshalNExternalExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExternalExam(ctx, sel, v[i]) } if isLen1 { f(i) @@ -34437,17 +35815,17 @@ func (ec *executionContext) marshalNExamDay2ᚕᚖgithubᚗcomᚋobcodeᚋplexam return ret } -func (ec *executionContext) marshalNExamDay2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamDay(ctx context.Context, sel ast.SelectionSet, v *model.ExamDay) graphql.Marshaler { +func (ec *executionContext) marshalNExternalExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExternalExam(ctx context.Context, sel ast.SelectionSet, v *model.ExternalExam) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._ExamDay(ctx, sel, v) + return ec._ExternalExam(ctx, sel, v) } -func (ec *executionContext) marshalNExamGroup2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroupᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExamGroup) graphql.Marshaler { +func (ec *executionContext) marshalNFK07Program2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐFK07Programᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.FK07Program) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -34471,7 +35849,7 @@ func (ec *executionContext) marshalNExamGroup2ᚕᚖgithubᚗcomᚋobcodeᚋplex if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNExamGroup2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroup(ctx, sel, v[i]) + ret[i] = ec.marshalNFK07Program2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐFK07Program(ctx, sel, v[i]) } if isLen1 { f(i) @@ -34491,27 +35869,36 @@ func (ec *executionContext) marshalNExamGroup2ᚕᚖgithubᚗcomᚋobcodeᚋplex return ret } -func (ec *executionContext) marshalNExamGroup2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamGroup(ctx context.Context, sel ast.SelectionSet, v *model.ExamGroup) graphql.Marshaler { +func (ec *executionContext) marshalNFK07Program2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐFK07Program(ctx context.Context, sel ast.SelectionSet, v *model.FK07Program) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._ExamGroup(ctx, sel, v) + return ec._FK07Program(ctx, sel, v) } -func (ec *executionContext) marshalNExamInPlan2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamInPlan(ctx context.Context, sel ast.SelectionSet, v *model.ExamInPlan) graphql.Marshaler { - if v == nil { +func (ec *executionContext) unmarshalNFloat2float64(ctx context.Context, v interface{}) (float64, error) { + res, err := graphql.UnmarshalFloatContext(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNFloat2float64(ctx context.Context, sel ast.SelectionSet, v float64) graphql.Marshaler { + res := graphql.MarshalFloatContext(v) + if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } - return graphql.Null } - return ec._ExamInPlan(ctx, sel, v) + return graphql.WrapContextMarshaler(ctx, res) } -func (ec *executionContext) marshalNExamToPlan2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamToPlanᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExamToPlan) graphql.Marshaler { +func (ec *executionContext) marshalNGeneratedExam2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExam(ctx context.Context, sel ast.SelectionSet, v model.GeneratedExam) graphql.Marshaler { + return ec._GeneratedExam(ctx, sel, &v) +} + +func (ec *executionContext) marshalNGeneratedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.GeneratedExam) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -34535,7 +35922,7 @@ func (ec *executionContext) marshalNExamToPlan2ᚕᚖgithubᚗcomᚋobcodeᚋple if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNExamToPlan2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamToPlan(ctx, sel, v[i]) + ret[i] = ec.marshalNGeneratedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExam(ctx, sel, v[i]) } if isLen1 { f(i) @@ -34555,80 +35942,53 @@ func (ec *executionContext) marshalNExamToPlan2ᚕᚖgithubᚗcomᚋobcodeᚋple return ret } -func (ec *executionContext) marshalNExamToPlan2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamToPlan(ctx context.Context, sel ast.SelectionSet, v *model.ExamToPlan) graphql.Marshaler { +func (ec *executionContext) marshalNGeneratedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExam(ctx context.Context, sel ast.SelectionSet, v *model.GeneratedExam) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._ExamToPlan(ctx, sel, v) + return ec._GeneratedExam(ctx, sel, v) } -func (ec *executionContext) marshalNExamWithRegs2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegs(ctx context.Context, sel ast.SelectionSet, v *model.ExamWithRegs) graphql.Marshaler { - if v == nil { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - return graphql.Null - } - return ec._ExamWithRegs(ctx, sel, v) +func (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) { + res, err := graphql.UnmarshalInt(v) + return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalNExamWithRegsAndRooms2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamWithRegsAndRooms(ctx context.Context, sel ast.SelectionSet, v *model.ExamWithRegsAndRooms) graphql.Marshaler { - if v == nil { +func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler { + res := graphql.MarshalInt(v) + if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } - return graphql.Null } - return ec._ExamWithRegsAndRooms(ctx, sel, v) + return res } -func (ec *executionContext) marshalNExamerInPlan2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExamerInPlan(ctx context.Context, sel ast.SelectionSet, v *model.ExamerInPlan) graphql.Marshaler { - if v == nil { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") +func (ec *executionContext) unmarshalNInt2ᚕintᚄ(ctx context.Context, v interface{}) ([]int, error) { + var vSlice []interface{} + if v != nil { + vSlice = graphql.CoerceList(v) + } + var err error + res := make([]int, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNInt2int(ctx, vSlice[i]) + if err != nil { + return nil, err } - return graphql.Null } - return ec._ExamerInPlan(ctx, sel, v) + return res, nil } -func (ec *executionContext) marshalNExternalExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExternalExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ExternalExam) graphql.Marshaler { +func (ec *executionContext) marshalNInt2ᚕintᚄ(ctx context.Context, sel ast.SelectionSet, v []int) graphql.Marshaler { ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } for i := range v { - i := i - fc := &graphql.FieldContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithFieldContext(ctx, fc) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalNExternalExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExternalExam(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - + ret[i] = ec.marshalNInt2int(ctx, sel, v[i]) } - wg.Wait() for _, e := range ret { if e == graphql.Null { @@ -34639,17 +35999,17 @@ func (ec *executionContext) marshalNExternalExam2ᚕᚖgithubᚗcomᚋobcodeᚋp return ret } -func (ec *executionContext) marshalNExternalExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExternalExam(ctx context.Context, sel ast.SelectionSet, v *model.ExternalExam) graphql.Marshaler { +func (ec *executionContext) marshalNInvigilation2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilation(ctx context.Context, sel ast.SelectionSet, v *model.Invigilation) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._ExternalExam(ctx, sel, v) + return ec._Invigilation(ctx, sel, v) } -func (ec *executionContext) marshalNFK07Program2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐFK07Programᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.FK07Program) graphql.Marshaler { +func (ec *executionContext) marshalNInvigilator2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilatorᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Invigilator) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -34673,7 +36033,7 @@ func (ec *executionContext) marshalNFK07Program2ᚕᚖgithubᚗcomᚋobcodeᚋpl if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNFK07Program2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐFK07Program(ctx, sel, v[i]) + ret[i] = ec.marshalNInvigilator2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilator(ctx, sel, v[i]) } if isLen1 { f(i) @@ -34693,32 +36053,21 @@ func (ec *executionContext) marshalNFK07Program2ᚕᚖgithubᚗcomᚋobcodeᚋpl return ret } -func (ec *executionContext) marshalNFK07Program2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐFK07Program(ctx context.Context, sel ast.SelectionSet, v *model.FK07Program) graphql.Marshaler { +func (ec *executionContext) marshalNInvigilator2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilator(ctx context.Context, sel ast.SelectionSet, v *model.Invigilator) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._FK07Program(ctx, sel, v) -} - -func (ec *executionContext) unmarshalNFloat2float64(ctx context.Context, v interface{}) (float64, error) { - res, err := graphql.UnmarshalFloatContext(ctx, v) - return res, graphql.ErrorOnPath(ctx, err) + return ec._Invigilator(ctx, sel, v) } -func (ec *executionContext) marshalNFloat2float64(ctx context.Context, sel ast.SelectionSet, v float64) graphql.Marshaler { - res := graphql.MarshalFloatContext(v) - if res == graphql.Null { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - } - return graphql.WrapContextMarshaler(ctx, res) +func (ec *executionContext) marshalNNTA2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTA(ctx context.Context, sel ast.SelectionSet, v model.NTA) graphql.Marshaler { + return ec._NTA(ctx, sel, &v) } -func (ec *executionContext) marshalNGeneratedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.GeneratedExam) graphql.Marshaler { +func (ec *executionContext) marshalNNTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.NTA) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -34742,7 +36091,7 @@ func (ec *executionContext) marshalNGeneratedExam2ᚕᚖgithubᚗcomᚋobcodeᚋ if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNGeneratedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExam(ctx, sel, v[i]) + ret[i] = ec.marshalNNTA2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTA(ctx, sel, v[i]) } if isLen1 { f(i) @@ -34762,74 +36111,106 @@ func (ec *executionContext) marshalNGeneratedExam2ᚕᚖgithubᚗcomᚋobcodeᚋ return ret } -func (ec *executionContext) marshalNGeneratedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExam(ctx context.Context, sel ast.SelectionSet, v *model.GeneratedExam) graphql.Marshaler { +func (ec *executionContext) marshalNNTA2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTA(ctx context.Context, sel ast.SelectionSet, v *model.NTA) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._GeneratedExam(ctx, sel, v) + return ec._NTA(ctx, sel, v) } -func (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) { - res, err := graphql.UnmarshalInt(v) - return res, graphql.ErrorOnPath(ctx, err) +func (ec *executionContext) marshalNNTAExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.NTAExam) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNNTAExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAExam(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret } -func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler { - res := graphql.MarshalInt(v) - if res == graphql.Null { +func (ec *executionContext) marshalNNTAExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAExam(ctx context.Context, sel ast.SelectionSet, v *model.NTAExam) graphql.Marshaler { + if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } + return graphql.Null } - return res + return ec._NTAExam(ctx, sel, v) } -func (ec *executionContext) unmarshalNInt2ᚕintᚄ(ctx context.Context, v interface{}) ([]int, error) { - var vSlice []interface{} - if v != nil { - vSlice = graphql.CoerceList(v) - } - var err error - res := make([]int, len(vSlice)) - for i := range vSlice { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNInt2int(ctx, vSlice[i]) - if err != nil { - return nil, err - } - } - return res, nil +func (ec *executionContext) unmarshalNNTAInput2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAInput(ctx context.Context, v interface{}) (model.NTAInput, error) { + res, err := ec.unmarshalInputNTAInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalNInt2ᚕintᚄ(ctx context.Context, sel ast.SelectionSet, v []int) graphql.Marshaler { - ret := make(graphql.Array, len(v)) - for i := range v { - ret[i] = ec.marshalNInt2int(ctx, sel, v[i]) +func (ec *executionContext) marshalNNTAWithRegs2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegs(ctx context.Context, sel ast.SelectionSet, v *model.NTAWithRegs) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null } + return ec._NTAWithRegs(ctx, sel, v) +} - for _, e := range ret { - if e == graphql.Null { - return graphql.Null +func (ec *executionContext) marshalNNTAWithRegsByExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsByExam(ctx context.Context, sel ast.SelectionSet, v *model.NTAWithRegsByExam) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") } + return graphql.Null } - - return ret + return ec._NTAWithRegsByExam(ctx, sel, v) } -func (ec *executionContext) marshalNInvigilation2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilation(ctx context.Context, sel ast.SelectionSet, v *model.Invigilation) graphql.Marshaler { +func (ec *executionContext) marshalNNTAWithRegsByExamAndTeacher2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsByExamAndTeacher(ctx context.Context, sel ast.SelectionSet, v *model.NTAWithRegsByExamAndTeacher) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._Invigilation(ctx, sel, v) + return ec._NTAWithRegsByExamAndTeacher(ctx, sel, v) } -func (ec *executionContext) marshalNInvigilator2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilatorᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Invigilator) graphql.Marshaler { +func (ec *executionContext) marshalNPlannedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PlannedExam) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -34853,7 +36234,7 @@ func (ec *executionContext) marshalNInvigilator2ᚕᚖgithubᚗcomᚋobcodeᚋpl if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNInvigilator2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilator(ctx, sel, v[i]) + ret[i] = ec.marshalNPlannedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExam(ctx, sel, v[i]) } if isLen1 { f(i) @@ -34873,21 +36254,27 @@ func (ec *executionContext) marshalNInvigilator2ᚕᚖgithubᚗcomᚋobcodeᚋpl return ret } -func (ec *executionContext) marshalNInvigilator2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilator(ctx context.Context, sel ast.SelectionSet, v *model.Invigilator) graphql.Marshaler { +func (ec *executionContext) marshalNPlannedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExam(ctx context.Context, sel ast.SelectionSet, v *model.PlannedExam) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._Invigilator(ctx, sel, v) + return ec._PlannedExam(ctx, sel, v) } -func (ec *executionContext) marshalNNTA2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTA(ctx context.Context, sel ast.SelectionSet, v model.NTA) graphql.Marshaler { - return ec._NTA(ctx, sel, &v) +func (ec *executionContext) marshalNPlannedExamWithNTA2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExamWithNta(ctx context.Context, sel ast.SelectionSet, v *model.PlannedExamWithNta) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._PlannedExamWithNTA(ctx, sel, v) } -func (ec *executionContext) marshalNNTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.NTA) graphql.Marshaler { +func (ec *executionContext) marshalNPlannedRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedRoomᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PlannedRoom) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -34911,7 +36298,7 @@ func (ec *executionContext) marshalNNTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗ if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNNTA2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTA(ctx, sel, v[i]) + ret[i] = ec.marshalNPlannedRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedRoom(ctx, sel, v[i]) } if isLen1 { f(i) @@ -34931,17 +36318,21 @@ func (ec *executionContext) marshalNNTA2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗ return ret } -func (ec *executionContext) marshalNNTA2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTA(ctx context.Context, sel ast.SelectionSet, v *model.NTA) graphql.Marshaler { +func (ec *executionContext) marshalNPlannedRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedRoom(ctx context.Context, sel ast.SelectionSet, v *model.PlannedRoom) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._NTA(ctx, sel, v) + return ec._PlannedRoom(ctx, sel, v) } -func (ec *executionContext) marshalNNTAExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.NTAExam) graphql.Marshaler { +func (ec *executionContext) marshalNPrimussExam2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx context.Context, sel ast.SelectionSet, v model.PrimussExam) graphql.Marshaler { + return ec._PrimussExam(ctx, sel, &v) +} + +func (ec *executionContext) marshalNPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PrimussExam) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -34965,7 +36356,7 @@ func (ec *executionContext) marshalNNTAExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexam if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNNTAExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAExam(ctx, sel, v[i]) + ret[i] = ec.marshalNPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx, sel, v[i]) } if isLen1 { f(i) @@ -34985,52 +36376,71 @@ func (ec *executionContext) marshalNNTAExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexam return ret } -func (ec *executionContext) marshalNNTAExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAExam(ctx context.Context, sel ast.SelectionSet, v *model.NTAExam) graphql.Marshaler { +func (ec *executionContext) marshalNPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx context.Context, sel ast.SelectionSet, v *model.PrimussExam) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._NTAExam(ctx, sel, v) -} - -func (ec *executionContext) unmarshalNNTAInput2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAInput(ctx context.Context, v interface{}) (model.NTAInput, error) { - res, err := ec.unmarshalInputNTAInput(ctx, v) - return res, graphql.ErrorOnPath(ctx, err) + return ec._PrimussExam(ctx, sel, v) } -func (ec *executionContext) marshalNNTAWithRegs2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegs(ctx context.Context, sel ast.SelectionSet, v *model.NTAWithRegs) graphql.Marshaler { - if v == nil { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") +func (ec *executionContext) marshalNPrimussExamAncode2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncodeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PrimussExamAncode) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], } - return graphql.Null + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNPrimussExamAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncode(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + } - return ec._NTAWithRegs(ctx, sel, v) -} + wg.Wait() -func (ec *executionContext) marshalNNTAWithRegsByExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsByExam(ctx context.Context, sel ast.SelectionSet, v *model.NTAWithRegsByExam) graphql.Marshaler { - if v == nil { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") + for _, e := range ret { + if e == graphql.Null { + return graphql.Null } - return graphql.Null } - return ec._NTAWithRegsByExam(ctx, sel, v) + + return ret } -func (ec *executionContext) marshalNNTAWithRegsByExamAndTeacher2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTAWithRegsByExamAndTeacher(ctx context.Context, sel ast.SelectionSet, v *model.NTAWithRegsByExamAndTeacher) graphql.Marshaler { +func (ec *executionContext) marshalNPrimussExamAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncode(ctx context.Context, sel ast.SelectionSet, v *model.PrimussExamAncode) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._NTAWithRegsByExamAndTeacher(ctx, sel, v) + return ec._PrimussExamAncode(ctx, sel, v) } -func (ec *executionContext) marshalNPlannedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PlannedExam) graphql.Marshaler { +func (ec *executionContext) marshalNPrimussExamWithCount2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamWithCountᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PrimussExamWithCount) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35054,7 +36464,7 @@ func (ec *executionContext) marshalNPlannedExam2ᚕᚖgithubᚗcomᚋobcodeᚋpl if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNPlannedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExam(ctx, sel, v[i]) + ret[i] = ec.marshalNPrimussExamWithCount2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamWithCount(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35074,27 +36484,17 @@ func (ec *executionContext) marshalNPlannedExam2ᚕᚖgithubᚗcomᚋobcodeᚋpl return ret } -func (ec *executionContext) marshalNPlannedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExam(ctx context.Context, sel ast.SelectionSet, v *model.PlannedExam) graphql.Marshaler { - if v == nil { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - return graphql.Null - } - return ec._PlannedExam(ctx, sel, v) -} - -func (ec *executionContext) marshalNPlannedExamWithNTA2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedExamWithNta(ctx context.Context, sel ast.SelectionSet, v *model.PlannedExamWithNta) graphql.Marshaler { +func (ec *executionContext) marshalNPrimussExamWithCount2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamWithCount(ctx context.Context, sel ast.SelectionSet, v *model.PrimussExamWithCount) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._PlannedExamWithNTA(ctx, sel, v) + return ec._PrimussExamWithCount(ctx, sel, v) } -func (ec *executionContext) marshalNPlannedRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedRoomᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PlannedRoom) graphql.Marshaler { +func (ec *executionContext) marshalNRegWithError2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRegWithErrorᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.RegWithError) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35118,7 +36518,7 @@ func (ec *executionContext) marshalNPlannedRoom2ᚕᚖgithubᚗcomᚋobcodeᚋpl if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNPlannedRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedRoom(ctx, sel, v[i]) + ret[i] = ec.marshalNRegWithError2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRegWithError(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35138,21 +36538,21 @@ func (ec *executionContext) marshalNPlannedRoom2ᚕᚖgithubᚗcomᚋobcodeᚋpl return ret } -func (ec *executionContext) marshalNPlannedRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedRoom(ctx context.Context, sel ast.SelectionSet, v *model.PlannedRoom) graphql.Marshaler { +func (ec *executionContext) marshalNRegWithError2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRegWithError(ctx context.Context, sel ast.SelectionSet, v *model.RegWithError) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._PlannedRoom(ctx, sel, v) + return ec._RegWithError(ctx, sel, v) } -func (ec *executionContext) marshalNPrimussExam2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx context.Context, sel ast.SelectionSet, v model.PrimussExam) graphql.Marshaler { - return ec._PrimussExam(ctx, sel, &v) +func (ec *executionContext) marshalNRoom2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoom(ctx context.Context, sel ast.SelectionSet, v model.Room) graphql.Marshaler { + return ec._Room(ctx, sel, &v) } -func (ec *executionContext) marshalNPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PrimussExam) graphql.Marshaler { +func (ec *executionContext) marshalNRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Room) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35176,7 +36576,7 @@ func (ec *executionContext) marshalNPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋpl if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx, sel, v[i]) + ret[i] = ec.marshalNRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoom(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35196,17 +36596,17 @@ func (ec *executionContext) marshalNPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋpl return ret } -func (ec *executionContext) marshalNPrimussExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExam(ctx context.Context, sel ast.SelectionSet, v *model.PrimussExam) graphql.Marshaler { +func (ec *executionContext) marshalNRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoom(ctx context.Context, sel ast.SelectionSet, v *model.Room) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._PrimussExam(ctx, sel, v) + return ec._Room(ctx, sel, v) } -func (ec *executionContext) marshalNPrimussExamAncode2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncodeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PrimussExamAncode) graphql.Marshaler { +func (ec *executionContext) marshalNRoomAndExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomAndExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.RoomAndExam) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35230,7 +36630,7 @@ func (ec *executionContext) marshalNPrimussExamAncode2ᚕᚖgithubᚗcomᚋobcod if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNPrimussExamAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncode(ctx, sel, v[i]) + ret[i] = ec.marshalNRoomAndExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomAndExam(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35250,17 +36650,32 @@ func (ec *executionContext) marshalNPrimussExamAncode2ᚕᚖgithubᚗcomᚋobcod return ret } -func (ec *executionContext) marshalNPrimussExamAncode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamAncode(ctx context.Context, sel ast.SelectionSet, v *model.PrimussExamAncode) graphql.Marshaler { +func (ec *executionContext) marshalNRoomAndExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomAndExam(ctx context.Context, sel ast.SelectionSet, v *model.RoomAndExam) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._PrimussExamAncode(ctx, sel, v) + return ec._RoomAndExam(ctx, sel, v) } -func (ec *executionContext) marshalNPrimussExamWithCount2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamWithCountᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PrimussExamWithCount) graphql.Marshaler { +func (ec *executionContext) marshalNRoomForExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomForExam(ctx context.Context, sel ast.SelectionSet, v *model.RoomForExam) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._RoomForExam(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNRoomForExamInput2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomForExamInput(ctx context.Context, v interface{}) (model.RoomForExamInput, error) { + res, err := ec.unmarshalInputRoomForExamInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNRoomWithInvigilator2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomWithInvigilatorᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.RoomWithInvigilator) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35284,7 +36699,7 @@ func (ec *executionContext) marshalNPrimussExamWithCount2ᚕᚖgithubᚗcomᚋob if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNPrimussExamWithCount2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamWithCount(ctx, sel, v[i]) + ret[i] = ec.marshalNRoomWithInvigilator2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomWithInvigilator(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35304,17 +36719,21 @@ func (ec *executionContext) marshalNPrimussExamWithCount2ᚕᚖgithubᚗcomᚋob return ret } -func (ec *executionContext) marshalNPrimussExamWithCount2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamWithCount(ctx context.Context, sel ast.SelectionSet, v *model.PrimussExamWithCount) graphql.Marshaler { +func (ec *executionContext) marshalNRoomWithInvigilator2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomWithInvigilator(ctx context.Context, sel ast.SelectionSet, v *model.RoomWithInvigilator) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._PrimussExamWithCount(ctx, sel, v) + return ec._RoomWithInvigilator(ctx, sel, v) } -func (ec *executionContext) marshalNRegWithError2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRegWithErrorᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.RegWithError) graphql.Marshaler { +func (ec *executionContext) marshalNSemester2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSemester(ctx context.Context, sel ast.SelectionSet, v model.Semester) graphql.Marshaler { + return ec._Semester(ctx, sel, &v) +} + +func (ec *executionContext) marshalNSemester2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSemesterᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Semester) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35338,7 +36757,7 @@ func (ec *executionContext) marshalNRegWithError2ᚕᚖgithubᚗcomᚋobcodeᚋp if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNRegWithError2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRegWithError(ctx, sel, v[i]) + ret[i] = ec.marshalNSemester2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSemester(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35358,17 +36777,31 @@ func (ec *executionContext) marshalNRegWithError2ᚕᚖgithubᚗcomᚋobcodeᚋp return ret } -func (ec *executionContext) marshalNRegWithError2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRegWithError(ctx context.Context, sel ast.SelectionSet, v *model.RegWithError) graphql.Marshaler { +func (ec *executionContext) marshalNSemester2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSemester(ctx context.Context, sel ast.SelectionSet, v *model.Semester) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._RegWithError(ctx, sel, v) + return ec._Semester(ctx, sel, v) } -func (ec *executionContext) marshalNRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Room) graphql.Marshaler { +func (ec *executionContext) marshalNSemesterConfig2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSemesterConfig(ctx context.Context, sel ast.SelectionSet, v model.SemesterConfig) graphql.Marshaler { + return ec._SemesterConfig(ctx, sel, &v) +} + +func (ec *executionContext) marshalNSemesterConfig2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSemesterConfig(ctx context.Context, sel ast.SelectionSet, v *model.SemesterConfig) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._SemesterConfig(ctx, sel, v) +} + +func (ec *executionContext) marshalNSlot2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSlotᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Slot) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35392,7 +36825,7 @@ func (ec *executionContext) marshalNRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexams if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoom(ctx, sel, v[i]) + ret[i] = ec.marshalNSlot2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSlot(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35412,17 +36845,17 @@ func (ec *executionContext) marshalNRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexams return ret } -func (ec *executionContext) marshalNRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoom(ctx context.Context, sel ast.SelectionSet, v *model.Room) graphql.Marshaler { +func (ec *executionContext) marshalNSlot2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSlot(ctx context.Context, sel ast.SelectionSet, v *model.Slot) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._Room(ctx, sel, v) + return ec._Slot(ctx, sel, v) } -func (ec *executionContext) marshalNRoomAndExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomAndExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.RoomAndExam) graphql.Marshaler { +func (ec *executionContext) marshalNStarttime2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStarttimeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Starttime) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35446,7 +36879,7 @@ func (ec *executionContext) marshalNRoomAndExam2ᚕᚖgithubᚗcomᚋobcodeᚋpl if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNRoomAndExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomAndExam(ctx, sel, v[i]) + ret[i] = ec.marshalNStarttime2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStarttime(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35466,32 +36899,17 @@ func (ec *executionContext) marshalNRoomAndExam2ᚕᚖgithubᚗcomᚋobcodeᚋpl return ret } -func (ec *executionContext) marshalNRoomAndExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomAndExam(ctx context.Context, sel ast.SelectionSet, v *model.RoomAndExam) graphql.Marshaler { - if v == nil { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - return graphql.Null - } - return ec._RoomAndExam(ctx, sel, v) -} - -func (ec *executionContext) marshalNRoomForExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomForExam(ctx context.Context, sel ast.SelectionSet, v *model.RoomForExam) graphql.Marshaler { +func (ec *executionContext) marshalNStarttime2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStarttime(ctx context.Context, sel ast.SelectionSet, v *model.Starttime) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._RoomForExam(ctx, sel, v) -} - -func (ec *executionContext) unmarshalNRoomForExamInput2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomForExamInput(ctx context.Context, v interface{}) (model.RoomForExamInput, error) { - res, err := ec.unmarshalInputRoomForExamInput(ctx, v) - return res, graphql.ErrorOnPath(ctx, err) + return ec._Starttime(ctx, sel, v) } -func (ec *executionContext) marshalNRoomWithInvigilator2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomWithInvigilatorᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.RoomWithInvigilator) graphql.Marshaler { +func (ec *executionContext) marshalNStep2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStepᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Step) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35515,7 +36933,7 @@ func (ec *executionContext) marshalNRoomWithInvigilator2ᚕᚖgithubᚗcomᚋobc if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNRoomWithInvigilator2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomWithInvigilator(ctx, sel, v[i]) + ret[i] = ec.marshalNStep2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStep(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35535,21 +36953,64 @@ func (ec *executionContext) marshalNRoomWithInvigilator2ᚕᚖgithubᚗcomᚋobc return ret } -func (ec *executionContext) marshalNRoomWithInvigilator2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomWithInvigilator(ctx context.Context, sel ast.SelectionSet, v *model.RoomWithInvigilator) graphql.Marshaler { +func (ec *executionContext) marshalNStep2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStep(ctx context.Context, sel ast.SelectionSet, v *model.Step) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._RoomWithInvigilator(ctx, sel, v) + return ec._Step(ctx, sel, v) } -func (ec *executionContext) marshalNSemester2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSemester(ctx context.Context, sel ast.SelectionSet, v model.Semester) graphql.Marshaler { - return ec._Semester(ctx, sel, &v) +func (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalNSemester2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSemesterᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Semester) graphql.Marshaler { +func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalString(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalNString2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) { + var vSlice []interface{} + if v != nil { + vSlice = graphql.CoerceList(v) + } + var err error + res := make([]string, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNString2string(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalNString2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + for i := range v { + ret[i] = ec.marshalNString2string(ctx, sel, v[i]) + } + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNStudent2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Student) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35573,7 +37034,7 @@ func (ec *executionContext) marshalNSemester2ᚕᚖgithubᚗcomᚋobcodeᚋplexa if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNSemester2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSemester(ctx, sel, v[i]) + ret[i] = ec.marshalNStudent2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudent(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35593,31 +37054,17 @@ func (ec *executionContext) marshalNSemester2ᚕᚖgithubᚗcomᚋobcodeᚋplexa return ret } -func (ec *executionContext) marshalNSemester2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSemester(ctx context.Context, sel ast.SelectionSet, v *model.Semester) graphql.Marshaler { - if v == nil { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - return graphql.Null - } - return ec._Semester(ctx, sel, v) -} - -func (ec *executionContext) marshalNSemesterConfig2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSemesterConfig(ctx context.Context, sel ast.SelectionSet, v model.SemesterConfig) graphql.Marshaler { - return ec._SemesterConfig(ctx, sel, &v) -} - -func (ec *executionContext) marshalNSemesterConfig2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSemesterConfig(ctx context.Context, sel ast.SelectionSet, v *model.SemesterConfig) graphql.Marshaler { +func (ec *executionContext) marshalNStudent2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudent(ctx context.Context, sel ast.SelectionSet, v *model.Student) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._SemesterConfig(ctx, sel, v) + return ec._Student(ctx, sel, v) } -func (ec *executionContext) marshalNSlot2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSlotᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Slot) graphql.Marshaler { +func (ec *executionContext) marshalNStudentReg2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentRegᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.StudentReg) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35641,7 +37088,7 @@ func (ec *executionContext) marshalNSlot2ᚕᚖgithubᚗcomᚋobcodeᚋplexams if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNSlot2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSlot(ctx, sel, v[i]) + ret[i] = ec.marshalNStudentReg2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentReg(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35661,17 +37108,17 @@ func (ec *executionContext) marshalNSlot2ᚕᚖgithubᚗcomᚋobcodeᚋplexams return ret } -func (ec *executionContext) marshalNSlot2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐSlot(ctx context.Context, sel ast.SelectionSet, v *model.Slot) graphql.Marshaler { +func (ec *executionContext) marshalNStudentReg2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentReg(ctx context.Context, sel ast.SelectionSet, v *model.StudentReg) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._Slot(ctx, sel, v) + return ec._StudentReg(ctx, sel, v) } -func (ec *executionContext) marshalNStarttime2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStarttimeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Starttime) graphql.Marshaler { +func (ec *executionContext) marshalNStudentRegsPerAncodeAndProgram2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentRegsPerAncodeAndProgramᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.StudentRegsPerAncodeAndProgram) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35695,7 +37142,7 @@ func (ec *executionContext) marshalNStarttime2ᚕᚖgithubᚗcomᚋobcodeᚋplex if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNStarttime2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStarttime(ctx, sel, v[i]) + ret[i] = ec.marshalNStudentRegsPerAncodeAndProgram2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentRegsPerAncodeAndProgram(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35715,17 +37162,17 @@ func (ec *executionContext) marshalNStarttime2ᚕᚖgithubᚗcomᚋobcodeᚋplex return ret } -func (ec *executionContext) marshalNStarttime2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStarttime(ctx context.Context, sel ast.SelectionSet, v *model.Starttime) graphql.Marshaler { +func (ec *executionContext) marshalNStudentRegsPerAncodeAndProgram2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentRegsPerAncodeAndProgram(ctx context.Context, sel ast.SelectionSet, v *model.StudentRegsPerAncodeAndProgram) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._Starttime(ctx, sel, v) + return ec._StudentRegsPerAncodeAndProgram(ctx, sel, v) } -func (ec *executionContext) marshalNStep2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStepᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Step) graphql.Marshaler { +func (ec *executionContext) marshalNTeacher2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐTeacherᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Teacher) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35749,7 +37196,7 @@ func (ec *executionContext) marshalNStep2ᚕᚖgithubᚗcomᚋobcodeᚋplexams if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNStep2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStep(ctx, sel, v[i]) + ret[i] = ec.marshalNTeacher2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐTeacher(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35769,23 +37216,23 @@ func (ec *executionContext) marshalNStep2ᚕᚖgithubᚗcomᚋobcodeᚋplexams return ret } -func (ec *executionContext) marshalNStep2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStep(ctx context.Context, sel ast.SelectionSet, v *model.Step) graphql.Marshaler { +func (ec *executionContext) marshalNTeacher2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐTeacher(ctx context.Context, sel ast.SelectionSet, v *model.Teacher) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._Step(ctx, sel, v) + return ec._Teacher(ctx, sel, v) } -func (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) { - res, err := graphql.UnmarshalString(v) +func (ec *executionContext) unmarshalNTime2timeᚐTime(ctx context.Context, v interface{}) (time.Time, error) { + res, err := graphql.UnmarshalTime(v) return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { - res := graphql.MarshalString(v) +func (ec *executionContext) marshalNTime2timeᚐTime(ctx context.Context, sel ast.SelectionSet, v time.Time) graphql.Marshaler { + res := graphql.MarshalTime(v) if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") @@ -35794,16 +37241,16 @@ func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.S return res } -func (ec *executionContext) unmarshalNString2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) { +func (ec *executionContext) unmarshalNTime2ᚕᚖtimeᚐTimeᚄ(ctx context.Context, v interface{}) ([]*time.Time, error) { var vSlice []interface{} if v != nil { vSlice = graphql.CoerceList(v) } var err error - res := make([]string, len(vSlice)) + res := make([]*time.Time, len(vSlice)) for i := range vSlice { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNString2string(ctx, vSlice[i]) + res[i], err = ec.unmarshalNTime2ᚖtimeᚐTime(ctx, vSlice[i]) if err != nil { return nil, err } @@ -35811,10 +37258,10 @@ func (ec *executionContext) unmarshalNString2ᚕstringᚄ(ctx context.Context, v return res, nil } -func (ec *executionContext) marshalNString2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { +func (ec *executionContext) marshalNTime2ᚕᚖtimeᚐTimeᚄ(ctx context.Context, sel ast.SelectionSet, v []*time.Time) graphql.Marshaler { ret := make(graphql.Array, len(v)) for i := range v { - ret[i] = ec.marshalNString2string(ctx, sel, v[i]) + ret[i] = ec.marshalNTime2ᚖtimeᚐTime(ctx, sel, v[i]) } for _, e := range ret { @@ -35826,7 +37273,82 @@ func (ec *executionContext) marshalNString2ᚕstringᚄ(ctx context.Context, sel return ret } -func (ec *executionContext) marshalNStudent2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Student) graphql.Marshaler { +func (ec *executionContext) unmarshalNTime2ᚖtimeᚐTime(ctx context.Context, v interface{}) (*time.Time, error) { + res, err := graphql.UnmarshalTime(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNTime2ᚖtimeᚐTime(ctx context.Context, sel ast.SelectionSet, v *time.Time) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + res := graphql.MarshalTime(*v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) marshalNZPAConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAConflictᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ZPAConflict) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNZPAConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAConflict(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNZPAConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAConflict(ctx context.Context, sel ast.SelectionSet, v *model.ZPAConflict) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._ZPAConflict(ctx, sel, v) +} + +func (ec *executionContext) marshalNZPAExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ZPAExam) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35850,7 +37372,7 @@ func (ec *executionContext) marshalNStudent2ᚕᚖgithubᚗcomᚋobcodeᚋplexam if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNStudent2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudent(ctx, sel, v[i]) + ret[i] = ec.marshalNZPAExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExam(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35870,17 +37392,17 @@ func (ec *executionContext) marshalNStudent2ᚕᚖgithubᚗcomᚋobcodeᚋplexam return ret } -func (ec *executionContext) marshalNStudent2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudent(ctx context.Context, sel ast.SelectionSet, v *model.Student) graphql.Marshaler { +func (ec *executionContext) marshalNZPAExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExam(ctx context.Context, sel ast.SelectionSet, v *model.ZPAExam) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._Student(ctx, sel, v) + return ec._ZPAExam(ctx, sel, v) } -func (ec *executionContext) marshalNStudentReg2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentRegᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.StudentReg) graphql.Marshaler { +func (ec *executionContext) marshalNZPAExamWithConstraints2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamWithConstraintsᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ZPAExamWithConstraints) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35904,7 +37426,7 @@ func (ec *executionContext) marshalNStudentReg2ᚕᚖgithubᚗcomᚋobcodeᚋple if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNStudentReg2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentReg(ctx, sel, v[i]) + ret[i] = ec.marshalNZPAExamWithConstraints2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamWithConstraints(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35924,17 +37446,17 @@ func (ec *executionContext) marshalNStudentReg2ᚕᚖgithubᚗcomᚋobcodeᚋple return ret } -func (ec *executionContext) marshalNStudentReg2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentReg(ctx context.Context, sel ast.SelectionSet, v *model.StudentReg) graphql.Marshaler { +func (ec *executionContext) marshalNZPAExamWithConstraints2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamWithConstraints(ctx context.Context, sel ast.SelectionSet, v *model.ZPAExamWithConstraints) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._StudentReg(ctx, sel, v) + return ec._ZPAExamWithConstraints(ctx, sel, v) } -func (ec *executionContext) marshalNStudentRegsPerAncodeAndProgram2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentRegsPerAncodeAndProgramᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.StudentRegsPerAncodeAndProgram) graphql.Marshaler { +func (ec *executionContext) marshalNZPAExamsForType2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamsForTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ZPAExamsForType) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -35958,7 +37480,7 @@ func (ec *executionContext) marshalNStudentRegsPerAncodeAndProgram2ᚕᚖgithub if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNStudentRegsPerAncodeAndProgram2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentRegsPerAncodeAndProgram(ctx, sel, v[i]) + ret[i] = ec.marshalNZPAExamsForType2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamsForType(ctx, sel, v[i]) } if isLen1 { f(i) @@ -35978,17 +37500,17 @@ func (ec *executionContext) marshalNStudentRegsPerAncodeAndProgram2ᚕᚖgithub return ret } -func (ec *executionContext) marshalNStudentRegsPerAncodeAndProgram2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐStudentRegsPerAncodeAndProgram(ctx context.Context, sel ast.SelectionSet, v *model.StudentRegsPerAncodeAndProgram) graphql.Marshaler { +func (ec *executionContext) marshalNZPAExamsForType2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamsForType(ctx context.Context, sel ast.SelectionSet, v *model.ZPAExamsForType) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._StudentRegsPerAncodeAndProgram(ctx, sel, v) + return ec._ZPAExamsForType(ctx, sel, v) } -func (ec *executionContext) marshalNTeacher2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐTeacherᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Teacher) graphql.Marshaler { +func (ec *executionContext) marshalNZPAInvigilator2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAInvigilatorᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ZPAInvigilator) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -36012,7 +37534,7 @@ func (ec *executionContext) marshalNTeacher2ᚕᚖgithubᚗcomᚋobcodeᚋplexam if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNTeacher2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐTeacher(ctx, sel, v[i]) + ret[i] = ec.marshalNZPAInvigilator2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAInvigilator(ctx, sel, v[i]) } if isLen1 { f(i) @@ -36032,85 +37554,21 @@ func (ec *executionContext) marshalNTeacher2ᚕᚖgithubᚗcomᚋobcodeᚋplexam return ret } -func (ec *executionContext) marshalNTeacher2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐTeacher(ctx context.Context, sel ast.SelectionSet, v *model.Teacher) graphql.Marshaler { +func (ec *executionContext) marshalNZPAInvigilator2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAInvigilator(ctx context.Context, sel ast.SelectionSet, v *model.ZPAInvigilator) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._Teacher(ctx, sel, v) -} - -func (ec *executionContext) unmarshalNTime2timeᚐTime(ctx context.Context, v interface{}) (time.Time, error) { - res, err := graphql.UnmarshalTime(v) - return res, graphql.ErrorOnPath(ctx, err) -} - -func (ec *executionContext) marshalNTime2timeᚐTime(ctx context.Context, sel ast.SelectionSet, v time.Time) graphql.Marshaler { - res := graphql.MarshalTime(v) - if res == graphql.Null { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - } - return res -} - -func (ec *executionContext) unmarshalNTime2ᚕᚖtimeᚐTimeᚄ(ctx context.Context, v interface{}) ([]*time.Time, error) { - var vSlice []interface{} - if v != nil { - vSlice = graphql.CoerceList(v) - } - var err error - res := make([]*time.Time, len(vSlice)) - for i := range vSlice { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNTime2ᚖtimeᚐTime(ctx, vSlice[i]) - if err != nil { - return nil, err - } - } - return res, nil -} - -func (ec *executionContext) marshalNTime2ᚕᚖtimeᚐTimeᚄ(ctx context.Context, sel ast.SelectionSet, v []*time.Time) graphql.Marshaler { - ret := make(graphql.Array, len(v)) - for i := range v { - ret[i] = ec.marshalNTime2ᚖtimeᚐTime(ctx, sel, v[i]) - } - - for _, e := range ret { - if e == graphql.Null { - return graphql.Null - } - } - - return ret -} - -func (ec *executionContext) unmarshalNTime2ᚖtimeᚐTime(ctx context.Context, v interface{}) (*time.Time, error) { - res, err := graphql.UnmarshalTime(v) - return &res, graphql.ErrorOnPath(ctx, err) + return ec._ZPAInvigilator(ctx, sel, v) } -func (ec *executionContext) marshalNTime2ᚖtimeᚐTime(ctx context.Context, sel ast.SelectionSet, v *time.Time) graphql.Marshaler { - if v == nil { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - return graphql.Null - } - res := graphql.MarshalTime(*v) - if res == graphql.Null { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - } - return res +func (ec *executionContext) marshalNZPAPrimussAncodes2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAPrimussAncodes(ctx context.Context, sel ast.SelectionSet, v model.ZPAPrimussAncodes) graphql.Marshaler { + return ec._ZPAPrimussAncodes(ctx, sel, &v) } -func (ec *executionContext) marshalNZPAConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAConflictᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ZPAConflict) graphql.Marshaler { +func (ec *executionContext) marshalNZPAPrimussAncodes2ᚕgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAPrimussAncodesᚄ(ctx context.Context, sel ast.SelectionSet, v []model.ZPAPrimussAncodes) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -36134,7 +37592,7 @@ func (ec *executionContext) marshalNZPAConflict2ᚕᚖgithubᚗcomᚋobcodeᚋpl if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNZPAConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAConflict(ctx, sel, v[i]) + ret[i] = ec.marshalNZPAPrimussAncodes2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAPrimussAncodes(ctx, sel, v[i]) } if isLen1 { f(i) @@ -36154,71 +37612,31 @@ func (ec *executionContext) marshalNZPAConflict2ᚕᚖgithubᚗcomᚋobcodeᚋpl return ret } -func (ec *executionContext) marshalNZPAConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAConflict(ctx context.Context, sel ast.SelectionSet, v *model.ZPAConflict) graphql.Marshaler { +func (ec *executionContext) marshalNZPAStudentReg2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAStudentReg(ctx context.Context, sel ast.SelectionSet, v *model.ZPAStudentReg) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._ZPAConflict(ctx, sel, v) -} - -func (ec *executionContext) marshalNZPAExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ZPAExam) graphql.Marshaler { - ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } - for i := range v { - i := i - fc := &graphql.FieldContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithFieldContext(ctx, fc) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalNZPAExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExam(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - - } - wg.Wait() - - for _, e := range ret { - if e == graphql.Null { - return graphql.Null - } - } - - return ret + return ec._ZPAStudentReg(ctx, sel, v) } -func (ec *executionContext) marshalNZPAExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExam(ctx context.Context, sel ast.SelectionSet, v *model.ZPAExam) graphql.Marshaler { +func (ec *executionContext) marshalNZPAStudentRegError2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAStudentRegError(ctx context.Context, sel ast.SelectionSet, v *model.ZPAStudentRegError) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._ZPAExam(ctx, sel, v) + return ec._ZPAStudentRegError(ctx, sel, v) } -func (ec *executionContext) marshalNZPAExamWithConstraints2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamWithConstraintsᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ZPAExamWithConstraints) graphql.Marshaler { +func (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler { + return ec.___Directive(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Directive) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -36242,7 +37660,7 @@ func (ec *executionContext) marshalNZPAExamWithConstraints2ᚕᚖgithubᚗcomᚋ if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNZPAExamWithConstraints2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamWithConstraints(ctx, sel, v[i]) + ret[i] = ec.marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx, sel, v[i]) } if isLen1 { f(i) @@ -36262,17 +37680,39 @@ func (ec *executionContext) marshalNZPAExamWithConstraints2ᚕᚖgithubᚗcomᚋ return ret } -func (ec *executionContext) marshalNZPAExamWithConstraints2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamWithConstraints(ctx context.Context, sel ast.SelectionSet, v *model.ZPAExamWithConstraints) graphql.Marshaler { - if v == nil { +func (ec *executionContext) unmarshalN__DirectiveLocation2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalN__DirectiveLocation2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalString(v) + if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } - return graphql.Null } - return ec._ZPAExamWithConstraints(ctx, sel, v) + return res } -func (ec *executionContext) marshalNZPAExamsForType2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamsForTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ZPAExamsForType) graphql.Marshaler { +func (ec *executionContext) unmarshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) { + var vSlice []interface{} + if v != nil { + vSlice = graphql.CoerceList(v) + } + var err error + res := make([]string, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalN__DirectiveLocation2string(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -36296,7 +37736,7 @@ func (ec *executionContext) marshalNZPAExamsForType2ᚕᚖgithubᚗcomᚋobcode if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNZPAExamsForType2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamsForType(ctx, sel, v[i]) + ret[i] = ec.marshalN__DirectiveLocation2string(ctx, sel, v[i]) } if isLen1 { f(i) @@ -36316,17 +37756,19 @@ func (ec *executionContext) marshalNZPAExamsForType2ᚕᚖgithubᚗcomᚋobcode return ret } -func (ec *executionContext) marshalNZPAExamsForType2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAExamsForType(ctx context.Context, sel ast.SelectionSet, v *model.ZPAExamsForType) graphql.Marshaler { - if v == nil { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - return graphql.Null - } - return ec._ZPAExamsForType(ctx, sel, v) +func (ec *executionContext) marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx context.Context, sel ast.SelectionSet, v introspection.EnumValue) graphql.Marshaler { + return ec.___EnumValue(ctx, sel, &v) } -func (ec *executionContext) marshalNZPAInvigilator2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAInvigilatorᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.ZPAInvigilator) graphql.Marshaler { +func (ec *executionContext) marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx context.Context, sel ast.SelectionSet, v introspection.Field) graphql.Marshaler { + return ec.___Field(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx context.Context, sel ast.SelectionSet, v introspection.InputValue) graphql.Marshaler { + return ec.___InputValue(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -36350,7 +37792,7 @@ func (ec *executionContext) marshalNZPAInvigilator2ᚕᚖgithubᚗcomᚋobcode if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNZPAInvigilator2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAInvigilator(ctx, sel, v[i]) + ret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i]) } if isLen1 { f(i) @@ -36370,21 +37812,11 @@ func (ec *executionContext) marshalNZPAInvigilator2ᚕᚖgithubᚗcomᚋobcode return ret } -func (ec *executionContext) marshalNZPAInvigilator2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAInvigilator(ctx context.Context, sel ast.SelectionSet, v *model.ZPAInvigilator) graphql.Marshaler { - if v == nil { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - return graphql.Null - } - return ec._ZPAInvigilator(ctx, sel, v) -} - -func (ec *executionContext) marshalNZPAPrimussAncodes2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAPrimussAncodes(ctx context.Context, sel ast.SelectionSet, v model.ZPAPrimussAncodes) graphql.Marshaler { - return ec._ZPAPrimussAncodes(ctx, sel, &v) +func (ec *executionContext) marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler { + return ec.___Type(ctx, sel, &v) } -func (ec *executionContext) marshalNZPAPrimussAncodes2ᚕgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAPrimussAncodesᚄ(ctx context.Context, sel ast.SelectionSet, v []model.ZPAPrimussAncodes) graphql.Marshaler { +func (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -36408,7 +37840,7 @@ func (ec *executionContext) marshalNZPAPrimussAncodes2ᚕgithubᚗcomᚋobcode if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNZPAPrimussAncodes2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAPrimussAncodes(ctx, sel, v[i]) + ret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i]) } if isLen1 { f(i) @@ -36428,31 +37860,35 @@ func (ec *executionContext) marshalNZPAPrimussAncodes2ᚕgithubᚗcomᚋobcode return ret } -func (ec *executionContext) marshalNZPAStudentReg2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAStudentReg(ctx context.Context, sel ast.SelectionSet, v *model.ZPAStudentReg) graphql.Marshaler { +func (ec *executionContext) marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } return graphql.Null } - return ec._ZPAStudentReg(ctx, sel, v) + return ec.___Type(ctx, sel, v) } -func (ec *executionContext) marshalNZPAStudentRegError2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐZPAStudentRegError(ctx context.Context, sel ast.SelectionSet, v *model.ZPAStudentRegError) graphql.Marshaler { - if v == nil { +func (ec *executionContext) unmarshalN__TypeKind2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalString(v) + if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") } - return graphql.Null } - return ec._ZPAStudentRegError(ctx, sel, v) -} - -func (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler { - return ec.___Directive(ctx, sel, &v) + return res } -func (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Directive) graphql.Marshaler { +func (ec *executionContext) marshalOAnCode2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAnCode(ctx context.Context, sel ast.SelectionSet, v []*model.AnCode) graphql.Marshaler { + if v == nil { + return graphql.Null + } ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -36476,7 +37912,7 @@ func (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgq if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx, sel, v[i]) + ret[i] = ec.marshalOAnCode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAnCode(ctx, sel, v[i]) } if isLen1 { f(i) @@ -36487,152 +37923,46 @@ func (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgq } wg.Wait() - for _, e := range ret { - if e == graphql.Null { - return graphql.Null - } - } - return ret } -func (ec *executionContext) unmarshalN__DirectiveLocation2string(ctx context.Context, v interface{}) (string, error) { - res, err := graphql.UnmarshalString(v) +func (ec *executionContext) marshalOAnCode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAnCode(ctx context.Context, sel ast.SelectionSet, v *model.AnCode) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._AnCode(ctx, sel, v) +} + +func (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) { + res, err := graphql.UnmarshalBoolean(v) return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalN__DirectiveLocation2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { - res := graphql.MarshalString(v) - if res == graphql.Null { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - } +func (ec *executionContext) marshalOBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { + res := graphql.MarshalBoolean(v) return res } -func (ec *executionContext) unmarshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) { - var vSlice []interface{} - if v != nil { - vSlice = graphql.CoerceList(v) - } - var err error - res := make([]string, len(vSlice)) - for i := range vSlice { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalN__DirectiveLocation2string(ctx, vSlice[i]) - if err != nil { - return nil, err - } +func (ec *executionContext) unmarshalOBoolean2ᚖbool(ctx context.Context, v interface{}) (*bool, error) { + if v == nil { + return nil, nil } - return res, nil + res, err := graphql.UnmarshalBoolean(v) + return &res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { - ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } - for i := range v { - i := i - fc := &graphql.FieldContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithFieldContext(ctx, fc) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalN__DirectiveLocation2string(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - - } - wg.Wait() - - for _, e := range ret { - if e == graphql.Null { - return graphql.Null - } +func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast.SelectionSet, v *bool) graphql.Marshaler { + if v == nil { + return graphql.Null } - - return ret -} - -func (ec *executionContext) marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx context.Context, sel ast.SelectionSet, v introspection.EnumValue) graphql.Marshaler { - return ec.___EnumValue(ctx, sel, &v) -} - -func (ec *executionContext) marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx context.Context, sel ast.SelectionSet, v introspection.Field) graphql.Marshaler { - return ec.___Field(ctx, sel, &v) -} - -func (ec *executionContext) marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx context.Context, sel ast.SelectionSet, v introspection.InputValue) graphql.Marshaler { - return ec.___InputValue(ctx, sel, &v) + res := graphql.MarshalBoolean(*v) + return res } -func (ec *executionContext) marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { - ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } - for i := range v { - i := i - fc := &graphql.FieldContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithFieldContext(ctx, fc) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - - } - wg.Wait() - - for _, e := range ret { - if e == graphql.Null { - return graphql.Null - } +func (ec *executionContext) marshalOConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Conflict) graphql.Marshaler { + if v == nil { + return graphql.Null } - - return ret -} - -func (ec *executionContext) marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler { - return ec.___Type(ctx, sel, &v) -} - -func (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -36656,7 +37986,7 @@ func (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgen if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i]) + ret[i] = ec.marshalNConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflict(ctx, sel, v[i]) } if isLen1 { f(i) @@ -36676,106 +38006,28 @@ func (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgen return ret } -func (ec *executionContext) marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler { - if v == nil { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - return graphql.Null - } - return ec.___Type(ctx, sel, v) -} - -func (ec *executionContext) unmarshalN__TypeKind2string(ctx context.Context, v interface{}) (string, error) { - res, err := graphql.UnmarshalString(v) - return res, graphql.ErrorOnPath(ctx, err) -} - -func (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { - res := graphql.MarshalString(v) - if res == graphql.Null { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - } - return res -} - -func (ec *executionContext) marshalOAnCode2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAnCode(ctx context.Context, sel ast.SelectionSet, v []*model.AnCode) graphql.Marshaler { +func (ec *executionContext) marshalOConflicts2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflicts(ctx context.Context, sel ast.SelectionSet, v *model.Conflicts) graphql.Marshaler { if v == nil { return graphql.Null } - ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } - for i := range v { - i := i - fc := &graphql.FieldContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithFieldContext(ctx, fc) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalOAnCode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAnCode(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - - } - wg.Wait() - - return ret + return ec._Conflicts(ctx, sel, v) } -func (ec *executionContext) marshalOAnCode2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐAnCode(ctx context.Context, sel ast.SelectionSet, v *model.AnCode) graphql.Marshaler { +func (ec *executionContext) marshalOConnectedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExam(ctx context.Context, sel ast.SelectionSet, v *model.ConnectedExam) graphql.Marshaler { if v == nil { return graphql.Null } - return ec._AnCode(ctx, sel, v) -} - -func (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) { - res, err := graphql.UnmarshalBoolean(v) - return res, graphql.ErrorOnPath(ctx, err) -} - -func (ec *executionContext) marshalOBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { - res := graphql.MarshalBoolean(v) - return res -} - -func (ec *executionContext) unmarshalOBoolean2ᚖbool(ctx context.Context, v interface{}) (*bool, error) { - if v == nil { - return nil, nil - } - res, err := graphql.UnmarshalBoolean(v) - return &res, graphql.ErrorOnPath(ctx, err) + return ec._ConnectedExam(ctx, sel, v) } -func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast.SelectionSet, v *bool) graphql.Marshaler { +func (ec *executionContext) marshalOConstraints2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConstraints(ctx context.Context, sel ast.SelectionSet, v *model.Constraints) graphql.Marshaler { if v == nil { return graphql.Null } - res := graphql.MarshalBoolean(*v) - return res + return ec._Constraints(ctx, sel, v) } -func (ec *executionContext) marshalOConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflictᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Conflict) graphql.Marshaler { +func (ec *executionContext) marshalOEnhancedPlannedRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPlannedRoomᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.EnhancedPlannedRoom) graphql.Marshaler { if v == nil { return graphql.Null } @@ -36802,7 +38054,7 @@ func (ec *executionContext) marshalOConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexa if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNConflict2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflict(ctx, sel, v[i]) + ret[i] = ec.marshalNEnhancedPlannedRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPlannedRoom(ctx, sel, v[i]) } if isLen1 { f(i) @@ -36822,27 +38074,6 @@ func (ec *executionContext) marshalOConflict2ᚕᚖgithubᚗcomᚋobcodeᚋplexa return ret } -func (ec *executionContext) marshalOConflicts2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConflicts(ctx context.Context, sel ast.SelectionSet, v *model.Conflicts) graphql.Marshaler { - if v == nil { - return graphql.Null - } - return ec._Conflicts(ctx, sel, v) -} - -func (ec *executionContext) marshalOConnectedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConnectedExam(ctx context.Context, sel ast.SelectionSet, v *model.ConnectedExam) graphql.Marshaler { - if v == nil { - return graphql.Null - } - return ec._ConnectedExam(ctx, sel, v) -} - -func (ec *executionContext) marshalOConstraints2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐConstraints(ctx context.Context, sel ast.SelectionSet, v *model.Constraints) graphql.Marshaler { - if v == nil { - return graphql.Null - } - return ec._Constraints(ctx, sel, v) -} - func (ec *executionContext) marshalOExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExam(ctx context.Context, sel ast.SelectionSet, v *model.Exam) graphql.Marshaler { if v == nil { return graphql.Null @@ -37693,6 +38924,53 @@ func (ec *executionContext) marshalOPlannedExamWithNTA2ᚕᚖgithubᚗcomᚋobco return ret } +func (ec *executionContext) marshalOPlannedRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedRoomᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PlannedRoom) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNPlannedRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedRoom(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + func (ec *executionContext) marshalOPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPrimussExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.PrimussExam) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index 7b0570a..e1b8531 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -278,6 +278,7 @@ type PlannedExam struct { Ntas []*NTA `json:"ntas"` MaxDuration int `json:"maxDuration"` PlanEntry *PlanEntry `json:"planEntry,omitempty"` + PlannedRooms []*PlannedRoom `json:"plannedRooms,omitempty"` } type PlannedExamWithNta struct { diff --git a/graph/model/rooms.go b/graph/model/rooms.go index ddc19d1..d08a1b4 100644 --- a/graph/model/rooms.go +++ b/graph/model/rooms.go @@ -9,3 +9,16 @@ type RoomForExam struct { Reserve bool `json:"reserve"` Students []*StudentReg `json:"students"` } + +type EnhancedPlannedRoom struct { + Day int `json:"day"` + Slot int `json:"slot"` + RoomName string `json:"roomName"` + Ancode int `json:"ancode"` + Duration int `json:"duration"` + Handicap bool `json:"handicap"` + HandicapRoomAlone bool `json:"handicapRoomAlone"` + Reserve bool `json:"reserve"` + StudentsInRoom []string `json:"studentsInRoom"` + NtaMtknr *string `json:"ntaMtknr,omitempty"` +} diff --git a/graph/query.graphqls b/graph/query.graphqls index ceaf825..b7a7ad1 100644 --- a/graph/query.graphqls +++ b/graph/query.graphqls @@ -41,8 +41,7 @@ type Query { exahm: Boolean ): [Room!]! roomsForSlot(day: Int!, time: Int!): SlotWithRooms - plannedRoomNames: [String!] - plannedRoomNamesInSlot(day: Int!, time: Int!): [String!] + # Invigilators invigilatorsWithReq: [Invigilator!]! invigilatorTodos: InvigilationTodos diff --git a/graph/query.resolvers.go b/graph/query.resolvers.go index d797333..d3367f5 100644 --- a/graph/query.resolvers.go +++ b/graph/query.resolvers.go @@ -127,16 +127,6 @@ func (r *queryResolver) RoomsForSlot(ctx context.Context, day int, time int) (*m return r.plexams.RoomsForSlot(ctx, day, time) } -// PlannedRoomNames is the resolver for the plannedRoomNames field. -func (r *queryResolver) PlannedRoomNames(ctx context.Context) ([]string, error) { - return r.plexams.PlannedRoomNames(ctx) -} - -// PlannedRoomNamesInSlot is the resolver for the plannedRoomNamesInSlot field. -func (r *queryResolver) PlannedRoomNamesInSlot(ctx context.Context, day int, time int) ([]string, error) { - return r.plexams.PlannedRoomNamesInSlot(ctx, day, time) -} - // InvigilatorsWithReq is the resolver for the invigilatorsWithReq field. func (r *queryResolver) InvigilatorsWithReq(ctx context.Context) ([]*model.Invigilator, error) { return r.plexams.InvigilatorsWithReq(ctx) diff --git a/graph/room.graphqls b/graph/room.graphqls index e16d854..fa085de 100644 --- a/graph/room.graphqls +++ b/graph/room.graphqls @@ -1,5 +1,8 @@ extend type Query { rooms: [Room!]! + plannedRoomNames: [String!] + plannedRoomNamesInSlot(day: Int!, time: Int!): [String!] + plannedRoomsInSlot(day: Int!, time: Int!): [EnhancedPlannedRoom!] } type Room { @@ -35,6 +38,22 @@ type PlannedRoom { ntaMtknr: String } +type EnhancedPlannedRoom { + day: Int! + slot: Int! + roomName: String! + room: Room! + ancode: Int! + exam: GeneratedExam! + duration: Int! + handicap: Boolean! + handicapRoomAlone: Boolean! + reserve: Boolean! + studentsInRoom: [String!]! + ntaMtknr: String + ntaInRoom: NTA +} + # Deprecated: rm me type RoomForExam { ancode: Int! diff --git a/graph/room.resolvers.go b/graph/room.resolvers.go index 7243be2..084cb09 100644 --- a/graph/room.resolvers.go +++ b/graph/room.resolvers.go @@ -6,22 +6,68 @@ package graph import ( "context" + "fmt" "github.com/obcode/plexams.go/graph/generated" "github.com/obcode/plexams.go/graph/model" ) +// Room is the resolver for the room field. +func (r *enhancedPlannedRoomResolver) Room(ctx context.Context, obj *model.EnhancedPlannedRoom) (*model.Room, error) { + if obj == nil { + return nil, fmt.Errorf("error enhanced planned room not available") + } + return r.plexams.RoomFromName(ctx, obj.RoomName) +} + +// Exam is the resolver for the exam field. +func (r *enhancedPlannedRoomResolver) Exam(ctx context.Context, obj *model.EnhancedPlannedRoom) (*model.GeneratedExam, error) { + if obj == nil { + return nil, fmt.Errorf("error enhanced planned room not available") + } + return r.plexams.GeneratedExam(ctx, obj.Ancode) +} + +// NtaInRoom is the resolver for the ntaInRoom field. +func (r *enhancedPlannedRoomResolver) NtaInRoom(ctx context.Context, obj *model.EnhancedPlannedRoom) (*model.NTA, error) { + if obj == nil { + return nil, fmt.Errorf("error enhanced planned room not available") + } + return r.plexams.NtaByMtknr(ctx, *obj.NtaMtknr) +} + // Rooms is the resolver for the rooms field. func (r *queryResolver) Rooms(ctx context.Context) ([]*model.Room, error) { return r.plexams.Rooms(ctx) } +// PlannedRoomNames is the resolver for the plannedRoomNames field. +func (r *queryResolver) PlannedRoomNames(ctx context.Context) ([]string, error) { + return r.plexams.PlannedRoomNames(ctx) +} + +// PlannedRoomNamesInSlot is the resolver for the plannedRoomNamesInSlot field. +func (r *queryResolver) PlannedRoomNamesInSlot(ctx context.Context, day int, time int) ([]string, error) { + return r.plexams.PlannedRoomNamesInSlot(ctx, day, time) +} + +// PlannedRoomsInSlot is the resolver for the plannedRoomsInSlot field. +func (r *queryResolver) PlannedRoomsInSlot(ctx context.Context, day int, time int) ([]*model.EnhancedPlannedRoom, error) { + return r.plexams.PlannedRoomsInSlot(ctx, day, time) +} + // Room is the resolver for the room field. func (r *roomForExamResolver) Room(ctx context.Context, obj *model.RoomForExam) (*model.Room, error) { return r.plexams.Room(ctx, obj) } +// EnhancedPlannedRoom returns generated.EnhancedPlannedRoomResolver implementation. +func (r *Resolver) EnhancedPlannedRoom() generated.EnhancedPlannedRoomResolver { + return &enhancedPlannedRoomResolver{r} +} + // RoomForExam returns generated.RoomForExamResolver implementation. func (r *Resolver) RoomForExam() generated.RoomForExamResolver { return &roomForExamResolver{r} } +type enhancedPlannedRoomResolver struct{ *Resolver } type roomForExamResolver struct{ *Resolver } diff --git a/plexams/invigilators.go b/plexams/invigilators.go index 068e827..b9d2c4f 100644 --- a/plexams/invigilators.go +++ b/plexams/invigilators.go @@ -413,77 +413,79 @@ func (p *Plexams) GetSelfInvigilations(ctx context.Context) ([]*model.Invigilati return invigilations, nil } +// TODO: rewrite me func (p *Plexams) RoomsWithInvigilationsForSlot(ctx context.Context, day int, time int) (*model.InvigilationSlot, error) { - rooms, err := p.PlannedRoomsInSlot(ctx, day, time) - if err != nil { - log.Error().Err(err).Int("day", day).Int("time", time). - Msg("cannot get rooms for slot") - return nil, err - } - - reserve, err := p.dbClient.GetInvigilatorInSlot(ctx, "reserve", day, time) - if err != nil { - log.Error().Err(err).Int("day", day).Int("time", time). - Msg("cannot get reserve for slot") - return nil, err - } - - slot := &model.InvigilationSlot{ - Reserve: reserve, - RoomsWithInvigilators: []*model.RoomWithInvigilator{}, - } - - roomMap := make(map[string][]*model.RoomForExam) - - for _, room := range rooms { - roomsForExam, ok := roomMap[room.RoomName] - if !ok { - roomsForExam = make([]*model.RoomForExam, 0, 1) - } - roomMap[room.RoomName] = append(roomsForExam, room) - } - - keys := make([]string, 0, len(roomMap)) - for k := range roomMap { - keys = append(keys, k) - } - sort.Strings(keys) - - for _, name := range keys { - roomsForExam := roomMap[name] - invigilator, err := p.dbClient.GetInvigilatorForRoom(ctx, name, day, time) - if err != nil { - log.Error().Err(err).Int("day", day).Int("slot", time).Str("room", name). - Msg("cannot get invigilator for rooms in slot") - } - - roomAndExams := make([]*model.RoomAndExam, 0) - maxDuration := 0 - studentCount := 0 - for _, roomForExam := range roomsForExam { - exam, err := p.dbClient.GetZpaExamByAncode(ctx, roomForExam.Ancode) - if err != nil { - log.Error().Err(err).Int("ancode", roomForExam.Ancode). - Msg("cannot get zpa exam") - return nil, err - } - roomAndExams = append(roomAndExams, &model.RoomAndExam{ - Room: roomForExam, - Exam: exam, - }) - if roomForExam.Duration > maxDuration { - maxDuration = roomForExam.Duration - } - studentCount += roomForExam.SeatsPlanned - } - - slot.RoomsWithInvigilators = append(slot.RoomsWithInvigilators, &model.RoomWithInvigilator{ - Name: name, - MaxDuration: maxDuration, - StudentCount: studentCount, - RoomAndExams: roomAndExams, - Invigilator: invigilator, - }) - } - return slot, nil + // rooms, err := p.PlannedRoomsInSlot(ctx, day, time) + // if err != nil { + // log.Error().Err(err).Int("day", day).Int("time", time). + // Msg("cannot get rooms for slot") + // return nil, err + // } + + // reserve, err := p.dbClient.GetInvigilatorInSlot(ctx, "reserve", day, time) + // if err != nil { + // log.Error().Err(err).Int("day", day).Int("time", time). + // Msg("cannot get reserve for slot") + // return nil, err + // } + + // slot := &model.InvigilationSlot{ + // Reserve: reserve, + // RoomsWithInvigilators: []*model.RoomWithInvigilator{}, + // } + + // roomMap := make(map[string][]*model.RoomForExam) + + // for _, room := range rooms { + // roomsForExam, ok := roomMap[room.RoomName] + // if !ok { + // roomsForExam = make([]*model.RoomForExam, 0, 1) + // } + // roomMap[room.RoomName] = append(roomsForExam, room) + // } + + // keys := make([]string, 0, len(roomMap)) + // for k := range roomMap { + // keys = append(keys, k) + // } + // sort.Strings(keys) + + // for _, name := range keys { + // roomsForExam := roomMap[name] + // invigilator, err := p.dbClient.GetInvigilatorForRoom(ctx, name, day, time) + // if err != nil { + // log.Error().Err(err).Int("day", day).Int("slot", time).Str("room", name). + // Msg("cannot get invigilator for rooms in slot") + // } + + // roomAndExams := make([]*model.RoomAndExam, 0) + // maxDuration := 0 + // studentCount := 0 + // for _, roomForExam := range roomsForExam { + // exam, err := p.dbClient.GetZpaExamByAncode(ctx, roomForExam.Ancode) + // if err != nil { + // log.Error().Err(err).Int("ancode", roomForExam.Ancode). + // Msg("cannot get zpa exam") + // return nil, err + // } + // roomAndExams = append(roomAndExams, &model.RoomAndExam{ + // Room: roomForExam, + // Exam: exam, + // }) + // if roomForExam.Duration > maxDuration { + // maxDuration = roomForExam.Duration + // } + // studentCount += roomForExam.SeatsPlanned + // } + + // slot.RoomsWithInvigilators = append(slot.RoomsWithInvigilators, &model.RoomWithInvigilator{ + // Name: name, + // MaxDuration: maxDuration, + // StudentCount: studentCount, + // RoomAndExams: roomAndExams, + // Invigilator: invigilator, + // }) + // } + // return slot, nil + return nil, nil } diff --git a/plexams/nta.go b/plexams/nta.go index 81182ba..d016a2f 100644 --- a/plexams/nta.go +++ b/plexams/nta.go @@ -18,10 +18,15 @@ func (p *Plexams) NtasWithRegs(ctx context.Context) ([]*model.Student, error) { return p.dbClient.NtasWithRegs(ctx) } +// Deprecated: rm me func (p *Plexams) Nta(ctx context.Context, mtknr string) (*model.NTAWithRegs, error) { return p.dbClient.NtaWithRegs(ctx, mtknr) } +func (p *Plexams) NtaByMtknr(ctx context.Context, mtknr string) (*model.NTA, error) { + return p.dbClient.Nta(ctx, mtknr) +} + // Deprecated: rm me func (p *Plexams) PrepareNta() error { // ctx := context.Background() diff --git a/plexams/plannedExams.go b/plexams/plannedExams.go index 619af68..bc91cb9 100644 --- a/plexams/plannedExams.go +++ b/plexams/plannedExams.go @@ -25,6 +25,12 @@ func (p *Plexams) PlannedExam(ctx context.Context, ancode int) (*model.PlannedEx return nil, err } + plannedRooms, err := p.dbClient.PlannedRoomsForAncode(ctx, ancode) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("cannot get planned rooms for ancode") + return nil, err + } + return &model.PlannedExam{ Ancode: exam.Ancode, ZpaExam: exam.ZpaExam, @@ -35,6 +41,7 @@ func (p *Plexams) PlannedExam(ctx context.Context, ancode int) (*model.PlannedEx Ntas: exam.Ntas, MaxDuration: exam.MaxDuration, PlanEntry: planEntry, + PlannedRooms: plannedRooms, }, err } diff --git a/plexams/rooms.go b/plexams/rooms.go index fee2205..dfe58b6 100644 --- a/plexams/rooms.go +++ b/plexams/rooms.go @@ -960,34 +960,38 @@ func (p *Plexams) PlannedRoomNames(ctx context.Context) ([]string, error) { } // TODO: rewrite me -func (p *Plexams) PlannedRoomsInSlot(ctx context.Context, day int, time int) ([]*model.RoomForExam, error) { - // exams, err := p.ExamsInSlotWithRooms(ctx, day, time) - // if err != nil { - // log.Error().Err(err).Int("day", day).Int("time", time).Msg("cannot get exams in slot") - // } +func (p *Plexams) PlannedRoomsInSlot(ctx context.Context, day int, time int) ([]*model.EnhancedPlannedRoom, error) { + rooms, err := p.dbClient.PlannedRoomsInSlot(ctx, day, time) + if err != nil { + log.Error().Err(err).Int("day", day).Int("time", time).Msg("cannot get exams in slot") + } - // rooms := make([]*model.RoomForExam, 0) - // for _, exam := range exams { - // rooms = append(rooms, exam.Rooms...) - // } + return enhancePlannedRooms(rooms), nil +} - // return rooms, nil - return nil, nil +func enhancePlannedRooms(plannedRooms []*model.PlannedRoom) []*model.EnhancedPlannedRoom { + enhancedPlannedRooms := make([]*model.EnhancedPlannedRoom, 0, len(plannedRooms)) + for _, room := range plannedRooms { + enhancedPlannedRooms = append(enhancedPlannedRooms, &model.EnhancedPlannedRoom{ + Day: room.Day, + Slot: room.Ancode, + RoomName: room.RoomName, + Ancode: room.Ancode, + Duration: room.Duration, + Handicap: room.Handicap, + HandicapRoomAlone: room.HandicapRoomAlone, + Reserve: room.Reserve, + StudentsInRoom: room.StudentsInRoom, + NtaMtknr: room.NtaMtknr, + }) + } + return enhancedPlannedRooms } func (p *Plexams) PlannedRoomNamesInSlot(ctx context.Context, day int, time int) ([]string, error) { - exams, err := p.ExamsInSlotWithRooms(ctx, day, time) - if err != nil { - log.Error().Err(err).Int("day", day).Int("time", time).Msg("cannot get exams in slot") - } + return p.dbClient.PlannedRoomNamesInSlot(ctx, day, time) +} - roomNamesSet := set.NewSet[string]() - for _, exam := range exams { - for _, room := range exam.Rooms { - roomNamesSet.Add(room.RoomName) - } - } - roomNames := roomNamesSet.ToSlice() - sort.Strings(roomNames) - return roomNames, nil +func (p *Plexams) RoomFromName(ctx context.Context, roomName string) (*model.Room, error) { + return p.dbClient.RoomFromName(ctx, roomName) } From 6960a4572ababca0c9c7443f39437d28120245a0 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Sun, 24 Dec 2023 14:48:13 +0100 Subject: [PATCH 54/78] =?UTF-8?q?=F0=9F=9A=A7=20rooms?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/rooms.go | 24 ++++++++++++++++++++++++ plexams/rooms.go | 4 ++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/db/rooms.go b/db/rooms.go index c38e9ab..d9d3274 100644 --- a/db/rooms.go +++ b/db/rooms.go @@ -309,3 +309,27 @@ func (db *DB) ReplaceRoomsForNTA(ctx context.Context, plannedRooms []*model.Plan return nil } + +func (db *DB) ReplaceNonNTARooms(ctx context.Context, plannedRooms []*model.PlannedRoom) error { + collection := db.getCollectionSemester(collectionRoomsPlanned) + + _, err := collection.DeleteMany(ctx, bson.M{"handicaproomalone": false}) + if err != nil { + log.Error().Err(err).Msg("cannot delete non NTA rooms") + return err + } + + roomsInterface := make([]interface{}, 0, len(plannedRooms)) + + for _, room := range plannedRooms { + roomsInterface = append(roomsInterface, room) + } + + _, err = collection.InsertMany(ctx, roomsInterface) + if err != nil { + log.Error().Err(err).Msg("cannot insert non NTA rooms") + return err + } + + return nil +} diff --git a/plexams/rooms.go b/plexams/rooms.go index dfe58b6..fcd24e3 100644 --- a/plexams/rooms.go +++ b/plexams/rooms.go @@ -578,7 +578,7 @@ func (p *Plexams) RoomsForNTAsWithRoomAlone() error { func (p *Plexams) PrepareRoomForExams() error { ctx := context.Background() - examRooms := make([]interface{}, 0) + examRooms := make([]*model.PlannedRoom, 0) // only if room is needed more than 100 Minutes roomsNotUsableInSlot := set.NewSet[string]() @@ -890,7 +890,7 @@ func (p *Plexams) PrepareRoomForExams() error { // return err // } - return nil + return p.dbClient.ReplaceNonNTARooms(ctx, examRooms) } func (p *Plexams) ChangeRoom(ctx context.Context, ancode int, oldRoomName, newRoomName string) (bool, error) { From 449608bb2974ede0e7bec4cd5193b5ee5175ca83 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Mon, 25 Dec 2023 21:37:31 +0100 Subject: [PATCH 55/78] room generating finished? next step -> validation --- db/rooms.go | 4 +- graph/generated/generated.go | 54 ++- graph/model/models_gen.go | 2 +- graph/room.graphqls | 2 +- plexams/rooms.go | 519 +----------------------- plexams/roomsForNTA.go | 57 --- plexams/roomsPrepare.go | 765 +++++++++++++++++++++++++++++++++++ 7 files changed, 806 insertions(+), 597 deletions(-) delete mode 100644 plexams/roomsForNTA.go create mode 100644 plexams/roomsPrepare.go diff --git a/db/rooms.go b/db/rooms.go index d9d3274..039f0f0 100644 --- a/db/rooms.go +++ b/db/rooms.go @@ -201,7 +201,7 @@ func (db *DB) ChangeRoom(ctx context.Context, ancode int, oldRoom, newRoom *mode func (db *DB) PlannedRoomNames(ctx context.Context) ([]string, error) { collection := db.getCollectionSemester(collectionRoomsPlanned) - rawNames, err := collection.Distinct(ctx, "roomname", bson.D{}) + rawNames, err := collection.Distinct(ctx, "room.name", bson.D{}) if err != nil { log.Error().Err(err).Msg("cannot find distinct room names") } @@ -223,7 +223,7 @@ func (db *DB) PlannedRoomNamesInSlot(ctx context.Context, day, slot int) ([]stri filter := bson.M{"day": day, "slot": slot} - rawNames, err := collection.Distinct(ctx, "roomname", filter) + rawNames, err := collection.Distinct(ctx, "room.name", filter) if err != nil { log.Error().Err(err).Int("day", day).Int("slot", slot).Msg("cannot find roomnames for slot") return nil, err diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 252e972..3560b57 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -388,7 +388,7 @@ type ComplexityRoot struct { HandicapRoomAlone func(childComplexity int) int NtaMtknr func(childComplexity int) int Reserve func(childComplexity int) int - RoomName func(childComplexity int) int + Room func(childComplexity int) int Slot func(childComplexity int) int StudentsInRoom func(childComplexity int) int } @@ -2449,12 +2449,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PlannedRoom.Reserve(childComplexity), true - case "PlannedRoom.roomName": - if e.complexity.PlannedRoom.RoomName == nil { + case "PlannedRoom.room": + if e.complexity.PlannedRoom.Room == nil { break } - return e.complexity.PlannedRoom.RoomName(childComplexity), true + return e.complexity.PlannedRoom.Room(childComplexity), true case "PlannedRoom.slot": if e.complexity.PlannedRoom.Slot == nil { @@ -4662,7 +4662,7 @@ type SlotWithRooms { type PlannedRoom { day: Int! slot: Int! - roomName: String! + room: Room! ancode: Int! duration: Int! handicap: Boolean! @@ -10516,8 +10516,8 @@ func (ec *executionContext) fieldContext_ExamWithRegsAndRooms_rooms(ctx context. return ec.fieldContext_PlannedRoom_day(ctx, field) case "slot": return ec.fieldContext_PlannedRoom_slot(ctx, field) - case "roomName": - return ec.fieldContext_PlannedRoom_roomName(ctx, field) + case "room": + return ec.fieldContext_PlannedRoom_room(ctx, field) case "ancode": return ec.fieldContext_PlannedRoom_ancode(ctx, field) case "duration": @@ -16290,8 +16290,8 @@ func (ec *executionContext) fieldContext_PlannedExam_plannedRooms(ctx context.Co return ec.fieldContext_PlannedRoom_day(ctx, field) case "slot": return ec.fieldContext_PlannedRoom_slot(ctx, field) - case "roomName": - return ec.fieldContext_PlannedRoom_roomName(ctx, field) + case "room": + return ec.fieldContext_PlannedRoom_room(ctx, field) case "ancode": return ec.fieldContext_PlannedRoom_ancode(ctx, field) case "duration": @@ -16567,8 +16567,8 @@ func (ec *executionContext) fieldContext_PlannedRoom_slot(ctx context.Context, f return fc, nil } -func (ec *executionContext) _PlannedRoom_roomName(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_PlannedRoom_roomName(ctx, field) +func (ec *executionContext) _PlannedRoom_room(ctx context.Context, field graphql.CollectedField, obj *model.PlannedRoom) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedRoom_room(ctx, field) if err != nil { return graphql.Null } @@ -16581,7 +16581,7 @@ func (ec *executionContext) _PlannedRoom_roomName(ctx context.Context, field gra }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.RoomName, nil + return obj.Room, nil }) if err != nil { ec.Error(ctx, err) @@ -16593,19 +16593,37 @@ func (ec *executionContext) _PlannedRoom_roomName(ctx context.Context, field gra } return graphql.Null } - res := resTmp.(string) + res := resTmp.(*model.Room) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoom(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_PlannedRoom_roomName(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_PlannedRoom_room(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "PlannedRoom", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + switch field.Name { + case "name": + return ec.fieldContext_Room_name(ctx, field) + case "seats": + return ec.fieldContext_Room_seats(ctx, field) + case "handicap": + return ec.fieldContext_Room_handicap(ctx, field) + case "lab": + return ec.fieldContext_Room_lab(ctx, field) + case "placesWithSocket": + return ec.fieldContext_Room_placesWithSocket(ctx, field) + case "needsRequest": + return ec.fieldContext_Room_needsRequest(ctx, field) + case "exahm": + return ec.fieldContext_Room_exahm(ctx, field) + case "seb": + return ec.fieldContext_Room_seb(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Room", field.Name) }, } return fc, nil @@ -31656,8 +31674,8 @@ func (ec *executionContext) _PlannedRoom(ctx context.Context, sel ast.SelectionS if out.Values[i] == graphql.Null { out.Invalids++ } - case "roomName": - out.Values[i] = ec._PlannedRoom_roomName(ctx, field, obj) + case "room": + out.Values[i] = ec._PlannedRoom_room(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index e1b8531..f8cd943 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -290,7 +290,7 @@ type PlannedExamWithNta struct { type PlannedRoom struct { Day int `json:"day"` Slot int `json:"slot"` - RoomName string `json:"roomName"` + Room *Room `json:"room"` Ancode int `json:"ancode"` Duration int `json:"duration"` Handicap bool `json:"handicap"` diff --git a/graph/room.graphqls b/graph/room.graphqls index fa085de..7a0dc8f 100644 --- a/graph/room.graphqls +++ b/graph/room.graphqls @@ -28,7 +28,7 @@ type SlotWithRooms { type PlannedRoom { day: Int! slot: Int! - roomName: String! + room: Room! ancode: Int! duration: Int! handicap: Boolean! diff --git a/plexams/rooms.go b/plexams/rooms.go index fcd24e3..ff0eadb 100644 --- a/plexams/rooms.go +++ b/plexams/rooms.go @@ -3,16 +3,13 @@ package plexams import ( "context" "fmt" - "math" "sort" "time" set "github.com/deckarep/golang-set/v2" - "github.com/logrusorgru/aurora" "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" "github.com/spf13/viper" - "github.com/theckman/yacspin" ) type SlotNumber struct { @@ -379,520 +376,6 @@ func (p *Plexams) AddRoomToExam(ctx context.Context, input model.RoomForExamInpu // return room, nil // } -func (p *Plexams) RoomsForNTAsWithRoomAlone() error { - ctx := context.Background() - ntas, err := p.NtasWithRegs(ctx) - if err != nil { - log.Error().Err(err).Msg("cannot get ntas") - return err - } - - ntasMap := make(map[string]*model.Student) - type dayEntry struct { - slot int - ancode int - mtknr string - } - daysMap := make(map[int][]dayEntry) - examsMap := make(map[int]*model.PlannedExam) - - plannedRooms := make([]*model.PlannedRoom, 0) - - for _, nta := range ntas { - if !nta.Nta.NeedsRoomAlone { - continue - } - - cfg := yacspin.Config{ - Frequency: 100 * time.Millisecond, - CharSet: yacspin.CharSets[69], - Suffix: aurora.Sprintf(aurora.Cyan("finding exams for %s (%s)"), - aurora.Yellow(nta.Name), - aurora.Green(nta.Mtknr), - ), - SuffixAutoColon: true, - StopCharacter: "✓", - StopColors: []string{"fgGreen"}, - StopFailMessage: "error", - StopFailCharacter: "✗", - StopFailColors: []string{"fgRed"}, - } - - spinner, err := yacspin.New(cfg) - if err != nil { - log.Debug().Err(err).Msg("cannot create spinner") - } - err = spinner.Start() - if err != nil { - log.Debug().Err(err).Msg("cannot start spinner") - } - - ntasMap[nta.Mtknr] = nta - - regsNew := make([]int, 0, len(nta.Regs)) - for _, ancode := range nta.Regs { - exam, err := p.PlannedExam(ctx, ancode) - if err != nil { - log.Error().Err(err).Int("ancode", ancode).Msg("cannot get exam") - return err - } - if exam.Constraints == nil || !exam.Constraints.NotPlannedByMe { - examsMap[exam.Ancode] = exam - dayEntries, ok := daysMap[exam.PlanEntry.DayNumber] - if !ok { - dayEntries = make([]dayEntry, 0, 1) - } - daysMap[exam.PlanEntry.DayNumber] = append(dayEntries, dayEntry{ - slot: exam.PlanEntry.SlotNumber, - ancode: ancode, - mtknr: nta.Mtknr, - }) - regsNew = append(regsNew, ancode) - } - } - - nta.Regs = regsNew - - spinner.StopMessage(aurora.Sprintf(aurora.Cyan("found %v"), - aurora.Magenta(nta.Regs), - )) - - err = spinner.Stop() - if err != nil { - log.Debug().Err(err).Msg("cannot stop spinner") - } - } - - days := make([]int, 0, len(daysMap)) - for day := range daysMap { - days = append(days, day) - } - sort.Ints(days) - - for _, day := range days { - entries := daysMap[day] - if len(entries) == 1 { - fmt.Printf("day %2d: only one room needed: %v", day, entries[0]) - rooms, err := p.RoomsForSlot(ctx, day, entries[0].slot) - if err != nil { - log.Error().Err(err).Int("day", day).Int("slot", entries[0].slot).Msg("no rooms for slot found") - } - room := rooms.NtaRooms[0] - fmt.Printf(" -> using %s\n", room.Name) - - exam := examsMap[entries[0].ancode] - nta := ntasMap[entries[0].mtknr] - - ntaDuration := int(math.Ceil(float64(exam.ZpaExam.Duration*(100+nta.Nta.DeltaDurationPercent)) / 100)) - - plannedRooms = append(plannedRooms, &model.PlannedRoom{ - Day: day, - Slot: entries[0].slot, - RoomName: room.Name, - Ancode: entries[0].ancode, - Duration: ntaDuration, - Handicap: true, - HandicapRoomAlone: true, - Reserve: false, - StudentsInRoom: []string{nta.Nta.Mtknr}, - NtaMtknr: &nta.Nta.Mtknr, - }) - } else { - fmt.Printf("day %2d: more than one room needed: %v\n", day, entries) - slotsMap := make(map[int][]dayEntry) - for _, entry := range entries { - slotEntries, ok := slotsMap[entry.slot] - if !ok { - slotEntries = make([]dayEntry, 0, 1) - } - slotsMap[entry.slot] = append(slotEntries, entry) - } - - slots := make([]int, 0, len(slotsMap)) - for slot := range slotsMap { - slots = append(slots, slot) - } - sort.Ints(slots) - - prevSlot := -100 - roomsInPrevSlot := set.NewSet[string]() - for _, slot := range slots { - roomsInSlot := set.NewSet[string]() - if prevSlot+1 < slot { - roomsInPrevSlot = set.NewSet[string]() - } - - slotEntries := slotsMap[slot] - rooms, err := p.RoomsForSlot(ctx, day, slot) - if err != nil { - log.Error().Err(err).Int("day", day).Int("slot", slotEntries[0].slot).Msg("no rooms for slot found") - } - - fmt.Printf(" %d entries in slot %d\n", len(slotEntries), slot) - - for _, slotEntry := range slotEntries { - for _, room := range rooms.NtaRooms { - if roomsInPrevSlot.Contains(room.Name) || roomsInSlot.Contains(room.Name) { - continue - } - roomsInSlot.Add(room.Name) - fmt.Printf(" -> using %s for %v\n", room.Name, slotEntry) - exam := examsMap[slotEntry.ancode] - nta := ntasMap[slotEntry.mtknr] - - ntaDuration := int(math.Ceil(float64(exam.ZpaExam.Duration*(100+nta.Nta.DeltaDurationPercent)) / 100)) - - plannedRooms = append(plannedRooms, &model.PlannedRoom{ - Day: day, - Slot: slot, - RoomName: room.Name, - Ancode: slotEntry.ancode, - Duration: ntaDuration, - Handicap: true, - HandicapRoomAlone: true, - Reserve: false, - StudentsInRoom: []string{nta.Nta.Mtknr}, - NtaMtknr: &nta.Nta.Mtknr, - }) - break - } - } - - prevSlot = slot - roomsInPrevSlot = roomsInSlot - } - } - } - - for _, plannedRoom := range plannedRooms { - exam := examsMap[plannedRoom.Ancode] - fmt.Printf("(%d/%d) %d. %s (%s), Raum %s für %s (%d Minuten)\n", plannedRoom.Day, plannedRoom.Slot, - exam.Ancode, exam.ZpaExam.Module, exam.ZpaExam.MainExamer, - plannedRoom.RoomName, ntasMap[*plannedRoom.NtaMtknr].Name, plannedRoom.Duration, - ) - } - return p.dbClient.ReplaceRoomsForNTA(ctx, plannedRooms) -} - -// TODO: rewrite me. -func (p *Plexams) PrepareRoomForExams() error { - ctx := context.Background() - - examRooms := make([]*model.PlannedRoom, 0) - - // only if room is needed more than 100 Minutes - roomsNotUsableInSlot := set.NewSet[string]() - - for _, slot := range p.semesterConfig.Slots { - cfg := yacspin.Config{ - Frequency: 100 * time.Millisecond, - CharSet: yacspin.CharSets[69], - Suffix: aurora.Sprintf(aurora.Black("finding rooms for slot (%d/%d)"), - aurora.Yellow(slot.DayNumber), - aurora.Yellow(slot.SlotNumber), - ), - SuffixAutoColon: true, - StopCharacter: "✓", - StopColors: []string{"fgGreen"}, - StopFailMessage: "error", - StopFailCharacter: "✗", - StopFailColors: []string{"fgRed"}, - } - - spinner, err := yacspin.New(cfg) - if err != nil { - log.Debug().Err(err).Msg("cannot create spinner") - } - err = spinner.Start() - if err != nil { - log.Debug().Err(err).Msg("cannot start spinner") - } - - log.Debug().Int("day", slot.DayNumber).Int("slot", slot.SlotNumber).Msg("preparing rooms for slot") - // get exams - if slot.SlotNumber == 1 { - roomsNotUsableInSlot = set.NewSet[string]() - } - examsInPlan, err := p.GetExamsInSlot(ctx, slot.DayNumber, slot.SlotNumber) - - if err != nil { - log.Error().Err(err).Int("day", slot.DayNumber).Int("time", slot.SlotNumber). - Msg("error while trying to find exams in slot") - return err - } - - // no exams in slot - if len(examsInPlan) == 0 { - spinner.StopMessage(aurora.Sprintf(aurora.Blue("no exams in slot"))) - err := spinner.Stop() - if err != nil { - log.Debug().Err(err).Msg("cannot stop spinner") - } - roomsNotUsableInSlot = set.NewSet[string]() - continue - } - - // no exams for me to plan in slot - needRooms := false - for _, exam := range examsInPlan { - if exam.Constraints == nil || !exam.Constraints.NotPlannedByMe { - needRooms = true - break - } - } - - if !needRooms { - spinner.StopMessage(aurora.Sprintf(aurora.Blue("no exams for me to plan in slot"))) - err = spinner.Stop() - if err != nil { - log.Debug().Err(err).Msg("cannot stop spinner") - } - roomsNotUsableInSlot = set.NewSet[string]() - continue - } - - err = spinner.Stop() - if err != nil { - log.Debug().Err(err).Msg("cannot stop spinner") - } - - // planning for each exam starts here - exams := make([]*model.ExamWithRegsAndRooms, 0, len(examsInPlan)) - for _, examInPlan := range examsInPlan { - - if examInPlan.Constraints != nil && examInPlan.Constraints.NotPlannedByMe { - continue - } - - ntas := examInPlan.Ntas - ntaMtknrs := set.NewSet[string]() - ntasInNormalRooms := make([]*model.NTA, 0) - for _, nta := range ntas { - ntaMtknrs.Add(nta.Mtknr) - if !nta.NeedsRoomAlone { - ntasInNormalRooms = append(ntasInNormalRooms, nta) // nolint - } - } - - normalRegs := make([]string, 0) - for _, primussExam := range examInPlan.PrimussExams { - for _, studentRegs := range primussExam.StudentRegs { - if !ntaMtknrs.Contains(studentRegs.Mtknr) { - normalRegs = append(normalRegs, studentRegs.Mtknr) - } - } - } - - exams = append(exams, &model.ExamWithRegsAndRooms{ - Exam: examInPlan, - NormalRegsMtknr: normalRegs, - Ntas: ntas, - Rooms: make([]*model.PlannedRoom, 0), - }) - } - - // get rooms - slotWithRooms, err := p.RoomsForSlot(ctx, slot.DayNumber, slot.SlotNumber) - if err != nil { - log.Error().Err(err).Int("day", slot.DayNumber).Int("time", slot.SlotNumber). - Msg("error while trying to get rooms for slot") - return err - } - - // rooms without NTA - for { - if len(exams) == 0 { - break - } - - sort.Slice(exams, func(i, j int) bool { - return len(exams[i].NormalRegsMtknr)+len(exams[i].Ntas) > len(exams[j].NormalRegsMtknr)+len(exams[j].Ntas) - }) - - if len(exams[0].NormalRegsMtknr) == 0 { - break - } - - exam := exams[0] - exams = exams[1:] - - cfg.Suffix = aurora.Sprintf(aurora.Magenta(" ↪ %d. %s (%s): %d of %d studs left"), - exam.Exam.Ancode, exam.Exam.ZpaExam.Module, exam.Exam.ZpaExam.MainExamer, - len(exam.NormalRegsMtknr), exam.Exam.StudentRegsCount) - spinner, err := yacspin.New(cfg) - if err != nil { - log.Debug().Err(err).Msg("cannot create spinner") - } - err = spinner.Start() - if err != nil { - log.Debug().Err(err).Msg("cannot start spinner") - } - - var room *model.Room - - // TODO: room used to long in previous slot - if exam.Exam.Constraints != nil { - if exam.Exam.Constraints.Online { - room = &model.Room{ - Name: "ONLINE", - Seats: 1000, - } - } else if exam.Exam.Constraints.RoomConstraints != nil { - if exam.Exam.Constraints.RoomConstraints.ExahmRooms { - if len(slotWithRooms.ExahmRooms) > 0 { - room = slotWithRooms.ExahmRooms[0] - slotWithRooms.ExahmRooms = slotWithRooms.ExahmRooms[1:] - } - } else if exam.Exam.Constraints.RoomConstraints.Seb { - if len(slotWithRooms.ExahmRooms) > 0 { - room = slotWithRooms.ExahmRooms[0] - slotWithRooms.ExahmRooms = slotWithRooms.ExahmRooms[1:] - } - } else if exam.Exam.Constraints.RoomConstraints.Lab { - if len(slotWithRooms.LabRooms) > 0 { - room = slotWithRooms.LabRooms[0] - slotWithRooms.LabRooms = slotWithRooms.LabRooms[1:] - } - } else if exam.Exam.Constraints.RoomConstraints.PlacesWithSocket { - for i := 0; i < len(slotWithRooms.NormalRooms); i++ { - if slotWithRooms.NormalRooms[i].PlacesWithSocket { - room = slotWithRooms.NormalRooms[i] - slotWithRooms.NormalRooms = append(slotWithRooms.NormalRooms[:i], slotWithRooms.NormalRooms[i+1:]...) - break - } - } - } else { - room = slotWithRooms.NormalRooms[0] - slotWithRooms.NormalRooms = slotWithRooms.NormalRooms[1:] - } - } else { - room = slotWithRooms.NormalRooms[0] - slotWithRooms.NormalRooms = slotWithRooms.NormalRooms[1:] - } - } else { - room = slotWithRooms.NormalRooms[0] - slotWithRooms.NormalRooms = slotWithRooms.NormalRooms[1:] - } - - if room == nil { - log.Error().Int("ancode", exam.Exam.Ancode). - Msg("no room found for exam") - room = &model.Room{ - Name: "No Room", - Seats: 1000, - } - } - - reserveRoom := false - studentCountInRoom := room.Seats - if studentCountInRoom > len(exam.NormalRegsMtknr) { - studentCountInRoom = len(exam.NormalRegsMtknr) - if len(exam.Rooms) > 0 && studentCountInRoom < 10 { - reserveRoom = true - } - } - - studentsInRoom := exam.NormalRegsMtknr[:studentCountInRoom] - exam.NormalRegsMtknr = exam.NormalRegsMtknr[studentCountInRoom:] - - examRoom := model.PlannedRoom{ - Day: slot.DayNumber, - Slot: slot.SlotNumber, - RoomName: room.Name, - Ancode: exam.Exam.Ancode, - Duration: exam.Exam.ZpaExam.Duration, - Handicap: false, - HandicapRoomAlone: false, - Reserve: reserveRoom, - StudentsInRoom: studentsInRoom, - NtaMtknr: nil, - } - - exam.Rooms = append(exam.Rooms, &examRoom) - examRooms = append(examRooms, &examRoom) // nolint - - exams = append(exams, exam) - - spinner.StopMessage(aurora.Sprintf(aurora.Green("added %s for %d students (max. %d)"), - examRoom.RoomName, len(examRoom.StudentsInRoom), room.Seats)) - err = spinner.Stop() - if err != nil { - log.Debug().Err(err).Msg("cannot stop spinner") - } - } // for exams - - if roomsNotUsableInSlot.Cardinality() > 0 { - log.Debug().Interface("rooms", roomsNotUsableInSlot).Msg("rooms not usable in slot") - } - - // // NTAs - // for _, exam := range exams { - // if len(exam.NtaRegs) == 0 { - // continue - // } - - // ntaRooms := slotWithRooms.NtaRooms - - // for _, nta := range exam.NtaRegs { - - // ntaDuration := int(math.Ceil(float64(exam.Exam.Exam.ZpaExam.Duration*(100+nta.Nta.DeltaDurationPercent)) / 100)) - - // if nta.Nta.NeedsRoomAlone { - // examRooms = append(examRooms, &model.RoomForExam{ - // Ancode: exam.Exam.Exam.Ancode, - // RoomName: ntaRooms[0].Name, - // SeatsPlanned: 1, - // Duration: ntaDuration, - // Handicap: true, - // Reserve: false, - // Students: []*model.StudentReg{ - // { - // Mtknr: nta.Nta.Mtknr, - // Name: nta.Nta.Name, - // }, - // }, - // }) - // ntaRooms = ntaRooms[1:] - // } else { - // // find room with a seat left - // for _, room := range exam.Rooms { - // if room.SeatsPlanned < p.GetRoomInfo(room.RoomName).Seats { - // examRooms = append(examRooms, &model.RoomForExam{ - // Ancode: exam.Exam.Exam.Ancode, - // RoomName: room.RoomName, - // SeatsPlanned: 1, - // Duration: ntaDuration, - // Handicap: true, - // Reserve: false, - // Students: []*model.StudentReg{ - // { - // Mtknr: nta.Nta.Mtknr, - // Name: nta.Nta.Name, - // }, - // }, - // }) - // break - // } - // } - // } - // } - // } - - err = spinner.Stop() - if err != nil { - log.Debug().Err(err).Msg("cannot stop spinner") - } - } // for slot - - // err := p.dbClient.DropAndSave(context.WithValue(ctx, db.CollectionName("collectionName"), "rooms_for_exams"), examRooms) - // if err != nil { - // log.Error().Err(err).Msg("cannot save rooms for exams") - // return err - // } - - return p.dbClient.ReplaceNonNTARooms(ctx, examRooms) -} - func (p *Plexams) ChangeRoom(ctx context.Context, ancode int, oldRoomName, newRoomName string) (bool, error) { roomsForAncode, err := p.dbClient.RoomsForAncode(ctx, ancode) if err != nil { @@ -975,7 +458,7 @@ func enhancePlannedRooms(plannedRooms []*model.PlannedRoom) []*model.EnhancedPla enhancedPlannedRooms = append(enhancedPlannedRooms, &model.EnhancedPlannedRoom{ Day: room.Day, Slot: room.Ancode, - RoomName: room.RoomName, + RoomName: room.Room.Name, Ancode: room.Ancode, Duration: room.Duration, Handicap: room.Handicap, diff --git a/plexams/roomsForNTA.go b/plexams/roomsForNTA.go deleted file mode 100644 index 9f48e1d..0000000 --- a/plexams/roomsForNTA.go +++ /dev/null @@ -1,57 +0,0 @@ -package plexams - -import "fmt" - -// FIXME: rewrite me -func (p *Plexams) GetRoomsForNTA(name string) error { - // ctx := context.Background() - // ntas, err := p.NtasWithRegs(ctx) - // if err != nil { - // return err - // } - // var nta *model.NTAWithRegs - // for _, ntaInDB := range ntas { - // if strings.HasPrefix(ntaInDB.Nta.Name, name) { - // nta = ntaInDB - // break - // } - // } - // if nta == nil { - // return fmt.Errorf("NTA with name=%s not found", name) - // } - // log.Debug().Str("name", nta.Nta.Name).Msg("found nta") - - // ANCODES: - // for _, ancode := range nta.Regs.Ancodes { - // exam, err := p.dbClient.GetZpaExamByAncode(ctx, ancode) - // if err != nil { - // log.Error().Err(err).Int("ancode", ancode).Msg("cannot get zpa exam") - // } - - // constraints, err := p.ConstraintForAncode(ctx, ancode) - // if err != nil { - // log.Error().Err(err).Int("ancode", ancode).Msg("cannot get constraints") - // } - // if constraints != nil && constraints.NotPlannedByMe { - // log.Debug().Int("ancode", ancode).Str("examer", exam.MainExamer).Str("module", exam.Module).Msg("exam not planned by me") - // continue - // } - // log.Debug().Int("ancode", ancode).Str("examer", exam.MainExamer).Str("module", exam.Module).Msg("found exam") - - // roomsForExam, err := p.dbClient.RoomsForAncode(ctx, ancode) - // if err != nil { - // log.Error().Err(err).Int("ancode", ancode).Msg("cannot get rooms") - // } - // for _, room := range roomsForExam { - // for _, stud := range room.Students { - // if nta.Nta.Mtknr == stud.Mtknr { - // fmt.Printf("%d. %s: %s --- Raum %s\n", ancode, exam.MainExamer, exam.Module, room.RoomName) - // continue ANCODES - // } - // } - // } - - // } - - return fmt.Errorf("rewrite me") -} diff --git a/plexams/roomsPrepare.go b/plexams/roomsPrepare.go new file mode 100644 index 0000000..767a64f --- /dev/null +++ b/plexams/roomsPrepare.go @@ -0,0 +1,765 @@ +package plexams + +import ( + "context" + "fmt" + "math" + "sort" + "time" + + set "github.com/deckarep/golang-set/v2" + "github.com/logrusorgru/aurora" + "github.com/obcode/plexams.go/graph/model" + "github.com/rs/zerolog/log" + "github.com/spf13/viper" + "github.com/theckman/yacspin" +) + +func (p *Plexams) RoomsForNTAsWithRoomAlone() error { + ctx := context.Background() + ntas, err := p.NtasWithRegs(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get ntas") + return err + } + + ntasMap := make(map[string]*model.Student) + type dayEntry struct { + slot int + ancode int + mtknr string + } + daysMap := make(map[int][]dayEntry) + examsMap := make(map[int]*model.PlannedExam) + + plannedRooms := make([]*model.PlannedRoom, 0) + + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: "", + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + + for _, nta := range ntas { + if !nta.Nta.NeedsRoomAlone { + continue + } + + cfg.Suffix = aurora.Sprintf(aurora.Cyan(" finding exams for %s (%s)"), + aurora.Yellow(nta.Name), + aurora.Green(nta.Mtknr), + ) + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + ntasMap[nta.Mtknr] = nta + + regsNew := make([]int, 0, len(nta.Regs)) + for _, ancode := range nta.Regs { + exam, err := p.PlannedExam(ctx, ancode) + if err != nil { + log.Error().Err(err).Int("ancode", ancode).Msg("cannot get exam") + return err + } + if exam.Constraints == nil || !exam.Constraints.NotPlannedByMe { + examsMap[exam.Ancode] = exam + dayEntries, ok := daysMap[exam.PlanEntry.DayNumber] + if !ok { + dayEntries = make([]dayEntry, 0, 1) + } + daysMap[exam.PlanEntry.DayNumber] = append(dayEntries, dayEntry{ + slot: exam.PlanEntry.SlotNumber, + ancode: ancode, + mtknr: nta.Mtknr, + }) + regsNew = append(regsNew, ancode) + } + } + + nta.Regs = regsNew + + spinner.StopMessage(aurora.Sprintf(aurora.Cyan("found %v"), + aurora.Magenta(nta.Regs), + )) + + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + } + + days := make([]int, 0, len(daysMap)) + for day := range daysMap { + days = append(days, day) + } + sort.Ints(days) + + for _, day := range days { + + slotsMap := make(map[int][]dayEntry) + for _, entry := range daysMap[day] { + slotEntries, ok := slotsMap[entry.slot] + if !ok { + slotEntries = make([]dayEntry, 0, 1) + } + slotsMap[entry.slot] = append(slotEntries, entry) + } + + slots := make([]int, 0, len(slotsMap)) + for slot := range slotsMap { + slots = append(slots, slot) + } + sort.Ints(slots) + + prevSlot := -100 + roomsInPrevSlot := set.NewSet[string]() + for _, slot := range slots { + roomsInSlot := set.NewSet[string]() + if prevSlot+1 < slot { + roomsInPrevSlot = set.NewSet[string]() + } + + slotEntries := slotsMap[slot] + rooms, err := p.RoomsForSlot(ctx, day, slot) + if err != nil { + log.Error().Err(err).Int("day", day).Int("slot", slotEntries[0].slot).Msg("no rooms for slot found") + } + + cfg.Suffix = aurora.Sprintf(aurora.Cyan(" slot (%d/%d) with %d needed room(s)"), day, slot, len(slotEntries)) + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + for _, slotEntry := range slotEntries { + + var room *model.Room + exam := examsMap[slotEntry.ancode] + if exam.Constraints != nil && exam.Constraints.RoomConstraints != nil && exam.Constraints.RoomConstraints.ExahmRooms { + for _, exahmRoom := range rooms.ExahmRooms { + if exahmRoom.Handicap { + room = exahmRoom + break + } + } + if room == nil { + fmt.Printf("we need an exahm room!!!") + return fmt.Errorf("we need an exahm room") + } + } else { + for _, ntaRoom := range rooms.NtaRooms { + if roomsInPrevSlot.Contains(ntaRoom.Name) || roomsInSlot.Contains(ntaRoom.Name) { + continue + } + room = ntaRoom + break + } + } + roomsInSlot.Add(room.Name) + + nta := ntasMap[slotEntry.mtknr] + + ntaDuration := int(math.Ceil(float64(exam.ZpaExam.Duration*(100+nta.Nta.DeltaDurationPercent)) / 100)) + + plannedRooms = append(plannedRooms, &model.PlannedRoom{ + Day: day, + Slot: slot, + Room: room, + Ancode: slotEntry.ancode, + Duration: ntaDuration, + Handicap: true, + HandicapRoomAlone: true, + Reserve: false, + StudentsInRoom: []string{nta.Nta.Mtknr}, + NtaMtknr: &nta.Nta.Mtknr, + }) + } + + prevSlot = slot + roomsInPrevSlot = roomsInSlot + + spinner.StopMessage(aurora.Sprintf(aurora.Green("using %v"), roomsInSlot.ToSlice())) + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + } + // } + } + + for _, plannedRoom := range plannedRooms { + exam := examsMap[plannedRoom.Ancode] + fmt.Println(aurora.Sprintf(aurora.Cyan("(%d/%d) %d. %s (%s), Raum %s für %s (%d Minuten)"), plannedRoom.Day, plannedRoom.Slot, + exam.Ancode, aurora.Blue(exam.ZpaExam.Module), exam.ZpaExam.MainExamer, + aurora.Magenta(plannedRoom.Room.Name), aurora.Green(ntasMap[*plannedRoom.NtaMtknr].Name), aurora.Green(plannedRoom.Duration), + )) + } + return p.dbClient.ReplaceRoomsForNTA(ctx, plannedRooms) +} + +// TODO: rewrite me. +func (p *Plexams) PrepareRoomForExams() error { + ctx := context.Background() + + additionalSeats := make(map[int]int) // ancode -> seats + additionalSeatsViper := viper.Get("roomconstraints.additionalseats") + + additionalSeatsSlice, ok := additionalSeatsViper.([]interface{}) + if ok { + for _, addSeat := range additionalSeatsSlice { + entry, ok := addSeat.(map[string]interface{}) + if !ok { + log.Error().Interface("addSeat", addSeat).Msg("cannot convert addSeat to map") + } + ancode, okAncode := entry["ancode"].(int) + seats, okSeats := entry["seats"].(int) + + if okAncode && okSeats { + additionalSeats[ancode] = seats + } + } + } + + log.Debug().Interface("additionalSeats", additionalSeats).Msg("found additional seats") + + // only if room is needed more than 100 Minutes + roomsNotUsableInSlot := set.NewSet[string]() + + examRooms := make([]*model.PlannedRoom, 0) + for _, slot := range p.semesterConfig.Slots { + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Black("finding rooms for slot (%d/%d)"), + aurora.Yellow(slot.DayNumber), + aurora.Yellow(slot.SlotNumber), + ), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + log.Debug().Int("day", slot.DayNumber).Int("slot", slot.SlotNumber).Msg("preparing rooms for slot") + // get exams + if slot.SlotNumber == 1 { + roomsNotUsableInSlot = set.NewSet[string]() + } + examsInPlan, err := p.GetExamsInSlot(ctx, slot.DayNumber, slot.SlotNumber) + + if err != nil { + log.Error().Err(err).Int("day", slot.DayNumber).Int("time", slot.SlotNumber). + Msg("error while trying to find exams in slot") + return err + } + + // no exams in slot + if len(examsInPlan) == 0 { + spinner.StopMessage(aurora.Sprintf(aurora.Blue("no exams in slot"))) + err := spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + roomsNotUsableInSlot = set.NewSet[string]() + continue + } + + // no exams for me to plan in slot + needRooms := false + for _, exam := range examsInPlan { + if exam.Constraints == nil || !exam.Constraints.NotPlannedByMe { + needRooms = true + break + } + } + + if !needRooms { + spinner.StopMessage(aurora.Sprintf(aurora.Blue("no exams for me to plan in slot"))) + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + roomsNotUsableInSlot = set.NewSet[string]() + continue + } + + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + + // planning for each exam starts here + exams := make([]*model.ExamWithRegsAndRooms, 0, len(examsInPlan)) + examsMap := make(map[int]*model.PlannedExam) + for _, examInPlan := range examsInPlan { + + if examInPlan.Constraints != nil && examInPlan.Constraints.NotPlannedByMe { + continue + } + + ntas := examInPlan.Ntas + ntaMtknrs := set.NewSet[string]() + ntasInNormalRooms := make([]*model.NTA, 0) + for _, nta := range ntas { + ntaMtknrs.Add(nta.Mtknr) + if !nta.NeedsRoomAlone { + ntasInNormalRooms = append(ntasInNormalRooms, nta) // nolint + } + } + + normalRegs := make([]string, 0) + for _, primussExam := range examInPlan.PrimussExams { + for _, studentRegs := range primussExam.StudentRegs { + if !ntaMtknrs.Contains(studentRegs.Mtknr) { + normalRegs = append(normalRegs, studentRegs.Mtknr) + } + } + } + + addSeats, ok := additionalSeats[examInPlan.Ancode] + if ok { + fmt.Println(aurora.Sprintf(aurora.BrightRed(" adding %d seats to %d. %s (%s)"), + addSeats, examInPlan.Ancode, examInPlan.ZpaExam.Module, examInPlan.ZpaExam.MainExamer)) + for i := 0; i < addSeats; i++ { + normalRegs = append(normalRegs, "dummy") + } + } + + exams = append(exams, &model.ExamWithRegsAndRooms{ + Exam: examInPlan, + NormalRegsMtknr: normalRegs, + Ntas: ntasInNormalRooms, + Rooms: make([]*model.PlannedRoom, 0), + }) + examsMap[examInPlan.Ancode] = examInPlan + } + + // get rooms + slotWithRooms, err := p.RoomsForSlot(ctx, slot.DayNumber, slot.SlotNumber) + if err != nil { + log.Error().Err(err).Int("day", slot.DayNumber).Int("time", slot.SlotNumber). + Msg("error while trying to get rooms for slot") + return err + } + + if roomsNotUsableInSlot.Cardinality() > 0 { + normalRooms := make([]*model.Room, 0, len(slotWithRooms.NormalRooms)) + for _, normalRoom := range slotWithRooms.NormalRooms { + if !roomsNotUsableInSlot.Contains(normalRoom.Name) { + normalRooms = append(normalRooms, normalRoom) + } + } + slotWithRooms.NormalRooms = normalRooms + + exahmRooms := make([]*model.Room, 0, len(slotWithRooms.ExahmRooms)) + for _, exahmRoom := range slotWithRooms.ExahmRooms { + if !roomsNotUsableInSlot.Contains(exahmRoom.Name) { + exahmRooms = append(exahmRooms, exahmRoom) + } + } + slotWithRooms.ExahmRooms = exahmRooms + + labRooms := make([]*model.Room, 0, len(slotWithRooms.LabRooms)) + for _, labRoom := range slotWithRooms.LabRooms { + if !roomsNotUsableInSlot.Contains(labRoom.Name) { + labRooms = append(labRooms, labRoom) + } + } + slotWithRooms.LabRooms = labRooms + + roomsNotUsableInSlot = set.NewSet[string]() + } + + type PlannedRoomsWithFreeSeats struct { + rooms []*model.PlannedRoom + freeSeats int + } + plannedRoomsWithFreeSeats := make(map[string]PlannedRoomsWithFreeSeats) + + // rooms without NTA + for { + if len(exams) == 0 { + break + } + + sort.Slice(exams, func(i, j int) bool { + return len(exams[i].NormalRegsMtknr)+len(exams[i].Ntas) > len(exams[j].NormalRegsMtknr)+len(exams[j].Ntas) + }) + + if len(exams[0].NormalRegsMtknr) == 0 { + break + } + + exam := exams[0] + exams = exams[1:] + + cfg.Suffix = aurora.Sprintf(aurora.Magenta(" ↪ %d. %s (%s): %d of %d studs left"), + exam.Exam.Ancode, exam.Exam.ZpaExam.Module, exam.Exam.ZpaExam.MainExamer, + len(exam.NormalRegsMtknr), exam.Exam.StudentRegsCount) + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + var room *model.Room + + neededSeats := len(exam.NormalRegsMtknr) + len(exam.Ntas) + + if neededSeats < 10 { + + type RoomWithSeatsLeft struct { + room *model.Room + seatsLeft int + } + var roomFound *RoomWithSeatsLeft + OUTER: + for _, plannedRoomWithFreeSeats := range plannedRoomsWithFreeSeats { + seatsLeft := plannedRoomWithFreeSeats.freeSeats - neededSeats + if seatsLeft <= 0 { + continue + } + for _, room := range plannedRoomWithFreeSeats.rooms { + otherExam := examsMap[room.Ancode] + if exam.Exam.Constraints != nil && exam.Exam.Constraints.RoomConstraints != nil { + if exam.Exam.Constraints.RoomConstraints.ExahmRooms && !room.Room.Exahm || + exam.Exam.Constraints.RoomConstraints.Lab && !room.Room.Lab || + exam.Exam.Constraints.RoomConstraints.PlacesWithSocket && !room.Room.PlacesWithSocket || + exam.Exam.Constraints.RoomConstraints.Seb && !room.Room.Seb { + continue OUTER + } + } + if exam.Exam.ZpaExam.Duration != otherExam.ZpaExam.Duration { + continue OUTER + } + + if exam.Exam.ZpaExam.MainExamerID == otherExam.ZpaExam.MainExamerID { + roomFound = &RoomWithSeatsLeft{ + room: room.Room, + seatsLeft: plannedRoomWithFreeSeats.freeSeats - neededSeats, + } + break OUTER + } + if exam.Exam.ZpaExam.Module == otherExam.ZpaExam.Module { + roomFound = &RoomWithSeatsLeft{ + room: room.Room, + seatsLeft: plannedRoomWithFreeSeats.freeSeats - neededSeats, + } + break OUTER + } + + if roomFound == nil || roomFound.seatsLeft < seatsLeft { + roomFound = &RoomWithSeatsLeft{ + room: room.Room, + seatsLeft: seatsLeft, + } + } + } + } + if roomFound != nil { + room = roomFound.room + } + } + + if room == nil { + // TODO: room used to long in previous slot + if exam.Exam.Constraints != nil { + if exam.Exam.Constraints.Online { + room = &model.Room{ + Name: "ONLINE", + Seats: 1000, + } + } else if exam.Exam.Constraints.RoomConstraints != nil { + if exam.Exam.Constraints.RoomConstraints.ExahmRooms { + if len(slotWithRooms.ExahmRooms) > 0 { + room = slotWithRooms.ExahmRooms[0] + slotWithRooms.ExahmRooms = slotWithRooms.ExahmRooms[1:] + } + } else if exam.Exam.Constraints.RoomConstraints.Seb { + if len(slotWithRooms.ExahmRooms) > 0 { + room = slotWithRooms.ExahmRooms[0] + slotWithRooms.ExahmRooms = slotWithRooms.ExahmRooms[1:] + } + } else if exam.Exam.Constraints.RoomConstraints.Lab { + if len(slotWithRooms.LabRooms) > 0 { + room = slotWithRooms.LabRooms[0] + slotWithRooms.LabRooms = slotWithRooms.LabRooms[1:] + } + } else if exam.Exam.Constraints.RoomConstraints.PlacesWithSocket { + for i := 0; i < len(slotWithRooms.NormalRooms); i++ { + if slotWithRooms.NormalRooms[i].PlacesWithSocket { + room = slotWithRooms.NormalRooms[i] + slotWithRooms.NormalRooms = append(slotWithRooms.NormalRooms[:i], slotWithRooms.NormalRooms[i+1:]...) + break + } + } + } else { + room = slotWithRooms.NormalRooms[0] + slotWithRooms.NormalRooms = slotWithRooms.NormalRooms[1:] + } + } else { + room = slotWithRooms.NormalRooms[0] + slotWithRooms.NormalRooms = slotWithRooms.NormalRooms[1:] + } + } else { + room = slotWithRooms.NormalRooms[0] + slotWithRooms.NormalRooms = slotWithRooms.NormalRooms[1:] + } + } + + if room == nil { + log.Error().Int("ancode", exam.Exam.Ancode). + Msg("no room found for exam") + room = &model.Room{ + Name: "No Room", + Seats: 1000, + } + } + + // TODO: no if only room for exam + reserveRoom := false + studentCountInRoom := room.Seats + if studentCountInRoom > len(exam.NormalRegsMtknr) { + studentCountInRoom = len(exam.NormalRegsMtknr) + if len(exam.Rooms) > 0 && studentCountInRoom < 10 { + reserveRoom = true + } + } + + studentsInRoom := exam.NormalRegsMtknr[:studentCountInRoom] + exam.NormalRegsMtknr = exam.NormalRegsMtknr[studentCountInRoom:] + + examRoom := model.PlannedRoom{ + Day: slot.DayNumber, + Slot: slot.SlotNumber, + Room: room, + Ancode: exam.Exam.Ancode, + Duration: exam.Exam.ZpaExam.Duration, + Handicap: false, + HandicapRoomAlone: false, + Reserve: reserveRoom, + StudentsInRoom: studentsInRoom, + NtaMtknr: nil, + } + + exam.Rooms = append(exam.Rooms, &examRoom) + examRooms = append(examRooms, &examRoom) // nolint + + exams = append(exams, exam) + + // for _, plannedRoom := range exam.Rooms { + plannedRoomWithFreeSeats, ok := plannedRoomsWithFreeSeats[examRoom.Room.Name] + if !ok { + plannedRoomWithFreeSeats = PlannedRoomsWithFreeSeats{ + rooms: make([]*model.PlannedRoom, 0, 1), + freeSeats: examRoom.Room.Seats, + } + } + plannedRoomsWithFreeSeats[examRoom.Room.Name] = PlannedRoomsWithFreeSeats{ + rooms: append(plannedRoomWithFreeSeats.rooms, &examRoom), + freeSeats: plannedRoomWithFreeSeats.freeSeats - (len(examRoom.StudentsInRoom) + len(exam.Ntas)), + } + // } + + spinner.StopMessage(aurora.Sprintf(aurora.Green("added %s for %d students (max. %d)"), + examRoom.Room.Name, len(examRoom.StudentsInRoom), room.Seats)) + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + } // for exams + + // NTAs in normal rooms + for _, exam := range exams { + maxDuration := exam.Exam.ZpaExam.Duration + for _, nta := range exam.Ntas { + ntaDuration := int(math.Ceil(float64(exam.Exam.ZpaExam.Duration*(100+nta.DeltaDurationPercent)) / 100)) + if maxDuration < ntaDuration { + maxDuration = ntaDuration + } + } + + // find room with a seat left + var roomFound *model.Room + for _, room := range exam.Rooms { + if maxDuration > 100 && (room.Room.Name == "R1.046" || room.Room.Name == "R1.049") { + continue + } + + if room.Room.Seats >= len(room.StudentsInRoom)+len(exam.Ntas) { + roomFound = room.Room + break + } + } + if roomFound == nil { + // need a new room + if exam.Exam.Constraints != nil { + if exam.Exam.Constraints.Online { + roomFound = &model.Room{ + Name: "ONLINE", + Seats: 1000, + } + } else if exam.Exam.Constraints.RoomConstraints != nil { + if exam.Exam.Constraints.RoomConstraints.ExahmRooms { + if len(slotWithRooms.ExahmRooms) > 0 { + roomFound = slotWithRooms.ExahmRooms[0] + slotWithRooms.ExahmRooms = slotWithRooms.ExahmRooms[1:] + } + } else if exam.Exam.Constraints.RoomConstraints.Seb { + if len(slotWithRooms.ExahmRooms) > 0 { + roomFound = slotWithRooms.ExahmRooms[0] + slotWithRooms.ExahmRooms = slotWithRooms.ExahmRooms[1:] + } + } else if exam.Exam.Constraints.RoomConstraints.Lab { + if len(slotWithRooms.LabRooms) > 0 { + roomFound = slotWithRooms.LabRooms[0] + slotWithRooms.LabRooms = slotWithRooms.LabRooms[1:] + } + } else if exam.Exam.Constraints.RoomConstraints.PlacesWithSocket { + for i := 0; i < len(slotWithRooms.NormalRooms); i++ { + if slotWithRooms.NormalRooms[i].PlacesWithSocket { + roomFound = slotWithRooms.NormalRooms[i] + slotWithRooms.NormalRooms = append(slotWithRooms.NormalRooms[:i], slotWithRooms.NormalRooms[i+1:]...) + break + } + } + } else { + roomFound = slotWithRooms.NormalRooms[0] + slotWithRooms.NormalRooms = slotWithRooms.NormalRooms[1:] + } + } else { + roomFound = slotWithRooms.NormalRooms[0] + slotWithRooms.NormalRooms = slotWithRooms.NormalRooms[1:] + } + } else { + roomFound = slotWithRooms.NormalRooms[0] + slotWithRooms.NormalRooms = slotWithRooms.NormalRooms[1:] + } + } + + for _, nta := range exam.Ntas { + ntaDuration := int(math.Ceil(float64(exam.Exam.ZpaExam.Duration*(100+nta.DeltaDurationPercent)) / 100)) + examRoom := model.PlannedRoom{ + Day: slot.DayNumber, + Slot: slot.SlotNumber, + Room: roomFound, + Ancode: exam.Exam.Ancode, + Duration: ntaDuration, + Handicap: true, + HandicapRoomAlone: false, + Reserve: false, + StudentsInRoom: []string{nta.Mtknr}, + NtaMtknr: &nta.Mtknr, + } + + exam.Rooms = append(exam.Rooms, &examRoom) + examRooms = append(examRooms, &examRoom) + fmt.Println(aurora.Sprintf(aurora.Red(" adding NTA room %s for %s (%d minuntes)"), + aurora.Green(roomFound.Name), aurora.Green(nta.Name), aurora.Green(ntaDuration))) + + if ntaDuration > 100 { + roomsNotUsableInSlot.Add(roomFound.Name) + fmt.Println(aurora.Sprintf(aurora.Red(" room %s not usable in next slot!"), + aurora.Green(roomFound.Name))) + } + } + } + + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + } // for slot + + // err := p.dbClient.DropAndSave(context.WithValue(ctx, db.CollectionName("collectionName"), "rooms_for_exams"), examRooms) + // if err != nil { + // log.Error().Err(err).Msg("cannot save rooms for exams") + // return err + // } + + return p.dbClient.ReplaceNonNTARooms(ctx, examRooms) +} + +// FIXME: rewrite me +func (p *Plexams) GetRoomsForNTA(name string) error { + // ctx := context.Background() + // ntas, err := p.NtasWithRegs(ctx) + // if err != nil { + // return err + // } + // var nta *model.NTAWithRegs + // for _, ntaInDB := range ntas { + // if strings.HasPrefix(ntaInDB.Nta.Name, name) { + // nta = ntaInDB + // break + // } + // } + // if nta == nil { + // return fmt.Errorf("NTA with name=%s not found", name) + // } + // log.Debug().Str("name", nta.Nta.Name).Msg("found nta") + + // ANCODES: + // for _, ancode := range nta.Regs.Ancodes { + // exam, err := p.dbClient.GetZpaExamByAncode(ctx, ancode) + // if err != nil { + // log.Error().Err(err).Int("ancode", ancode).Msg("cannot get zpa exam") + // } + + // constraints, err := p.ConstraintForAncode(ctx, ancode) + // if err != nil { + // log.Error().Err(err).Int("ancode", ancode).Msg("cannot get constraints") + // } + // if constraints != nil && constraints.NotPlannedByMe { + // log.Debug().Int("ancode", ancode).Str("examer", exam.MainExamer).Str("module", exam.Module).Msg("exam not planned by me") + // continue + // } + // log.Debug().Int("ancode", ancode).Str("examer", exam.MainExamer).Str("module", exam.Module).Msg("found exam") + + // roomsForExam, err := p.dbClient.RoomsForAncode(ctx, ancode) + // if err != nil { + // log.Error().Err(err).Int("ancode", ancode).Msg("cannot get rooms") + // } + // for _, room := range roomsForExam { + // for _, stud := range room.Students { + // if nta.Nta.Mtknr == stud.Mtknr { + // fmt.Printf("%d. %s: %s --- Raum %s\n", ancode, exam.MainExamer, exam.Module, room.RoomName) + // continue ANCODES + // } + // } + // } + + // } + + return fmt.Errorf("rewrite me") +} From e5d273e75830271b335734488ca4524923c09374 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Tue, 26 Dec 2023 15:20:01 +0100 Subject: [PATCH 56/78] enhance planned room for GraphQL --- graph/generated/generated.go | 1165 +++------------------------------- graph/model/models_gen.go | 13 - graph/model/rooms.go | 2 +- graph/room.graphqls | 32 +- graph/room.resolvers.go | 32 +- plexams/rooms.go | 40 +- plexams/roomsPrepare.go | 48 +- 7 files changed, 175 insertions(+), 1157 deletions(-) diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 3560b57..4ae2b74 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -37,8 +37,8 @@ type Config struct { } type ResolverRoot interface { - EnhancedPlannedRoom() EnhancedPlannedRoomResolver Mutation() MutationResolver + PlannedRoom() PlannedRoomResolver Query() QueryResolver RoomForExam() RoomForExamResolver } @@ -103,22 +103,6 @@ type ComplexityRoot struct { SameSlot func(childComplexity int) int } - EnhancedPlannedRoom struct { - Ancode func(childComplexity int) int - Day func(childComplexity int) int - Duration func(childComplexity int) int - Exam func(childComplexity int) int - Handicap func(childComplexity int) int - HandicapRoomAlone func(childComplexity int) int - NtaInRoom func(childComplexity int) int - NtaMtknr func(childComplexity int) int - Reserve func(childComplexity int) int - Room func(childComplexity int) int - RoomName func(childComplexity int) int - Slot func(childComplexity int) int - StudentsInRoom func(childComplexity int) int - } - EnhancedPrimussExam struct { Conflicts func(childComplexity int) int Exam func(childComplexity int) int @@ -686,13 +670,6 @@ type ComplexityRoot struct { } } -type EnhancedPlannedRoomResolver interface { - Room(ctx context.Context, obj *model.EnhancedPlannedRoom) (*model.Room, error) - - Exam(ctx context.Context, obj *model.EnhancedPlannedRoom) (*model.GeneratedExam, error) - - NtaInRoom(ctx context.Context, obj *model.EnhancedPlannedRoom) (*model.NTA, error) -} type MutationResolver interface { SetSemester(ctx context.Context, input string) (*model.Semester, error) ZpaExamsToPlan(ctx context.Context, input []int) ([]*model.ZPAExam, error) @@ -716,6 +693,9 @@ type MutationResolver interface { AddExamToSlot(ctx context.Context, day int, time int, ancode int) (bool, error) RmExamFromSlot(ctx context.Context, ancode int) (bool, error) } +type PlannedRoomResolver interface { + Room(ctx context.Context, obj *model.PlannedRoom) (*model.Room, error) +} type QueryResolver interface { Workflow(ctx context.Context) ([]*model.Step, error) NextDeadline(ctx context.Context) (*model.Step, error) @@ -768,7 +748,7 @@ type QueryResolver interface { Rooms(ctx context.Context) ([]*model.Room, error) PlannedRoomNames(ctx context.Context) ([]string, error) PlannedRoomNamesInSlot(ctx context.Context, day int, time int) ([]string, error) - PlannedRoomsInSlot(ctx context.Context, day int, time int) ([]*model.EnhancedPlannedRoom, error) + PlannedRoomsInSlot(ctx context.Context, day int, time int) ([]*model.PlannedRoom, error) StudentByMtknr(ctx context.Context, mtknr string) (*model.Student, error) StudentsByName(ctx context.Context, regex string) ([]*model.Student, error) Students(ctx context.Context) ([]*model.Student, error) @@ -1028,97 +1008,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Constraints.SameSlot(childComplexity), true - case "EnhancedPlannedRoom.ancode": - if e.complexity.EnhancedPlannedRoom.Ancode == nil { - break - } - - return e.complexity.EnhancedPlannedRoom.Ancode(childComplexity), true - - case "EnhancedPlannedRoom.day": - if e.complexity.EnhancedPlannedRoom.Day == nil { - break - } - - return e.complexity.EnhancedPlannedRoom.Day(childComplexity), true - - case "EnhancedPlannedRoom.duration": - if e.complexity.EnhancedPlannedRoom.Duration == nil { - break - } - - return e.complexity.EnhancedPlannedRoom.Duration(childComplexity), true - - case "EnhancedPlannedRoom.exam": - if e.complexity.EnhancedPlannedRoom.Exam == nil { - break - } - - return e.complexity.EnhancedPlannedRoom.Exam(childComplexity), true - - case "EnhancedPlannedRoom.handicap": - if e.complexity.EnhancedPlannedRoom.Handicap == nil { - break - } - - return e.complexity.EnhancedPlannedRoom.Handicap(childComplexity), true - - case "EnhancedPlannedRoom.handicapRoomAlone": - if e.complexity.EnhancedPlannedRoom.HandicapRoomAlone == nil { - break - } - - return e.complexity.EnhancedPlannedRoom.HandicapRoomAlone(childComplexity), true - - case "EnhancedPlannedRoom.ntaInRoom": - if e.complexity.EnhancedPlannedRoom.NtaInRoom == nil { - break - } - - return e.complexity.EnhancedPlannedRoom.NtaInRoom(childComplexity), true - - case "EnhancedPlannedRoom.ntaMtknr": - if e.complexity.EnhancedPlannedRoom.NtaMtknr == nil { - break - } - - return e.complexity.EnhancedPlannedRoom.NtaMtknr(childComplexity), true - - case "EnhancedPlannedRoom.reserve": - if e.complexity.EnhancedPlannedRoom.Reserve == nil { - break - } - - return e.complexity.EnhancedPlannedRoom.Reserve(childComplexity), true - - case "EnhancedPlannedRoom.room": - if e.complexity.EnhancedPlannedRoom.Room == nil { - break - } - - return e.complexity.EnhancedPlannedRoom.Room(childComplexity), true - - case "EnhancedPlannedRoom.roomName": - if e.complexity.EnhancedPlannedRoom.RoomName == nil { - break - } - - return e.complexity.EnhancedPlannedRoom.RoomName(childComplexity), true - - case "EnhancedPlannedRoom.slot": - if e.complexity.EnhancedPlannedRoom.Slot == nil { - break - } - - return e.complexity.EnhancedPlannedRoom.Slot(childComplexity), true - - case "EnhancedPlannedRoom.studentsInRoom": - if e.complexity.EnhancedPlannedRoom.StudentsInRoom == nil { - break - } - - return e.complexity.EnhancedPlannedRoom.StudentsInRoom(childComplexity), true - case "EnhancedPrimussExam.conflicts": if e.complexity.EnhancedPrimussExam.Conflicts == nil { break @@ -4636,7 +4525,7 @@ type ConflictsPerProgramAncode { rooms: [Room!]! plannedRoomNames: [String!] plannedRoomNamesInSlot(day: Int!, time: Int!): [String!] - plannedRoomsInSlot(day: Int!, time: Int!): [EnhancedPlannedRoom!] + plannedRoomsInSlot(day: Int!, time: Int!): [PlannedRoom!] } type Room { @@ -4672,21 +4561,21 @@ type PlannedRoom { ntaMtknr: String } -type EnhancedPlannedRoom { - day: Int! - slot: Int! - roomName: String! - room: Room! - ancode: Int! - exam: GeneratedExam! - duration: Int! - handicap: Boolean! - handicapRoomAlone: Boolean! - reserve: Boolean! - studentsInRoom: [String!]! - ntaMtknr: String - ntaInRoom: NTA -} +# type EnhancedPlannedRoom { +# day: Int! +# slot: Int! +# roomName: String! +# room: Room! +# ancode: Int! +# exam: GeneratedExam! +# duration: Int! +# handicap: Boolean! +# handicapRoomAlone: Boolean! +# reserve: Boolean! +# studentsInRoom: [String!]! +# ntaMtknr: String +# ntaInRoom: NTA +# } # Deprecated: rm me type RoomForExam { @@ -7316,632 +7205,6 @@ func (ec *executionContext) fieldContext_Constraints_roomConstraints(ctx context return fc, nil } -func (ec *executionContext) _EnhancedPlannedRoom_day(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_EnhancedPlannedRoom_day(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Day, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int) - fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_EnhancedPlannedRoom_day(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "EnhancedPlannedRoom", - Field: field, - IsMethod: false, - IsResolver: false, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") - }, - } - return fc, nil -} - -func (ec *executionContext) _EnhancedPlannedRoom_slot(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_EnhancedPlannedRoom_slot(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Slot, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int) - fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_EnhancedPlannedRoom_slot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "EnhancedPlannedRoom", - Field: field, - IsMethod: false, - IsResolver: false, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") - }, - } - return fc, nil -} - -func (ec *executionContext) _EnhancedPlannedRoom_roomName(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_EnhancedPlannedRoom_roomName(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.RoomName, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(string) - fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_EnhancedPlannedRoom_roomName(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "EnhancedPlannedRoom", - Field: field, - IsMethod: false, - IsResolver: false, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") - }, - } - return fc, nil -} - -func (ec *executionContext) _EnhancedPlannedRoom_room(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_EnhancedPlannedRoom_room(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.EnhancedPlannedRoom().Room(rctx, obj) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(*model.Room) - fc.Result = res - return ec.marshalNRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoom(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_EnhancedPlannedRoom_room(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "EnhancedPlannedRoom", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "name": - return ec.fieldContext_Room_name(ctx, field) - case "seats": - return ec.fieldContext_Room_seats(ctx, field) - case "handicap": - return ec.fieldContext_Room_handicap(ctx, field) - case "lab": - return ec.fieldContext_Room_lab(ctx, field) - case "placesWithSocket": - return ec.fieldContext_Room_placesWithSocket(ctx, field) - case "needsRequest": - return ec.fieldContext_Room_needsRequest(ctx, field) - case "exahm": - return ec.fieldContext_Room_exahm(ctx, field) - case "seb": - return ec.fieldContext_Room_seb(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type Room", field.Name) - }, - } - return fc, nil -} - -func (ec *executionContext) _EnhancedPlannedRoom_ancode(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_EnhancedPlannedRoom_ancode(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Ancode, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int) - fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_EnhancedPlannedRoom_ancode(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "EnhancedPlannedRoom", - Field: field, - IsMethod: false, - IsResolver: false, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") - }, - } - return fc, nil -} - -func (ec *executionContext) _EnhancedPlannedRoom_exam(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_EnhancedPlannedRoom_exam(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.EnhancedPlannedRoom().Exam(rctx, obj) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(*model.GeneratedExam) - fc.Result = res - return ec.marshalNGeneratedExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExam(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_EnhancedPlannedRoom_exam(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "EnhancedPlannedRoom", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "ancode": - return ec.fieldContext_GeneratedExam_ancode(ctx, field) - case "zpaExam": - return ec.fieldContext_GeneratedExam_zpaExam(ctx, field) - case "primussExams": - return ec.fieldContext_GeneratedExam_primussExams(ctx, field) - case "constraints": - return ec.fieldContext_GeneratedExam_constraints(ctx, field) - case "conflicts": - return ec.fieldContext_GeneratedExam_conflicts(ctx, field) - case "studentRegsCount": - return ec.fieldContext_GeneratedExam_studentRegsCount(ctx, field) - case "ntas": - return ec.fieldContext_GeneratedExam_ntas(ctx, field) - case "maxDuration": - return ec.fieldContext_GeneratedExam_maxDuration(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type GeneratedExam", field.Name) - }, - } - return fc, nil -} - -func (ec *executionContext) _EnhancedPlannedRoom_duration(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_EnhancedPlannedRoom_duration(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Duration, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int) - fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_EnhancedPlannedRoom_duration(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "EnhancedPlannedRoom", - Field: field, - IsMethod: false, - IsResolver: false, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") - }, - } - return fc, nil -} - -func (ec *executionContext) _EnhancedPlannedRoom_handicap(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_EnhancedPlannedRoom_handicap(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Handicap, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(bool) - fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_EnhancedPlannedRoom_handicap(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "EnhancedPlannedRoom", - Field: field, - IsMethod: false, - IsResolver: false, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Boolean does not have child fields") - }, - } - return fc, nil -} - -func (ec *executionContext) _EnhancedPlannedRoom_handicapRoomAlone(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_EnhancedPlannedRoom_handicapRoomAlone(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.HandicapRoomAlone, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(bool) - fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_EnhancedPlannedRoom_handicapRoomAlone(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "EnhancedPlannedRoom", - Field: field, - IsMethod: false, - IsResolver: false, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Boolean does not have child fields") - }, - } - return fc, nil -} - -func (ec *executionContext) _EnhancedPlannedRoom_reserve(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_EnhancedPlannedRoom_reserve(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Reserve, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(bool) - fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_EnhancedPlannedRoom_reserve(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "EnhancedPlannedRoom", - Field: field, - IsMethod: false, - IsResolver: false, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Boolean does not have child fields") - }, - } - return fc, nil -} - -func (ec *executionContext) _EnhancedPlannedRoom_studentsInRoom(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_EnhancedPlannedRoom_studentsInRoom(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.StudentsInRoom, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.([]string) - fc.Result = res - return ec.marshalNString2ᚕstringᚄ(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_EnhancedPlannedRoom_studentsInRoom(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "EnhancedPlannedRoom", - Field: field, - IsMethod: false, - IsResolver: false, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") - }, - } - return fc, nil -} - -func (ec *executionContext) _EnhancedPlannedRoom_ntaMtknr(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_EnhancedPlannedRoom_ntaMtknr(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.NtaMtknr, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.(*string) - fc.Result = res - return ec.marshalOString2ᚖstring(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_EnhancedPlannedRoom_ntaMtknr(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "EnhancedPlannedRoom", - Field: field, - IsMethod: false, - IsResolver: false, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") - }, - } - return fc, nil -} - -func (ec *executionContext) _EnhancedPlannedRoom_ntaInRoom(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPlannedRoom) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_EnhancedPlannedRoom_ntaInRoom(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.EnhancedPlannedRoom().NtaInRoom(rctx, obj) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.(*model.NTA) - fc.Result = res - return ec.marshalONTA2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐNTA(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_EnhancedPlannedRoom_ntaInRoom(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "EnhancedPlannedRoom", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "name": - return ec.fieldContext_NTA_name(ctx, field) - case "email": - return ec.fieldContext_NTA_email(ctx, field) - case "mtknr": - return ec.fieldContext_NTA_mtknr(ctx, field) - case "compensation": - return ec.fieldContext_NTA_compensation(ctx, field) - case "deltaDurationPercent": - return ec.fieldContext_NTA_deltaDurationPercent(ctx, field) - case "needsRoomAlone": - return ec.fieldContext_NTA_needsRoomAlone(ctx, field) - case "program": - return ec.fieldContext_NTA_program(ctx, field) - case "from": - return ec.fieldContext_NTA_from(ctx, field) - case "until": - return ec.fieldContext_NTA_until(ctx, field) - case "lastSemester": - return ec.fieldContext_NTA_lastSemester(ctx, field) - case "exams": - return ec.fieldContext_NTA_exams(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type NTA", field.Name) - }, - } - return fc, nil -} - func (ec *executionContext) _EnhancedPrimussExam_exam(ctx context.Context, field graphql.CollectedField, obj *model.EnhancedPrimussExam) (ret graphql.Marshaler) { fc, err := ec.fieldContext_EnhancedPrimussExam_exam(ctx, field) if err != nil { @@ -16581,7 +15844,7 @@ func (ec *executionContext) _PlannedRoom_room(ctx context.Context, field graphql }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Room, nil + return ec.resolvers.PlannedRoom().Room(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -16602,8 +15865,8 @@ func (ec *executionContext) fieldContext_PlannedRoom_room(ctx context.Context, f fc = &graphql.FieldContext{ Object: "PlannedRoom", Field: field, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { case "name": @@ -20745,9 +20008,9 @@ func (ec *executionContext) _Query_plannedRoomsInSlot(ctx context.Context, field if resTmp == nil { return graphql.Null } - res := resTmp.([]*model.EnhancedPlannedRoom) + res := resTmp.([]*model.PlannedRoom) fc.Result = res - return ec.marshalOEnhancedPlannedRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPlannedRoomᚄ(ctx, field.Selections, res) + return ec.marshalOPlannedRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedRoomᚄ(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Query_plannedRoomsInSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -20759,33 +20022,27 @@ func (ec *executionContext) fieldContext_Query_plannedRoomsInSlot(ctx context.Co Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { case "day": - return ec.fieldContext_EnhancedPlannedRoom_day(ctx, field) + return ec.fieldContext_PlannedRoom_day(ctx, field) case "slot": - return ec.fieldContext_EnhancedPlannedRoom_slot(ctx, field) - case "roomName": - return ec.fieldContext_EnhancedPlannedRoom_roomName(ctx, field) + return ec.fieldContext_PlannedRoom_slot(ctx, field) case "room": - return ec.fieldContext_EnhancedPlannedRoom_room(ctx, field) + return ec.fieldContext_PlannedRoom_room(ctx, field) case "ancode": - return ec.fieldContext_EnhancedPlannedRoom_ancode(ctx, field) - case "exam": - return ec.fieldContext_EnhancedPlannedRoom_exam(ctx, field) + return ec.fieldContext_PlannedRoom_ancode(ctx, field) case "duration": - return ec.fieldContext_EnhancedPlannedRoom_duration(ctx, field) + return ec.fieldContext_PlannedRoom_duration(ctx, field) case "handicap": - return ec.fieldContext_EnhancedPlannedRoom_handicap(ctx, field) + return ec.fieldContext_PlannedRoom_handicap(ctx, field) case "handicapRoomAlone": - return ec.fieldContext_EnhancedPlannedRoom_handicapRoomAlone(ctx, field) + return ec.fieldContext_PlannedRoom_handicapRoomAlone(ctx, field) case "reserve": - return ec.fieldContext_EnhancedPlannedRoom_reserve(ctx, field) + return ec.fieldContext_PlannedRoom_reserve(ctx, field) case "studentsInRoom": - return ec.fieldContext_EnhancedPlannedRoom_studentsInRoom(ctx, field) + return ec.fieldContext_PlannedRoom_studentsInRoom(ctx, field) case "ntaMtknr": - return ec.fieldContext_EnhancedPlannedRoom_ntaMtknr(ctx, field) - case "ntaInRoom": - return ec.fieldContext_EnhancedPlannedRoom_ntaInRoom(ctx, field) + return ec.fieldContext_PlannedRoom_ntaMtknr(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type EnhancedPlannedRoom", field.Name) + return nil, fmt.Errorf("no field named %q was found under type PlannedRoom", field.Name) }, } defer func() { @@ -29576,230 +28833,44 @@ func (ec *executionContext) _ConnectedExam(ctx context.Context, sel ast.Selectio return out } -var constraintsImplementors = []string{"Constraints"} - -func (ec *executionContext) _Constraints(ctx context.Context, sel ast.SelectionSet, obj *model.Constraints) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, constraintsImplementors) - - out := graphql.NewFieldSet(fields) - deferred := make(map[string]*graphql.FieldSet) - for i, field := range fields { - switch field.Name { - case "__typename": - out.Values[i] = graphql.MarshalString("Constraints") - case "ancode": - out.Values[i] = ec._Constraints_ancode(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "notPlannedByMe": - out.Values[i] = ec._Constraints_notPlannedByMe(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "excludeDays": - out.Values[i] = ec._Constraints_excludeDays(ctx, field, obj) - case "possibleDays": - out.Values[i] = ec._Constraints_possibleDays(ctx, field, obj) - case "fixedDay": - out.Values[i] = ec._Constraints_fixedDay(ctx, field, obj) - case "fixedTime": - out.Values[i] = ec._Constraints_fixedTime(ctx, field, obj) - case "sameSlot": - out.Values[i] = ec._Constraints_sameSlot(ctx, field, obj) - case "online": - out.Values[i] = ec._Constraints_online(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } - case "roomConstraints": - out.Values[i] = ec._Constraints_roomConstraints(ctx, field, obj) - default: - panic("unknown field " + strconv.Quote(field.Name)) - } - } - out.Dispatch(ctx) - if out.Invalids > 0 { - return graphql.Null - } - - atomic.AddInt32(&ec.deferred, int32(len(deferred))) - - for label, dfs := range deferred { - ec.processDeferredGroup(graphql.DeferredGroup{ - Label: label, - Path: graphql.GetPath(ctx), - FieldSet: dfs, - Context: ctx, - }) - } - - return out -} - -var enhancedPlannedRoomImplementors = []string{"EnhancedPlannedRoom"} +var constraintsImplementors = []string{"Constraints"} -func (ec *executionContext) _EnhancedPlannedRoom(ctx context.Context, sel ast.SelectionSet, obj *model.EnhancedPlannedRoom) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, enhancedPlannedRoomImplementors) +func (ec *executionContext) _Constraints(ctx context.Context, sel ast.SelectionSet, obj *model.Constraints) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, constraintsImplementors) out := graphql.NewFieldSet(fields) deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("EnhancedPlannedRoom") - case "day": - out.Values[i] = ec._EnhancedPlannedRoom_day(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) - } - case "slot": - out.Values[i] = ec._EnhancedPlannedRoom_slot(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) - } - case "roomName": - out.Values[i] = ec._EnhancedPlannedRoom_roomName(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) - } - case "room": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._EnhancedPlannedRoom_room(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } - return res - } - - if field.Deferrable != nil { - dfs, ok := deferred[field.Deferrable.Label] - di := 0 - if ok { - dfs.AddField(field) - di = len(dfs.Values) - 1 - } else { - dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) - deferred[field.Deferrable.Label] = dfs - } - dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { - return innerFunc(ctx, dfs) - }) - - // don't run the out.Concurrently() call below - out.Values[i] = graphql.Null - continue - } - - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + out.Values[i] = graphql.MarshalString("Constraints") case "ancode": - out.Values[i] = ec._EnhancedPlannedRoom_ancode(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) - } - case "exam": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._EnhancedPlannedRoom_exam(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } - return res - } - - if field.Deferrable != nil { - dfs, ok := deferred[field.Deferrable.Label] - di := 0 - if ok { - dfs.AddField(field) - di = len(dfs.Values) - 1 - } else { - dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) - deferred[field.Deferrable.Label] = dfs - } - dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { - return innerFunc(ctx, dfs) - }) - - // don't run the out.Concurrently() call below - out.Values[i] = graphql.Null - continue - } - - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - case "duration": - out.Values[i] = ec._EnhancedPlannedRoom_duration(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) - } - case "handicap": - out.Values[i] = ec._EnhancedPlannedRoom_handicap(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) - } - case "handicapRoomAlone": - out.Values[i] = ec._EnhancedPlannedRoom_handicapRoomAlone(ctx, field, obj) + out.Values[i] = ec._Constraints_ancode(ctx, field, obj) if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) + out.Invalids++ } - case "reserve": - out.Values[i] = ec._EnhancedPlannedRoom_reserve(ctx, field, obj) + case "notPlannedByMe": + out.Values[i] = ec._Constraints_notPlannedByMe(ctx, field, obj) if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) + out.Invalids++ } - case "studentsInRoom": - out.Values[i] = ec._EnhancedPlannedRoom_studentsInRoom(ctx, field, obj) + case "excludeDays": + out.Values[i] = ec._Constraints_excludeDays(ctx, field, obj) + case "possibleDays": + out.Values[i] = ec._Constraints_possibleDays(ctx, field, obj) + case "fixedDay": + out.Values[i] = ec._Constraints_fixedDay(ctx, field, obj) + case "fixedTime": + out.Values[i] = ec._Constraints_fixedTime(ctx, field, obj) + case "sameSlot": + out.Values[i] = ec._Constraints_sameSlot(ctx, field, obj) + case "online": + out.Values[i] = ec._Constraints_online(ctx, field, obj) if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) - } - case "ntaMtknr": - out.Values[i] = ec._EnhancedPlannedRoom_ntaMtknr(ctx, field, obj) - case "ntaInRoom": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._EnhancedPlannedRoom_ntaInRoom(ctx, field, obj) - return res - } - - if field.Deferrable != nil { - dfs, ok := deferred[field.Deferrable.Label] - di := 0 - if ok { - dfs.AddField(field) - di = len(dfs.Values) - 1 - } else { - dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) - deferred[field.Deferrable.Label] = dfs - } - dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { - return innerFunc(ctx, dfs) - }) - - // don't run the out.Concurrently() call below - out.Values[i] = graphql.Null - continue + out.Invalids++ } - - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "roomConstraints": + out.Values[i] = ec._Constraints_roomConstraints(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -31667,47 +30738,78 @@ func (ec *executionContext) _PlannedRoom(ctx context.Context, sel ast.SelectionS case "day": out.Values[i] = ec._PlannedRoom_day(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "slot": out.Values[i] = ec._PlannedRoom_slot(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "room": - out.Values[i] = ec._PlannedRoom_room(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._PlannedRoom_room(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) case "ancode": out.Values[i] = ec._PlannedRoom_ancode(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "duration": out.Values[i] = ec._PlannedRoom_duration(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "handicap": out.Values[i] = ec._PlannedRoom_handicap(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "handicapRoomAlone": out.Values[i] = ec._PlannedRoom_handicapRoomAlone(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "reserve": out.Values[i] = ec._PlannedRoom_reserve(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "studentsInRoom": out.Values[i] = ec._PlannedRoom_studentsInRoom(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "ntaMtknr": out.Values[i] = ec._PlannedRoom_ntaMtknr(ctx, field, obj) @@ -35469,16 +34571,6 @@ func (ec *executionContext) marshalNConnectedExam2ᚖgithubᚗcomᚋobcodeᚋple return ec._ConnectedExam(ctx, sel, v) } -func (ec *executionContext) marshalNEnhancedPlannedRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPlannedRoom(ctx context.Context, sel ast.SelectionSet, v *model.EnhancedPlannedRoom) graphql.Marshaler { - if v == nil { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - return graphql.Null - } - return ec._EnhancedPlannedRoom(ctx, sel, v) -} - func (ec *executionContext) marshalNEnhancedPrimussExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPrimussExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.EnhancedPrimussExam) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup @@ -35912,10 +35004,6 @@ func (ec *executionContext) marshalNFloat2float64(ctx context.Context, sel ast.S return graphql.WrapContextMarshaler(ctx, res) } -func (ec *executionContext) marshalNGeneratedExam2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExam(ctx context.Context, sel ast.SelectionSet, v model.GeneratedExam) graphql.Marshaler { - return ec._GeneratedExam(ctx, sel, &v) -} - func (ec *executionContext) marshalNGeneratedExam2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐGeneratedExamᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.GeneratedExam) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup @@ -38045,53 +37133,6 @@ func (ec *executionContext) marshalOConstraints2ᚖgithubᚗcomᚋobcodeᚋplexa return ec._Constraints(ctx, sel, v) } -func (ec *executionContext) marshalOEnhancedPlannedRoom2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPlannedRoomᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.EnhancedPlannedRoom) graphql.Marshaler { - if v == nil { - return graphql.Null - } - ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } - for i := range v { - i := i - fc := &graphql.FieldContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithFieldContext(ctx, fc) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalNEnhancedPlannedRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐEnhancedPlannedRoom(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - - } - wg.Wait() - - for _, e := range ret { - if e == graphql.Null { - return graphql.Null - } - } - - return ret -} - func (ec *executionContext) marshalOExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐExam(ctx context.Context, sel ast.SelectionSet, v *model.Exam) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index f8cd943..18ef7d6 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -287,19 +287,6 @@ type PlannedExamWithNta struct { Nta []*NTAWithRegs `json:"nta,omitempty"` } -type PlannedRoom struct { - Day int `json:"day"` - Slot int `json:"slot"` - Room *Room `json:"room"` - Ancode int `json:"ancode"` - Duration int `json:"duration"` - Handicap bool `json:"handicap"` - HandicapRoomAlone bool `json:"handicapRoomAlone"` - Reserve bool `json:"reserve"` - StudentsInRoom []string `json:"studentsInRoom"` - NtaMtknr *string `json:"ntaMtknr,omitempty"` -} - type PrimussExamAncode struct { Ancode int `json:"ancode"` Program string `json:"program"` diff --git a/graph/model/rooms.go b/graph/model/rooms.go index d08a1b4..1961b14 100644 --- a/graph/model/rooms.go +++ b/graph/model/rooms.go @@ -10,7 +10,7 @@ type RoomForExam struct { Students []*StudentReg `json:"students"` } -type EnhancedPlannedRoom struct { +type PlannedRoom struct { Day int `json:"day"` Slot int `json:"slot"` RoomName string `json:"roomName"` diff --git a/graph/room.graphqls b/graph/room.graphqls index 7a0dc8f..28ac6bb 100644 --- a/graph/room.graphqls +++ b/graph/room.graphqls @@ -2,7 +2,7 @@ extend type Query { rooms: [Room!]! plannedRoomNames: [String!] plannedRoomNamesInSlot(day: Int!, time: Int!): [String!] - plannedRoomsInSlot(day: Int!, time: Int!): [EnhancedPlannedRoom!] + plannedRoomsInSlot(day: Int!, time: Int!): [PlannedRoom!] } type Room { @@ -38,21 +38,21 @@ type PlannedRoom { ntaMtknr: String } -type EnhancedPlannedRoom { - day: Int! - slot: Int! - roomName: String! - room: Room! - ancode: Int! - exam: GeneratedExam! - duration: Int! - handicap: Boolean! - handicapRoomAlone: Boolean! - reserve: Boolean! - studentsInRoom: [String!]! - ntaMtknr: String - ntaInRoom: NTA -} +# type EnhancedPlannedRoom { +# day: Int! +# slot: Int! +# roomName: String! +# room: Room! +# ancode: Int! +# exam: GeneratedExam! +# duration: Int! +# handicap: Boolean! +# handicapRoomAlone: Boolean! +# reserve: Boolean! +# studentsInRoom: [String!]! +# ntaMtknr: String +# ntaInRoom: NTA +# } # Deprecated: rm me type RoomForExam { diff --git a/graph/room.resolvers.go b/graph/room.resolvers.go index 084cb09..c9af92a 100644 --- a/graph/room.resolvers.go +++ b/graph/room.resolvers.go @@ -6,36 +6,16 @@ package graph import ( "context" - "fmt" "github.com/obcode/plexams.go/graph/generated" "github.com/obcode/plexams.go/graph/model" ) // Room is the resolver for the room field. -func (r *enhancedPlannedRoomResolver) Room(ctx context.Context, obj *model.EnhancedPlannedRoom) (*model.Room, error) { - if obj == nil { - return nil, fmt.Errorf("error enhanced planned room not available") - } +func (r *plannedRoomResolver) Room(ctx context.Context, obj *model.PlannedRoom) (*model.Room, error) { return r.plexams.RoomFromName(ctx, obj.RoomName) } -// Exam is the resolver for the exam field. -func (r *enhancedPlannedRoomResolver) Exam(ctx context.Context, obj *model.EnhancedPlannedRoom) (*model.GeneratedExam, error) { - if obj == nil { - return nil, fmt.Errorf("error enhanced planned room not available") - } - return r.plexams.GeneratedExam(ctx, obj.Ancode) -} - -// NtaInRoom is the resolver for the ntaInRoom field. -func (r *enhancedPlannedRoomResolver) NtaInRoom(ctx context.Context, obj *model.EnhancedPlannedRoom) (*model.NTA, error) { - if obj == nil { - return nil, fmt.Errorf("error enhanced planned room not available") - } - return r.plexams.NtaByMtknr(ctx, *obj.NtaMtknr) -} - // Rooms is the resolver for the rooms field. func (r *queryResolver) Rooms(ctx context.Context) ([]*model.Room, error) { return r.plexams.Rooms(ctx) @@ -52,7 +32,7 @@ func (r *queryResolver) PlannedRoomNamesInSlot(ctx context.Context, day int, tim } // PlannedRoomsInSlot is the resolver for the plannedRoomsInSlot field. -func (r *queryResolver) PlannedRoomsInSlot(ctx context.Context, day int, time int) ([]*model.EnhancedPlannedRoom, error) { +func (r *queryResolver) PlannedRoomsInSlot(ctx context.Context, day int, time int) ([]*model.PlannedRoom, error) { return r.plexams.PlannedRoomsInSlot(ctx, day, time) } @@ -61,13 +41,11 @@ func (r *roomForExamResolver) Room(ctx context.Context, obj *model.RoomForExam) return r.plexams.Room(ctx, obj) } -// EnhancedPlannedRoom returns generated.EnhancedPlannedRoomResolver implementation. -func (r *Resolver) EnhancedPlannedRoom() generated.EnhancedPlannedRoomResolver { - return &enhancedPlannedRoomResolver{r} -} +// PlannedRoom returns generated.PlannedRoomResolver implementation. +func (r *Resolver) PlannedRoom() generated.PlannedRoomResolver { return &plannedRoomResolver{r} } // RoomForExam returns generated.RoomForExamResolver implementation. func (r *Resolver) RoomForExam() generated.RoomForExamResolver { return &roomForExamResolver{r} } -type enhancedPlannedRoomResolver struct{ *Resolver } +type plannedRoomResolver struct{ *Resolver } type roomForExamResolver struct{ *Resolver } diff --git a/plexams/rooms.go b/plexams/rooms.go index ff0eadb..ee84dbc 100644 --- a/plexams/rooms.go +++ b/plexams/rooms.go @@ -443,33 +443,33 @@ func (p *Plexams) PlannedRoomNames(ctx context.Context) ([]string, error) { } // TODO: rewrite me -func (p *Plexams) PlannedRoomsInSlot(ctx context.Context, day int, time int) ([]*model.EnhancedPlannedRoom, error) { +func (p *Plexams) PlannedRoomsInSlot(ctx context.Context, day int, time int) ([]*model.PlannedRoom, error) { rooms, err := p.dbClient.PlannedRoomsInSlot(ctx, day, time) if err != nil { log.Error().Err(err).Int("day", day).Int("time", time).Msg("cannot get exams in slot") } - return enhancePlannedRooms(rooms), nil + return rooms, nil } -func enhancePlannedRooms(plannedRooms []*model.PlannedRoom) []*model.EnhancedPlannedRoom { - enhancedPlannedRooms := make([]*model.EnhancedPlannedRoom, 0, len(plannedRooms)) - for _, room := range plannedRooms { - enhancedPlannedRooms = append(enhancedPlannedRooms, &model.EnhancedPlannedRoom{ - Day: room.Day, - Slot: room.Ancode, - RoomName: room.Room.Name, - Ancode: room.Ancode, - Duration: room.Duration, - Handicap: room.Handicap, - HandicapRoomAlone: room.HandicapRoomAlone, - Reserve: room.Reserve, - StudentsInRoom: room.StudentsInRoom, - NtaMtknr: room.NtaMtknr, - }) - } - return enhancedPlannedRooms -} +// func enhancePlannedRooms(plannedRooms []*model.PlannedRoom) []*model.EnhancedPlannedRoom { +// enhancedPlannedRooms := make([]*model.EnhancedPlannedRoom, 0, len(plannedRooms)) +// for _, room := range plannedRooms { +// enhancedPlannedRooms = append(enhancedPlannedRooms, &model.EnhancedPlannedRoom{ +// Day: room.Day, +// Slot: room.Ancode, +// RoomName: room.RoomName, +// Ancode: room.Ancode, +// Duration: room.Duration, +// Handicap: room.Handicap, +// HandicapRoomAlone: room.HandicapRoomAlone, +// Reserve: room.Reserve, +// StudentsInRoom: room.StudentsInRoom, +// NtaMtknr: room.NtaMtknr, +// }) +// } +// return enhancedPlannedRooms +// } func (p *Plexams) PlannedRoomNamesInSlot(ctx context.Context, day int, time int) ([]string, error) { return p.dbClient.PlannedRoomNamesInSlot(ctx, day, time) diff --git a/plexams/roomsPrepare.go b/plexams/roomsPrepare.go index 767a64f..ec7404b 100644 --- a/plexams/roomsPrepare.go +++ b/plexams/roomsPrepare.go @@ -180,7 +180,7 @@ func (p *Plexams) RoomsForNTAsWithRoomAlone() error { plannedRooms = append(plannedRooms, &model.PlannedRoom{ Day: day, Slot: slot, - Room: room, + RoomName: room.Name, Ancode: slotEntry.ancode, Duration: ntaDuration, Handicap: true, @@ -207,7 +207,7 @@ func (p *Plexams) RoomsForNTAsWithRoomAlone() error { exam := examsMap[plannedRoom.Ancode] fmt.Println(aurora.Sprintf(aurora.Cyan("(%d/%d) %d. %s (%s), Raum %s für %s (%d Minuten)"), plannedRoom.Day, plannedRoom.Slot, exam.Ancode, aurora.Blue(exam.ZpaExam.Module), exam.ZpaExam.MainExamer, - aurora.Magenta(plannedRoom.Room.Name), aurora.Green(ntasMap[*plannedRoom.NtaMtknr].Name), aurora.Green(plannedRoom.Duration), + aurora.Magenta(plannedRoom.RoomName), aurora.Green(ntasMap[*plannedRoom.NtaMtknr].Name), aurora.Green(plannedRoom.Duration), )) } return p.dbClient.ReplaceRoomsForNTA(ctx, plannedRooms) @@ -238,6 +238,17 @@ func (p *Plexams) PrepareRoomForExams() error { log.Debug().Interface("additionalSeats", additionalSeats).Msg("found additional seats") + allRooms, err := p.dbClient.Rooms(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get global rooms") + return err + } + + roomInfo := make(map[string]*model.Room) + for _, room := range allRooms { + roomInfo[room.Name] = room + } + // only if room is needed more than 100 Minutes roomsNotUsableInSlot := set.NewSet[string]() @@ -450,12 +461,13 @@ func (p *Plexams) PrepareRoomForExams() error { continue } for _, room := range plannedRoomWithFreeSeats.rooms { + roomInfo := roomInfo[room.RoomName] otherExam := examsMap[room.Ancode] if exam.Exam.Constraints != nil && exam.Exam.Constraints.RoomConstraints != nil { - if exam.Exam.Constraints.RoomConstraints.ExahmRooms && !room.Room.Exahm || - exam.Exam.Constraints.RoomConstraints.Lab && !room.Room.Lab || - exam.Exam.Constraints.RoomConstraints.PlacesWithSocket && !room.Room.PlacesWithSocket || - exam.Exam.Constraints.RoomConstraints.Seb && !room.Room.Seb { + if exam.Exam.Constraints.RoomConstraints.ExahmRooms && !roomInfo.Exahm || + exam.Exam.Constraints.RoomConstraints.Lab && !roomInfo.Lab || + exam.Exam.Constraints.RoomConstraints.PlacesWithSocket && !roomInfo.PlacesWithSocket || + exam.Exam.Constraints.RoomConstraints.Seb && !roomInfo.Seb { continue OUTER } } @@ -465,14 +477,14 @@ func (p *Plexams) PrepareRoomForExams() error { if exam.Exam.ZpaExam.MainExamerID == otherExam.ZpaExam.MainExamerID { roomFound = &RoomWithSeatsLeft{ - room: room.Room, + room: roomInfo, seatsLeft: plannedRoomWithFreeSeats.freeSeats - neededSeats, } break OUTER } if exam.Exam.ZpaExam.Module == otherExam.ZpaExam.Module { roomFound = &RoomWithSeatsLeft{ - room: room.Room, + room: roomInfo, seatsLeft: plannedRoomWithFreeSeats.freeSeats - neededSeats, } break OUTER @@ -480,7 +492,7 @@ func (p *Plexams) PrepareRoomForExams() error { if roomFound == nil || roomFound.seatsLeft < seatsLeft { roomFound = &RoomWithSeatsLeft{ - room: room.Room, + room: roomInfo, seatsLeft: seatsLeft, } } @@ -562,7 +574,7 @@ func (p *Plexams) PrepareRoomForExams() error { examRoom := model.PlannedRoom{ Day: slot.DayNumber, Slot: slot.SlotNumber, - Room: room, + RoomName: room.Name, Ancode: exam.Exam.Ancode, Duration: exam.Exam.ZpaExam.Duration, Handicap: false, @@ -578,21 +590,21 @@ func (p *Plexams) PrepareRoomForExams() error { exams = append(exams, exam) // for _, plannedRoom := range exam.Rooms { - plannedRoomWithFreeSeats, ok := plannedRoomsWithFreeSeats[examRoom.Room.Name] + plannedRoomWithFreeSeats, ok := plannedRoomsWithFreeSeats[examRoom.RoomName] if !ok { plannedRoomWithFreeSeats = PlannedRoomsWithFreeSeats{ rooms: make([]*model.PlannedRoom, 0, 1), - freeSeats: examRoom.Room.Seats, + freeSeats: roomInfo[examRoom.RoomName].Seats, } } - plannedRoomsWithFreeSeats[examRoom.Room.Name] = PlannedRoomsWithFreeSeats{ + plannedRoomsWithFreeSeats[examRoom.RoomName] = PlannedRoomsWithFreeSeats{ rooms: append(plannedRoomWithFreeSeats.rooms, &examRoom), freeSeats: plannedRoomWithFreeSeats.freeSeats - (len(examRoom.StudentsInRoom) + len(exam.Ntas)), } // } spinner.StopMessage(aurora.Sprintf(aurora.Green("added %s for %d students (max. %d)"), - examRoom.Room.Name, len(examRoom.StudentsInRoom), room.Seats)) + examRoom.RoomName, len(examRoom.StudentsInRoom), room.Seats)) err = spinner.Stop() if err != nil { log.Debug().Err(err).Msg("cannot stop spinner") @@ -612,12 +624,12 @@ func (p *Plexams) PrepareRoomForExams() error { // find room with a seat left var roomFound *model.Room for _, room := range exam.Rooms { - if maxDuration > 100 && (room.Room.Name == "R1.046" || room.Room.Name == "R1.049") { + if maxDuration > 100 && (room.RoomName == "R1.046" || room.RoomName == "R1.049") { continue } - if room.Room.Seats >= len(room.StudentsInRoom)+len(exam.Ntas) { - roomFound = room.Room + if roomInfo[room.RoomName].Seats >= len(room.StudentsInRoom)+len(exam.Ntas) { + roomFound = roomInfo[room.RoomName] break } } @@ -672,7 +684,7 @@ func (p *Plexams) PrepareRoomForExams() error { examRoom := model.PlannedRoom{ Day: slot.DayNumber, Slot: slot.SlotNumber, - Room: roomFound, + RoomName: roomFound.Name, Ancode: exam.Exam.Ancode, Duration: ntaDuration, Handicap: true, From 5d53f76295d36ff1dd1ec5edcda298b855439397 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Tue, 26 Dec 2023 21:12:52 +0100 Subject: [PATCH 57/78] room validation adapted --- plexams/plannedExams.go | 6 + plexams/validate_rooms.go | 310 +++++++++++++++++++++++++------------- 2 files changed, 213 insertions(+), 103 deletions(-) diff --git a/plexams/plannedExams.go b/plexams/plannedExams.go index bc91cb9..c980854 100644 --- a/plexams/plannedExams.go +++ b/plexams/plannedExams.go @@ -66,6 +66,11 @@ func (p *Plexams) PlannedExams(ctx context.Context) ([]*model.PlannedExam, error plannedExams := make([]*model.PlannedExam, 0, len(exams)) for _, exam := range exams { + plannedRooms, err := p.dbClient.PlannedRoomsForAncode(ctx, exam.Ancode) + if err != nil { + log.Error().Err(err).Int("ancode", exam.Ancode).Msg("cannot find planned rooms") + } + plannedExams = append(plannedExams, &model.PlannedExam{ Ancode: exam.Ancode, @@ -77,6 +82,7 @@ func (p *Plexams) PlannedExams(ctx context.Context) ([]*model.PlannedExam, error Ntas: exam.Ntas, MaxDuration: exam.MaxDuration, PlanEntry: planEntryMap[exam.Ancode], + PlannedRooms: plannedRooms, }) } diff --git a/plexams/validate_rooms.go b/plexams/validate_rooms.go index 7d552ce..e8fb589 100644 --- a/plexams/validate_rooms.go +++ b/plexams/validate_rooms.go @@ -2,34 +2,63 @@ package plexams import ( "context" - "math" + "fmt" "strings" "time" set "github.com/deckarep/golang-set/v2" - "github.com/gookit/color" + "github.com/logrusorgru/aurora" "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" "github.com/spf13/viper" + "github.com/theckman/yacspin" ) func (p *Plexams) ValidateRoomsPerSlot() error { ctx := context.Background() - color.Style{color.FgRed, color.BgGreen, color.OpBold}.Println(" --- validating rooms per slot --- ") + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Cyan(" validating rooms per slot (allowed and enough seats)")), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + validationMessages := make([]string, 0) slots := p.semesterConfig.Slots for _, slot := range slots { - plannedRooms, err := p.dbClient.RoomsPlannedInSlot(ctx, slot.DayNumber, slot.SlotNumber) + + plannedExams, err := p.dbClient.GetExamsInSlot(ctx, slot.DayNumber, slot.SlotNumber) if err != nil { log.Error().Err(err). Int("day", slot.DayNumber). Int("time", slot.SlotNumber). - Msg("error while getting rooms planned in slot") + Msg("error while getting exams planned in slot") return err } - // color.Style{color.FgRed, color.BgGreen, color.OpBold}.Println(" --- check if planned rooms are allowed in slot ") + plannedRooms := make([]*model.PlannedRoom, 0) + for _, plannedExam := range plannedExams { + plannedRooms = append(plannedRooms, plannedExam.PlannedRooms...) + } + + spinner.Message(aurora.Sprintf(aurora.Yellow("checking slot (%d/%d) with %d rooms in %d exams"), + slot.DayNumber, slot.SlotNumber, len(plannedRooms), len(plannedExams))) allowedRooms, err := p.RoomsForSlot(ctx, slot.DayNumber, slot.SlotNumber) if err != nil { @@ -46,8 +75,14 @@ func (p *Plexams) ValidateRoomsPerSlot() error { allowedRooms.NtaRooms...)...)...) for _, plannedRoom := range plannedRooms { - if plannedRoom.RoomName == "ONLINE" || plannedRoom.RoomName == "No Room" { - break + if plannedRoom.RoomName == "ONLINE" { + continue + } + + if plannedRoom.RoomName == "No Room" { + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("No Room for %d students in slot (%d/%d)"), + aurora.Magenta(len(plannedRoom.StudentsInRoom)), aurora.Blue(slot.DayNumber), aurora.Blue(slot.SlotNumber))) + continue } isAllowed := false @@ -58,12 +93,11 @@ func (p *Plexams) ValidateRoomsPerSlot() error { } } if !isAllowed { - color.Red.Printf("Room %s is not allowed in slot (%d,%d)\n", plannedRoom.RoomName, slot.DayNumber, slot.SlotNumber) + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("Room %s is not allowed in slot (%d/%d)"), + aurora.Magenta(plannedRoom.RoomName), aurora.Blue(slot.DayNumber), aurora.Blue(slot.SlotNumber))) } } - // color.Style{color.FgRed, color.BgGreen, color.OpBold}.Println(" --- check if seatsPlanned <= seats ") - type roomSeats struct { seatsPlanned, seats int } @@ -78,94 +112,144 @@ func (p *Plexams) ValidateRoomsPerSlot() error { } if !ok { - seats[plannedRoom.RoomName] = roomSeats{seatsPlanned: plannedRoom.SeatsPlanned, seats: p.GetRoomInfo(plannedRoom.RoomName).Seats} + seats[plannedRoom.RoomName] = roomSeats{seatsPlanned: len(plannedRoom.StudentsInRoom), seats: p.GetRoomInfo(plannedRoom.RoomName).Seats} } else { - seats[plannedRoom.RoomName] = roomSeats{seatsPlanned: plannedRoom.SeatsPlanned + entry.seatsPlanned, seats: p.GetRoomInfo(plannedRoom.RoomName).Seats} + seats[plannedRoom.RoomName] = roomSeats{seatsPlanned: len(plannedRoom.StudentsInRoom) + entry.seatsPlanned, seats: p.GetRoomInfo(plannedRoom.RoomName).Seats} } } for roomName, roomSeats := range seats { if roomSeats.seatsPlanned > roomSeats.seats { - color.Red.Printf("Room %s is overbooked in slot (%d, %d): %d seats planned, but only %d available \n", - roomName, slot.DayNumber, slot.SlotNumber, roomSeats.seatsPlanned, roomSeats.seats) + validationMessages = append(validationMessages, + aurora.Sprintf(aurora.Red("Room %s is overbooked in slot (%d/%d): %d seats planned, but only %d available"), + aurora.Magenta(roomName), aurora.Blue(slot.DayNumber), aurora.Blue(slot.SlotNumber), + aurora.Cyan(roomSeats.seatsPlanned), aurora.Cyan(roomSeats.seats))) } } } + if len(validationMessages) > 0 { + spinner.StopFailMessage(aurora.Sprintf(aurora.Red("%d problems found"), len(validationMessages))) + err = spinner.StopFail() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + for _, msg := range validationMessages { + fmt.Printf(" ↪ %s\n", msg) + } + + } else { + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + } + return nil } func (p *Plexams) ValidateRoomsPerExam() error { ctx := context.Background() - color.Style{color.FgRed, color.BgGreen, color.OpBold}.Println(" --- validating rooms per exam --- ") + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Cyan(" validating rooms per exam")), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + validationMessages := make([]string, 0) - exams, err := p.ExamsInPlan(ctx) + exams, err := p.PlannedExams(ctx) if err != nil { log.Error().Err(err).Msg("cannot get exams in plan") } for _, exam := range exams { + if exam.PlanEntry == nil { + continue + } + + if exam.Constraints != nil && exam.Constraints.NotPlannedByMe { + continue + } + + spinner.Message(aurora.Sprintf(aurora.Yellow("checking rooms for %d. %s (%s) with %d students and %d ntas"), + exam.Ancode, exam.ZpaExam.Module, exam.ZpaExam.MainExamer, exam.StudentRegsCount, len(exam.Ntas))) // check if each student has a room allStudentRegs := make([]*model.StudentReg, 0) - for _, regs := range exam.Exam.StudentRegs { - allStudentRegs = append(allStudentRegs, regs.StudentRegs...) + for _, primussExam := range exam.PrimussExams { + allStudentRegs = append(allStudentRegs, primussExam.StudentRegs...) } - rooms, err := p.dbClient.RoomsForAncode(ctx, exam.Exam.Ancode) - if err != nil { - log.Error().Err(err).Int("andoce", exam.Exam.Ancode).Msg("cannot get rooms for ancode") - return err - } + // rooms, err := p.dbClient.RoomsForAncode(ctx, exam.Exam.Ancode) + // if err != nil { + // log.Error().Err(err).Int("ancode", exam.Exam.Ancode).Msg("cannot get rooms for ancode") + // return err + // } - allStudentsInRooms := make([]*model.StudentReg, 0) - for _, room := range rooms { + allStudentsInRooms := make([]string, 0) + for _, room := range exam.PlannedRooms { if room.RoomName != "No Room" { - allStudentsInRooms = append(allStudentsInRooms, room.Students...) + allStudentsInRooms = append(allStudentsInRooms, room.StudentsInRoom...) } } for _, studentReg := range allStudentRegs { studentHasSeat := false - for _, studentInRoom := range allStudentsInRooms { - if studentReg.Mtknr == studentInRoom.Mtknr { + for _, mtknr := range allStudentsInRooms { + if studentReg.Mtknr == mtknr { studentHasSeat = true break } } if !studentHasSeat { - color.Red.Printf("Student %s (%s) has no seat for exam %d. %s: %s in slot (%d,%d)\n", - studentReg.Name, studentReg.Mtknr, exam.Exam.Ancode, exam.Exam.ZpaExam.MainExamer, exam.Exam.ZpaExam.Module, - exam.Slot.DayNumber, exam.Slot.SlotNumber) + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("Student %s (%s) has no seat for exam %d. %s (%s) in slot (%d,%d)"), + aurora.Magenta(studentReg.Name), aurora.Magenta(studentReg.Mtknr), aurora.Cyan(exam.Ancode), aurora.Cyan(exam.ZpaExam.Module), aurora.Cyan(exam.ZpaExam.MainExamer), + aurora.BrightBlue(exam.PlanEntry.DayNumber), aurora.BrightBlue(exam.PlanEntry.SlotNumber))) } } // check if room constraints of exams are met if exam.Constraints != nil && exam.Constraints.RoomConstraints != nil { if exam.Constraints.RoomConstraints.ExahmRooms { - for _, room := range rooms { + for _, room := range exam.PlannedRooms { if !p.GetRoomInfo(room.RoomName).Exahm { - color.Red.Printf("Is not Exahm-Room %s for exam %d. %s: %s in slot (%d,%d)\n", - room.RoomName, exam.Exam.Ancode, exam.Exam.ZpaExam.MainExamer, exam.Exam.ZpaExam.Module, - exam.Slot.DayNumber, exam.Slot.SlotNumber) + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("Is not an exahm room %s for exam %d. %s (%s) in slot (%d,%d)"), + aurora.Magenta(room.RoomName), aurora.Cyan(exam.Ancode), aurora.Cyan(exam.ZpaExam.Module), aurora.Cyan(exam.ZpaExam.MainExamer), + aurora.BrightBlue(exam.PlanEntry.DayNumber), aurora.BrightBlue(exam.PlanEntry.SlotNumber))) } } } if exam.Constraints.RoomConstraints.Lab { - for _, room := range rooms { + for _, room := range exam.PlannedRooms { if !p.GetRoomInfo(room.RoomName).Lab { - color.Red.Printf("Is not Lab %s for exam %d. %s: %s in slot (%d,%d)\n", - room.RoomName, exam.Exam.Ancode, exam.Exam.ZpaExam.MainExamer, exam.Exam.ZpaExam.Module, - exam.Slot.DayNumber, exam.Slot.SlotNumber) + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("Is not a lab %s for exam %d. %s (%s) in slot (%d,%d)"), + aurora.Magenta(room.RoomName), aurora.Cyan(exam.Ancode), aurora.Cyan(exam.ZpaExam.Module), aurora.Cyan(exam.ZpaExam.MainExamer), + aurora.BrightBlue(exam.PlanEntry.DayNumber), aurora.BrightBlue(exam.PlanEntry.SlotNumber))) } } } if exam.Constraints.RoomConstraints.PlacesWithSocket { - for _, room := range rooms { + for _, room := range exam.PlannedRooms { if !p.GetRoomInfo(room.RoomName).PlacesWithSocket && !p.GetRoomInfo(room.RoomName).Lab { - color.Red.Printf("Is not Room with sockets %s for exam %d. %s: %s in slot (%d,%d)\n", - room.RoomName, exam.Exam.Ancode, exam.Exam.ZpaExam.MainExamer, exam.Exam.ZpaExam.Module, - exam.Slot.DayNumber, exam.Slot.SlotNumber) + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("Is not a room with places with sockets %s for exam %d. %s (%s) in slot (%d,%d)"), + aurora.Magenta(room.RoomName), aurora.Cyan(exam.Ancode), aurora.Cyan(exam.ZpaExam.Module), aurora.Cyan(exam.ZpaExam.MainExamer), + aurora.BrightBlue(exam.PlanEntry.DayNumber), aurora.BrightBlue(exam.PlanEntry.SlotNumber))) } } } @@ -173,81 +257,84 @@ func (p *Plexams) ValidateRoomsPerExam() error { // check rooms for NTAs // - needsRoomAlone okay - // - TODO: enough time between usage - - if exam.Nta != nil { - plannedRooms, err := p.dbClient.RoomsPlannedInSlot(ctx, exam.Slot.DayNumber, exam.Slot.SlotNumber) - if err != nil { - log.Error().Err(err). - Int("day", exam.Slot.DayNumber). - Int("time", exam.Slot.SlotNumber). - Msg("error while getting rooms planned in slot") - return err - } - - for _, nta := range exam.Nta { - if nta.Nta.NeedsRoomAlone { - var roomForNta *model.RoomForExam - for _, room := range plannedRooms { - for _, student := range room.Students { - if student.Mtknr == nta.Nta.Mtknr { - roomForNta = room - break - } + if len(exam.Ntas) > 0 { + spinner.Message(aurora.Sprintf(aurora.Yellow("checking rooms for ntas"))) + for _, nta := range exam.Ntas { + if nta.NeedsRoomAlone { + var roomForNta *model.PlannedRoom + for _, room := range exam.PlannedRooms { + if room.NtaMtknr != nil && *room.NtaMtknr == nta.Mtknr { + roomForNta = room + break } } OUTER: - for _, room := range plannedRooms { + for _, room := range exam.PlannedRooms { if room.RoomName == roomForNta.RoomName { - for _, student := range room.Students { - if student.Mtknr != nta.Nta.Mtknr { - color.Red.Printf("NTA %s has room %s not alone for exam %d. %s: %s in slot (%d,%d)\n", - nta.Nta.Name, room.RoomName, exam.Exam.Ancode, exam.Exam.ZpaExam.MainExamer, exam.Exam.ZpaExam.Module, - exam.Slot.DayNumber, exam.Slot.SlotNumber) + for _, mtknr := range room.StudentsInRoom { + if mtknr != nta.Mtknr { + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("NTA %s has room %s not alone for exam %d. %s (%s) in slot (%d,%d)"), + aurora.Magenta(nta.Name), aurora.Magenta(room.RoomName), aurora.Cyan(exam.Ancode), aurora.Cyan(exam.ZpaExam.Module), aurora.Cyan(exam.ZpaExam.MainExamer), + aurora.BrightBlue(exam.PlanEntry.DayNumber), aurora.BrightBlue(exam.PlanEntry.SlotNumber))) break OUTER } } } } - } else /* do not need room alone */ { - var roomForNta *model.RoomForExam - for _, room := range plannedRooms { - for _, student := range room.Students { - if student.Mtknr == nta.Nta.Mtknr { - roomForNta = room - break - } - } - } - if roomForNta == nil { - color.Red.Printf("NTA %s has no room for exam %d. %s: %s in slot (%d,%d)\n", - nta.Nta.Name, exam.Exam.Ancode, exam.Exam.ZpaExam.MainExamer, exam.Exam.ZpaExam.Module, - exam.Slot.DayNumber, exam.Slot.SlotNumber) - } else { - ntaDuration := int(math.Ceil(float64((exam.Exam.ZpaExam.Duration * (100 + nta.Nta.DeltaDurationPercent))) / 100)) - if roomForNta.Duration != ntaDuration { - color.Red.Printf("NTA %s has room %s without correct duration %d for exam %d. %s: %s in slot (%d,%d): found %d\n", - nta.Nta.Name, roomForNta.RoomName, ntaDuration, exam.Exam.Ancode, exam.Exam.ZpaExam.MainExamer, exam.Exam.ZpaExam.Module, - exam.Slot.DayNumber, exam.Slot.SlotNumber, roomForNta.Duration) - } - } } } } - } + if len(validationMessages) > 0 { + spinner.StopFailMessage(aurora.Sprintf(aurora.Red("%d problems found"), len(validationMessages))) + err = spinner.StopFail() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + for _, msg := range validationMessages { + fmt.Printf(" ↪ %s\n", msg) + } + + } else { + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + } return nil } func (p *Plexams) ValidateRoomsTimeDistance() error { ctx := context.Background() timelag := viper.GetInt("rooms.timelag") - color.Style{color.FgRed, color.BgGreen, color.OpBold}. - Printf(" --- validating time lag of planned rooms (%d minutes) --- \n", timelag) + + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Cyan(" validating time lag of planned rooms (%d minutes)"), timelag), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + validationMessages := make([]string, 0) for _, day := range p.semesterConfig.Days { - log.Debug().Interface("day", day).Msg("checking day") + spinner.Message(aurora.Sprintf(aurora.Yellow("checking day %d (%s)"), day.Number, day.Date.Format("02.01.06"))) + for i := range p.semesterConfig.Starttimes { if i == len(p.semesterConfig.Days)-1 { continue @@ -255,7 +342,7 @@ func (p *Plexams) ValidateRoomsTimeDistance() error { slot1, slot2 := i+1, i+2 log.Debug().Int("slot 1", slot1).Int("slot 2", slot2).Msg("checking slot") - plannedRoomsSlot1, err := p.dbClient.RoomsPlannedInSlot(ctx, day.Number, slot1) + plannedRoomsSlot1, err := p.dbClient.PlannedRoomsInSlot(ctx, day.Number, slot1) if err != nil { log.Error().Err(err). Int("day", day.Number). @@ -276,7 +363,7 @@ func (p *Plexams) ValidateRoomsTimeDistance() error { } } - plannedRoomsSlot2, err := p.dbClient.RoomsPlannedInSlot(ctx, day.Number, slot2) + plannedRoomsSlot2, err := p.dbClient.PlannedRoomsInSlot(ctx, day.Number, slot2) if err != nil { log.Error().Err(err). Int("day", day.Number). @@ -313,16 +400,33 @@ func (p *Plexams) ValidateRoomsTimeDistance() error { diff := time.Duration(timelag) * time.Minute if startSlot2.Before(endSlot1.Add(diff)) { - color.Red.Printf("Not enough time in room %s between slot (%d, %d) ends %s and slot (%d,%d) begins %s: %g minutes between\n", - roomName, day.Number, slot1, endSlot1.Format("15:04"), day.Number, slot2, startSlot2.Format("15:04"), - startSlot2.Sub(endSlot1).Minutes()) + validationMessages = append(validationMessages, aurora.Sprintf( + "Not enough time in room %s between slot (%d/%d) ends %s and slot (%d/%d) begins %s: %g minutes between", + aurora.Magenta(roomName), aurora.BrightBlue(day.Number), aurora.BrightBlue(slot1), aurora.Magenta(endSlot1.Format("15:04")), + aurora.BrightBlue(day.Number), aurora.BrightBlue(slot2), aurora.Magenta(startSlot2.Format("15:04")), + aurora.Magenta(startSlot2.Sub(endSlot1).Minutes()), + )) } - } } + } + } + if len(validationMessages) > 0 { + spinner.StopFailMessage(aurora.Sprintf(aurora.Red("%d problems found"), len(validationMessages))) + err = spinner.StopFail() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + for _, msg := range validationMessages { + fmt.Printf(" ↪ %s\n", msg) } + } else { + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } } return nil From 2095d73ff15ffa2799ef9686d2d97902cc2d7c8e Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Wed, 27 Dec 2023 18:26:59 +0100 Subject: [PATCH 58/78] validate zpa with spinner --- cmd/validate.go | 1 - plexams/validate_zpa.go | 77 +++++++++++++++++++++++++++++++---------- 2 files changed, 59 insertions(+), 19 deletions(-) diff --git a/cmd/validate.go b/cmd/validate.go index e4a0dba..77c932c 100644 --- a/cmd/validate.go +++ b/cmd/validate.go @@ -53,7 +53,6 @@ var ( []func() error{plexams.ValidateRoomsPerSlot, plexams.ValidateRoomsPerExam, plexams.ValidateRoomsTimeDistance}...) case "zpa": - fmt.Println("validating zpa dates and times") err := plexams.ValidateZPADateTimes() if err != nil { log.Fatal(err) diff --git a/plexams/validate_zpa.go b/plexams/validate_zpa.go index 8b4a50f..1f61e64 100644 --- a/plexams/validate_zpa.go +++ b/plexams/validate_zpa.go @@ -2,14 +2,42 @@ package plexams import ( "context" + "fmt" "strings" + "time" "github.com/gookit/color" + "github.com/logrusorgru/aurora" "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" + "github.com/theckman/yacspin" ) func (p *Plexams) ValidateZPADateTimes() error { + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Cyan(" validating zpa dates and times")), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + validationMessages := make([]string, 0) + + spinner.Message(aurora.Sprintf(aurora.Yellow("fetching exam from ZPA"))) if err := p.SetZPA(); err != nil { return err } @@ -21,15 +49,17 @@ func (p *Plexams) ValidateZPADateTimes() error { examsMap[exam.AnCode] = exam } + spinner.Message(aurora.Sprintf(aurora.Yellow("fetching planned exams from db"))) plannedExams, err := p.PlannedExams(context.Background()) if err != nil { return err } - problems := 0 notPlannedByMe := 0 for _, plannedExam := range plannedExams { + spinner.Message(aurora.Sprintf(aurora.Yellow("checking exam %d. %s (%s)"), + plannedExam.Ancode, plannedExam.ZpaExam.Module, plannedExam.ZpaExam.MainExamer)) zpaExam := examsMap[plannedExam.ZpaExam.AnCode] delete(examsMap, plannedExam.ZpaExam.AnCode) @@ -54,31 +84,42 @@ func (p *Plexams) ValidateZPADateTimes() error { if zpaExam.Date != plannedExamDate || zpaExam.Starttime != plannedExamStarttime { - problems++ - color.Red.Printf("wrong date for %d. %s: %s\nwant: %s %s\ngot: %s %s\n", - plannedExam.ZpaExam.AnCode, plannedExam.ZpaExam.MainExamer, plannedExam.ZpaExam.Module, - plannedExamDate, plannedExamStarttime, - zpaExam.Date, zpaExam.Starttime) + validationMessages = append(validationMessages, aurora.Sprintf( + aurora.Red("wrong date for %d. %s (%s), want: %s %s, got: %s %s"), + aurora.Cyan(zpaExam.AnCode), aurora.Cyan(zpaExam.Module), aurora.Cyan(zpaExam.MainExamer), + aurora.Green(plannedExamDate), aurora.Green(plannedExamStarttime), + aurora.Magenta(zpaExam.Date), aurora.Magenta(zpaExam.Starttime), + )) } } - if problems == 0 { - color.Green.Printf("all %d planned exams in zpa with correct date/time (%d not planned by me)\n", len(plannedExams), notPlannedByMe) - } - - problems = 0 - for _, zpaExam := range examsMap { if zpaExam.Date != "-" || zpaExam.Starttime != "-" { - problems++ - color.Red.Printf("exam %d. %s: %s has date %s %s, but should not", - zpaExam.AnCode, zpaExam.MainExamer, zpaExam.Module, - zpaExam.Date, zpaExam.Starttime) + validationMessages = append(validationMessages, aurora.Sprintf( + aurora.Red("exam %d. %s (%s) has date %s %s, but should not be planned"), + aurora.Cyan(zpaExam.AnCode), aurora.Cyan(zpaExam.Module), aurora.Cyan(zpaExam.MainExamer), + aurora.Magenta(zpaExam.Date), aurora.Magenta(zpaExam.Starttime))) } } - if problems == 0 { - color.Green.Printf("all %d not planned exams in zpa without date/time\n", len(examsMap)) + if len(validationMessages) > 0 { + spinner.StopFailMessage(aurora.Sprintf(aurora.Red("%d problems found"), len(validationMessages))) + err = spinner.StopFail() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + for _, msg := range validationMessages { + fmt.Printf(" ↪ %s\n", msg) + } + + } else { + spinner.StopMessage(aurora.Sprintf( + aurora.Green("%d planned exams (%d not planned by me) & %d not planned are correct"), + len(plannedExams), notPlannedByMe, len(examsMap))) + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } } return nil From 659e7ced21a0f951caf52f4dec38a5d5b975e4e9 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Wed, 27 Dec 2023 19:47:36 +0100 Subject: [PATCH 59/78] validate conflicts with spinner --- plexams/validate.go | 79 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 62 insertions(+), 17 deletions(-) diff --git a/plexams/validate.go b/plexams/validate.go index ddb9281..4fb58cf 100644 --- a/plexams/validate.go +++ b/plexams/validate.go @@ -7,9 +7,11 @@ import ( set "github.com/deckarep/golang-set/v2" "github.com/gookit/color" + "github.com/logrusorgru/aurora" "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" "github.com/spf13/viper" + "github.com/theckman/yacspin" ) // TODO: Validate if all NTAs have MTKNR @@ -27,8 +29,30 @@ func (p *Plexams) ValidateConflicts(onlyPlannedByMe bool, ancode int) error { count = 0 knownConflictsCount = 0 ctx := context.Background() - color.Style{color.FgRed, color.BgGreen, color.OpBold}.Println(" --- validating conflicts --- ") + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Cyan(" validating conflicts")), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + validationMessages := make([]string, 0) + spinner.Message(aurora.Sprintf(aurora.Yellow(" get planned ancodes"))) planAncodeEntries, err := p.dbClient.PlannedAncodes(ctx) if err != nil { log.Error().Err(err).Msg("cannot get plan entries") @@ -47,6 +71,7 @@ func (p *Plexams) ValidateConflicts(onlyPlannedByMe bool, ancode int) error { } } + spinner.Message(aurora.Sprintf(aurora.Yellow(" get student regs"))) students, err := p.StudentRegsPerStudentPlanned(ctx) if err != nil { log.Error().Err(err).Msg("cannot get student registries per student") @@ -55,6 +80,7 @@ func (p *Plexams) ValidateConflicts(onlyPlannedByMe bool, ancode int) error { knownConflicts := set.NewSet[KnownConflict]() + spinner.Message(aurora.Sprintf(aurora.Yellow(" get known conflicts"))) knownConflictsConf := viper.Get("knownConflicts.studentRegs") if knownConflictsConf != nil { knownConflictsSlice := knownConflictsConf.([]interface{}) @@ -70,19 +96,38 @@ func (p *Plexams) ValidateConflicts(onlyPlannedByMe bool, ancode int) error { log.Debug().Int("count", knownConflicts.Cardinality()).Interface("conflicts", knownConflicts).Msg("found known conflicts") + spinner.Message(aurora.Sprintf(aurora.Yellow(" validating students"))) for _, student := range students { - validateStudentReg(student, planAncodeEntries, planAncodeEntriesNotPlannedByMe, onlyPlannedByMe, knownConflicts, ancode) + validateStudentReg(student, planAncodeEntries, planAncodeEntriesNotPlannedByMe, onlyPlannedByMe, + knownConflicts, ancode, &validationMessages) } - if knownConflictsCount > 0 { - color.Green.Printf("%d known conflicts found\n", knownConflictsCount) + if len(validationMessages) > 0 { + spinner.StopFailMessage(aurora.Sprintf(aurora.Red("%d known conflicts, but %d problems found"), + knownConflictsCount, len(validationMessages))) + err = spinner.StopFail() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + for _, msg := range validationMessages { + fmt.Printf("%s\n", msg) + } + + } else { + spinner.StopMessage(aurora.Sprintf(aurora.Green("%d known conflicts, no further problems found"), + knownConflictsCount)) + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } } return nil } func validateStudentReg(student *model.Student, planAncodeEntries []*model.PlanEntry, - planAncodeEntriesNotPlannedByMe set.Set[int], onlyPlannedByMe bool, knownConflicts set.Set[KnownConflict], ancode int) { + planAncodeEntriesNotPlannedByMe set.Set[int], onlyPlannedByMe bool, knownConflicts set.Set[KnownConflict], ancode int, + validationMessages *[]string) { log.Debug().Str("name", student.Name).Str("mtknr", student.Mtknr).Msg("checking regs for student") planAncodeEntriesForStudent := make([]*model.PlanEntry, 0) @@ -135,34 +180,34 @@ func validateStudentReg(student *model.Student, planAncodeEntries []*model.PlanE if p[i].DayNumber == p[j].DayNumber && p[i].SlotNumber == p[j].SlotNumber { count++ - color.Red.Printf(" - [\"%s\", \"%d\", \"%d\"] # %3d. Same slot: ancodes %d (%d, %d) and %d (%d,%d) for student %s (%s/%s)\n", - student.Mtknr, p[i].Ancode, p[j].Ancode, count, + *validationMessages = append(*validationMessages, aurora.Sprintf(aurora.Red(" - [\"%s\", \"%d\", \"%d\"] # %3d. Same slot: ancodes %d (%d, %d) and %d (%d,%d) for student %s (%s/%s)"), + aurora.Magenta(student.Mtknr), aurora.Magenta(p[i].Ancode), aurora.Magenta(p[j].Ancode), count, p[i].Ancode, p[i].DayNumber, p[i].SlotNumber, p[j].Ancode, p[j].DayNumber, p[j].SlotNumber, - student.Name, student.Program, student.Mtknr, - ) + aurora.Cyan(student.Name), aurora.Cyan(student.Program), aurora.Cyan(student.Mtknr), + )) } else // adjacent slots if p[i].DayNumber == p[j].DayNumber && (p[i].SlotNumber+1 == p[j].SlotNumber || p[i].SlotNumber-1 == p[j].SlotNumber) { count++ - color.Red.Printf(" - [\"%s\", \"%d\", \"%d\"] # %3d. Adjacent slots: ancodes %d (%d, %d) and %d (%d,%d) for student %s (%s/%s)\n", - student.Mtknr, p[i].Ancode, p[j].Ancode, count, + *validationMessages = append(*validationMessages, aurora.Sprintf(aurora.Red(" - [\"%s\", \"%d\", \"%d\"] # %3d. Adjacent slots: ancodes %d (%d, %d) and %d (%d,%d) for student %s (%s/%s)"), + aurora.Magenta(student.Mtknr), aurora.Magenta(p[i].Ancode), aurora.Magenta(p[j].Ancode), count, p[i].Ancode, p[i].DayNumber, p[i].SlotNumber, p[j].Ancode, p[j].DayNumber, p[j].SlotNumber, - student.Name, student.Program, student.Mtknr, - ) + aurora.Cyan(student.Name), aurora.Cyan(student.Program), aurora.Cyan(student.Mtknr), + )) } else // same day if p[i].DayNumber == p[j].DayNumber { count++ - color.Yellow.Printf(" - [\"%s\", \"%d\", \"%d\"] # %3d. Same day: ancodes %d (%d, %d) and %d (%d,%d) for student %s (%s/%s)\n", - student.Mtknr, p[i].Ancode, p[j].Ancode, count, + *validationMessages = append(*validationMessages, aurora.Sprintf(aurora.Yellow(" - [\"%s\", \"%d\", \"%d\"] # %3d. Same day: ancodes %d (%d, %d) and %d (%d,%d) for student %s (%s/%s)"), + aurora.Magenta(student.Mtknr), aurora.Magenta(p[i].Ancode), aurora.Magenta(p[j].Ancode), count, p[i].Ancode, p[i].DayNumber, p[i].SlotNumber, p[j].Ancode, p[j].DayNumber, p[j].SlotNumber, - student.Name, student.Program, student.Mtknr, - ) + aurora.Cyan(student.Name), aurora.Cyan(student.Program), aurora.Cyan(student.Mtknr), + )) } } } From dca352ca79da8f215bb33bbff4a67ccb04634920 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Wed, 3 Jan 2024 14:51:39 +0100 Subject: [PATCH 60/78] mv query --- graph/generated/generated.go | 165 ++++++++++++++++---------------- graph/invigilation.graphqls | 4 + graph/invigilation.resolvers.go | 16 ++++ graph/query.graphqls | 1 - graph/query.resolvers.go | 5 - 5 files changed, 104 insertions(+), 87 deletions(-) create mode 100644 graph/invigilation.resolvers.go diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 4ae2b74..98fe94b 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -721,7 +721,6 @@ type QueryResolver interface { RoomsWithConstraints(ctx context.Context, handicap bool, lab bool, placesWithSocket bool, exahm *bool) ([]*model.Room, error) RoomsForSlot(ctx context.Context, day int, time int) (*model.SlotWithRooms, error) InvigilatorsWithReq(ctx context.Context) ([]*model.Invigilator, error) - InvigilatorTodos(ctx context.Context) (*model.InvigilationTodos, error) RoomsWithInvigilationsForSlot(ctx context.Context, day int, time int) (*model.InvigilationSlot, error) InvigilatorsForDay(ctx context.Context, day int) (*model.InvigilatorsForDay, error) DayOkForInvigilator(ctx context.Context, day int, invigilatorID int) (*bool, error) @@ -735,6 +734,7 @@ type QueryResolver interface { ConflictingAncodes(ctx context.Context, ancode int) ([]*model.Conflict, error) Exam(ctx context.Context, ancode int) (*model.Exam, error) Exams(ctx context.Context) ([]*model.Exam, error) + InvigilatorTodos(ctx context.Context) (*model.InvigilationTodos, error) Ntas(ctx context.Context) ([]*model.NTA, error) NtasWithRegs(ctx context.Context) ([]*model.Student, error) AllProgramsInPlan(ctx context.Context) ([]string, error) @@ -4146,7 +4146,11 @@ type Exam { rooms: [RoomForExam!] } `, BuiltIn: false}, - {Name: "../invigilation.graphqls", Input: `type Invigilation { + {Name: "../invigilation.graphqls", Input: `extend type Query { + invigilatorTodos: InvigilationTodos +} + +type Invigilation { roomName: String duration: Int! invigilatorID: Int! @@ -4515,7 +4519,6 @@ type ConflictsPerProgramAncode { # Invigilators invigilatorsWithReq: [Invigilator!]! - invigilatorTodos: InvigilationTodos roomsWithInvigilationsForSlot(day: Int!, time: Int!): InvigilationSlot invigilatorsForDay(day: Int!): InvigilatorsForDay dayOkForInvigilator(day: Int!, invigilatorID: Int!): Boolean @@ -18394,65 +18397,6 @@ func (ec *executionContext) fieldContext_Query_invigilatorsWithReq(ctx context.C return fc, nil } -func (ec *executionContext) _Query_invigilatorTodos(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_invigilatorTodos(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().InvigilatorTodos(rctx) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.(*model.InvigilationTodos) - fc.Result = res - return ec.marshalOInvigilationTodos2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilationTodos(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_invigilatorTodos(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "sumExamRooms": - return ec.fieldContext_InvigilationTodos_sumExamRooms(ctx, field) - case "sumReserve": - return ec.fieldContext_InvigilationTodos_sumReserve(ctx, field) - case "sumOtherContributions": - return ec.fieldContext_InvigilationTodos_sumOtherContributions(ctx, field) - case "sumOtherContributionsOvertimeCutted": - return ec.fieldContext_InvigilationTodos_sumOtherContributionsOvertimeCutted(ctx, field) - case "invigilatorCount": - return ec.fieldContext_InvigilationTodos_invigilatorCount(ctx, field) - case "todoPerInvigilator": - return ec.fieldContext_InvigilationTodos_todoPerInvigilator(ctx, field) - case "todoPerInvigilatorOvertimeCutted": - return ec.fieldContext_InvigilationTodos_todoPerInvigilatorOvertimeCutted(ctx, field) - case "invigilators": - return ec.fieldContext_InvigilationTodos_invigilators(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type InvigilationTodos", field.Name) - }, - } - return fc, nil -} - func (ec *executionContext) _Query_roomsWithInvigilationsForSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_roomsWithInvigilationsForSlot(ctx, field) if err != nil { @@ -19271,6 +19215,65 @@ func (ec *executionContext) fieldContext_Query_exams(ctx context.Context, field return fc, nil } +func (ec *executionContext) _Query_invigilatorTodos(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_invigilatorTodos(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().InvigilatorTodos(rctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.InvigilationTodos) + fc.Result = res + return ec.marshalOInvigilationTodos2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilationTodos(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_invigilatorTodos(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "sumExamRooms": + return ec.fieldContext_InvigilationTodos_sumExamRooms(ctx, field) + case "sumReserve": + return ec.fieldContext_InvigilationTodos_sumReserve(ctx, field) + case "sumOtherContributions": + return ec.fieldContext_InvigilationTodos_sumOtherContributions(ctx, field) + case "sumOtherContributionsOvertimeCutted": + return ec.fieldContext_InvigilationTodos_sumOtherContributionsOvertimeCutted(ctx, field) + case "invigilatorCount": + return ec.fieldContext_InvigilationTodos_invigilatorCount(ctx, field) + case "todoPerInvigilator": + return ec.fieldContext_InvigilationTodos_todoPerInvigilator(ctx, field) + case "todoPerInvigilatorOvertimeCutted": + return ec.fieldContext_InvigilationTodos_todoPerInvigilatorOvertimeCutted(ctx, field) + case "invigilators": + return ec.fieldContext_InvigilationTodos_invigilators(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type InvigilationTodos", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _Query_ntas(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_ntas(ctx, field) if err != nil { @@ -31566,25 +31569,6 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "invigilatorTodos": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_invigilatorTodos(ctx, field) - return res - } - - rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, - func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "roomsWithInvigilationsForSlot": field := field @@ -31847,6 +31831,25 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "invigilatorTodos": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_invigilatorTodos(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "ntas": field := field diff --git a/graph/invigilation.graphqls b/graph/invigilation.graphqls index ef74bf6..b67fc24 100644 --- a/graph/invigilation.graphqls +++ b/graph/invigilation.graphqls @@ -1,3 +1,7 @@ +extend type Query { + invigilatorTodos: InvigilationTodos +} + type Invigilation { roomName: String duration: Int! diff --git a/graph/invigilation.resolvers.go b/graph/invigilation.resolvers.go new file mode 100644 index 0000000..fb649cb --- /dev/null +++ b/graph/invigilation.resolvers.go @@ -0,0 +1,16 @@ +package graph + +// This file will be automatically regenerated based on the schema, any resolver implementations +// will be copied through when generating and any unknown code will be moved to the end. +// Code generated by github.com/99designs/gqlgen version v0.17.34 + +import ( + "context" + + "github.com/obcode/plexams.go/graph/model" +) + +// InvigilatorTodos is the resolver for the invigilatorTodos field. +func (r *queryResolver) InvigilatorTodos(ctx context.Context) (*model.InvigilationTodos, error) { + return r.plexams.InvigilationTodos(ctx) +} diff --git a/graph/query.graphqls b/graph/query.graphqls index b7a7ad1..5cbe71a 100644 --- a/graph/query.graphqls +++ b/graph/query.graphqls @@ -44,7 +44,6 @@ type Query { # Invigilators invigilatorsWithReq: [Invigilator!]! - invigilatorTodos: InvigilationTodos roomsWithInvigilationsForSlot(day: Int!, time: Int!): InvigilationSlot invigilatorsForDay(day: Int!): InvigilatorsForDay dayOkForInvigilator(day: Int!, invigilatorID: Int!): Boolean diff --git a/graph/query.resolvers.go b/graph/query.resolvers.go index d3367f5..9ca65c4 100644 --- a/graph/query.resolvers.go +++ b/graph/query.resolvers.go @@ -132,11 +132,6 @@ func (r *queryResolver) InvigilatorsWithReq(ctx context.Context) ([]*model.Invig return r.plexams.InvigilatorsWithReq(ctx) } -// InvigilatorTodos is the resolver for the invigilatorTodos field. -func (r *queryResolver) InvigilatorTodos(ctx context.Context) (*model.InvigilationTodos, error) { - return r.plexams.InvigilationTodos(ctx) -} - // RoomsWithInvigilationsForSlot is the resolver for the roomsWithInvigilationsForSlot field. func (r *queryResolver) RoomsWithInvigilationsForSlot(ctx context.Context, day int, time int) (*model.InvigilationSlot, error) { return r.plexams.RoomsWithInvigilationsForSlot(ctx, day, time) From d4313382d237919898720dda28a13c119ee62c2d Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Thu, 4 Jan 2024 14:29:25 +0100 Subject: [PATCH 61/78] ValidateRoomsNeedRequest --- cmd/validate.go | 7 ++- db/rooms.go | 23 ++++++++- plexams/rooms.go | 82 ++++++++++++++++++++++------- plexams/validate_rooms.go | 105 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 195 insertions(+), 22 deletions(-) diff --git a/cmd/validate.go b/cmd/validate.go index 77c932c..bc23bf1 100644 --- a/cmd/validate.go +++ b/cmd/validate.go @@ -50,7 +50,12 @@ var ( case "rooms": validations = append(validations, - []func() error{plexams.ValidateRoomsPerSlot, plexams.ValidateRoomsPerExam, plexams.ValidateRoomsTimeDistance}...) + []func() error{ + plexams.ValidateRoomsPerSlot, + plexams.ValidateRoomsNeedRequest, + plexams.ValidateRoomsPerExam, + plexams.ValidateRoomsTimeDistance, + }...) case "zpa": err := plexams.ValidateZPADateTimes() diff --git a/db/rooms.go b/db/rooms.go index 039f0f0..af63a24 100644 --- a/db/rooms.go +++ b/db/rooms.go @@ -201,7 +201,7 @@ func (db *DB) ChangeRoom(ctx context.Context, ancode int, oldRoom, newRoom *mode func (db *DB) PlannedRoomNames(ctx context.Context) ([]string, error) { collection := db.getCollectionSemester(collectionRoomsPlanned) - rawNames, err := collection.Distinct(ctx, "room.name", bson.D{}) + rawNames, err := collection.Distinct(ctx, "roomname", bson.D{}) if err != nil { log.Error().Err(err).Msg("cannot find distinct room names") } @@ -223,7 +223,7 @@ func (db *DB) PlannedRoomNamesInSlot(ctx context.Context, day, slot int) ([]stri filter := bson.M{"day": day, "slot": slot} - rawNames, err := collection.Distinct(ctx, "room.name", filter) + rawNames, err := collection.Distinct(ctx, "roomname", filter) if err != nil { log.Error().Err(err).Int("day", day).Int("slot", slot).Msg("cannot find roomnames for slot") return nil, err @@ -241,6 +241,25 @@ func (db *DB) PlannedRoomNamesInSlot(ctx context.Context, day, slot int) ([]stri return names, nil } +func (db *DB) PlannedRooms(ctx context.Context) ([]*model.PlannedRoom, error) { + collection := db.getCollectionSemester(collectionRoomsPlanned) + + cur, err := collection.Find(ctx, bson.M{}) + if err != nil { + log.Error().Err(err).Msg("cannot find planned rooms") + return nil, err + } + + plannedRooms := make([]*model.PlannedRoom, 0) + err = cur.All(ctx, &plannedRooms) + if err != nil { + log.Error().Err(err).Msg("cannot decode planned rooms") + return nil, err + } + + return plannedRooms, nil +} + func (db *DB) PlannedRoomsInSlot(ctx context.Context, day, slot int) ([]*model.PlannedRoom, error) { collection := db.getCollectionSemester(collectionRoomsPlanned) diff --git a/plexams/rooms.go b/plexams/rooms.go index ee84dbc..4d72828 100644 --- a/plexams/rooms.go +++ b/plexams/rooms.go @@ -46,7 +46,7 @@ func (p *Plexams) ExahmRoomsFromBooked() ([]BookedEntry, error) { entries := make([]BookedEntry, 0, len(bookedInfoSlice)) for _, bookedEntry := range bookedInfoSlice { - from, until, err := fromUntil(bookedEntry) + fromUntil, err := fromUntil(bookedEntry) if err != nil { log.Error().Err(err).Interface("entry", bookedEntry).Msg("cannot convert entry to time") return nil, err @@ -75,8 +75,8 @@ func (p *Plexams) ExahmRoomsFromBooked() ([]BookedEntry, error) { } entries = append(entries, BookedEntry{ - From: from, - Until: until, + From: fromUntil.From, + Until: fromUntil.Until, Rooms: rooms, }) @@ -215,19 +215,59 @@ func (p *Plexams) PrepareRoomsForSemester() error { return p.dbClient.SaveRooms(context.Background(), slotsWithRooms) } +type TimeRange struct { + From time.Time + Until time.Time +} + +func (p *Plexams) GetReservations() (map[string][]TimeRange, error) { + ctx := context.Background() + rooms, err := p.Rooms(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get rooms") + } + + reservations := make(map[string][]TimeRange) + + for _, room := range rooms { + if viper.IsSet(fmt.Sprintf("roomConstraints.%s.reservations", room.Name)) { + log.Debug().Str("room", room.Name).Msg("found reservations for room") + reservationsForRoom := viper.Get(fmt.Sprintf("roomConstraints.%s.reservations", room.Name)) + reservationsSlice, ok := reservationsForRoom.([]interface{}) + if !ok { + log.Error().Interface("reservations", reservations).Msg("cannot convert reservations to slice") + return nil, fmt.Errorf("cannot convert reservations to slice") + } + + reservations[room.Name] = make([]TimeRange, 0, len(reservationsSlice)) + + for _, reservationEntry := range reservationsSlice { + fromUntil, err := fromUntil(reservationEntry) + if err != nil { + log.Error().Err(err).Interface("reservation", reservationsSlice).Msg("cannot convert reservation to time") + return nil, err + } + reservations[room.Name] = append(reservations[room.Name], *fromUntil) + } + } + } + + return reservations, nil +} + func (p *Plexams) reservations2Slots(reservations []interface{}) (set.Set[SlotNumber], error) { slots := set.NewSet[SlotNumber]() for _, reservation := range reservations { - from, until, err := fromUntil(reservation) + fromUntil, err := fromUntil(reservation) if err != nil { log.Error().Err(err).Interface("reservation", reservation).Msg("cannot convert reservation to time") return nil, err } - fmt.Printf(" From: %v Until: %v\n", from, until) + fmt.Printf(" From: %v Until: %v\n", fromUntil.From, fromUntil.Until) for _, slot := range p.semesterConfig.Slots { - if (from.Before(slot.Starttime.Local()) || from.Equal(slot.Starttime.Local())) && until.After(slot.Starttime.Local().Add(89*time.Minute)) { + if (fromUntil.From.Before(slot.Starttime.Local()) || fromUntil.From.Equal(slot.Starttime.Local())) && fromUntil.Until.After(slot.Starttime.Local().Add(89*time.Minute)) { fmt.Printf(" ---> add (%d, %d)\n", slot.DayNumber, slot.SlotNumber) slots.Add(SlotNumber{slot.DayNumber, slot.SlotNumber}) } @@ -236,48 +276,48 @@ func (p *Plexams) reservations2Slots(reservations []interface{}) (set.Set[SlotNu return slots, nil } -func fromUntil(dateEntry interface{}) (from time.Time, until time.Time, err error) { - from = time.Now() - until = time.Now() - +func fromUntil(dateEntry interface{}) (fromUntil *TimeRange, err error) { entry, ok := dateEntry.(map[string]interface{}) if !ok { err = fmt.Errorf("cannot convert date entry to map") log.Error().Interface("date entry", dateEntry).Msg("cannot convert date entry to map") - return + return nil, err } rawDate, ok := entry["date"].(time.Time) if !ok { err = fmt.Errorf("cannot convert date entry to string") log.Error().Interface("date entry", entry["date"]).Msg("cannot convert date entry to string") - return + return nil, err } rawFrom, ok := entry["from"].(string) if !ok { err = fmt.Errorf("cannot convert from entry to string") log.Error().Interface("date entry", entry["from"]).Msg("cannot convert from entry to string") - return + return nil, err } rawUntil, ok := entry["until"].(string) if !ok { err = fmt.Errorf("cannot convert until entry to string") log.Error().Interface("date entry", entry["until"]).Msg("cannot convert until entry to string") - return + return nil, err } - from, err = time.ParseInLocation("2006-01-02 15:04", fmt.Sprintf("%s %s", rawDate.Format("2006-01-02"), rawFrom), time.Local) + from, err := time.ParseInLocation("2006-01-02 15:04", fmt.Sprintf("%s %s", rawDate.Format("2006-01-02"), rawFrom), time.Local) if err != nil { log.Error().Err(err).Interface("date", rawDate).Str("time", rawFrom).Msg("cannot parse to time") - return + return nil, err } - until, err = time.ParseInLocation("2006-01-02 15:04", fmt.Sprintf("%s %s", rawDate.Format("2006-01-02"), rawUntil), time.Local) + until, err := time.ParseInLocation("2006-01-02 15:04", fmt.Sprintf("%s %s", rawDate.Format("2006-01-02"), rawUntil), time.Local) if err != nil { log.Error().Err(err).Interface("date", rawDate).Str("time", rawFrom).Msg("cannot parse to time") - return + return nil, err } - return + return &TimeRange{ + From: from, + Until: until, + }, nil } func splitRooms(rooms []*model.Room) ([]*model.Room, []*model.Room, []*model.Room, []*model.Room) { @@ -475,6 +515,10 @@ func (p *Plexams) PlannedRoomNamesInSlot(ctx context.Context, day int, time int) return p.dbClient.PlannedRoomNamesInSlot(ctx, day, time) } +func (p *Plexams) PlannedRooms(ctx context.Context) ([]*model.PlannedRoom, error) { + return p.dbClient.PlannedRooms(ctx) +} + func (p *Plexams) RoomFromName(ctx context.Context, roomName string) (*model.Room, error) { return p.dbClient.RoomFromName(ctx, roomName) } diff --git a/plexams/validate_rooms.go b/plexams/validate_rooms.go index e8fb589..1ed0430 100644 --- a/plexams/validate_rooms.go +++ b/plexams/validate_rooms.go @@ -148,6 +148,111 @@ func (p *Plexams) ValidateRoomsPerSlot() error { return nil } +func (p *Plexams) ValidateRoomsNeedRequest() error { + ctx := context.Background() + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Cyan(" validating rooms which needs requests")), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + validationMessages := make([]string, 0) + + roomTimetables, err := p.GetReservations() + if err != nil { + log.Error().Err(err).Msg("cannot get reservations") + return err + } + + bookedEntries, err := p.ExahmRoomsFromBooked() + if err != nil { + log.Error().Err(err).Msg("cannot get booked entries") + return err + } + + for _, bookedEntry := range bookedEntries { + for _, roomName := range bookedEntry.Rooms { + timeRanges, ok := roomTimetables[roomName] + if !ok { + timeRanges = make([]TimeRange, 0, 1) + } + roomTimetables[roomName] = append(timeRanges, TimeRange{ + From: bookedEntry.From, + Until: bookedEntry.Until, + }) + } + } + + log.Debug().Interface("timetables", roomTimetables).Msg("found booked and reserved rooms") + + plannedRooms, err := p.PlannedRooms(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get all planned rooms") + } + + reservationFound := 0 + +PLANNEDROOM: + for _, plannedRoom := range plannedRooms { + + if !p.roomInfo[plannedRoom.RoomName].NeedsRequest { + log.Debug().Str("room", plannedRoom.RoomName).Msg("room needs no request") + continue + } + + spinner.Message(aurora.Sprintf(aurora.Yellow("checking room %s in slot (%d/%d)"), + plannedRoom.RoomName, plannedRoom.Day, plannedRoom.Slot)) + + startTime := p.getSlotTime(plannedRoom.Day, plannedRoom.Slot).Local() + endTime := startTime.Add(time.Duration(plannedRoom.Duration) * time.Minute) + + for _, timerange := range roomTimetables[plannedRoom.RoomName] { + if timerange.From.Before(startTime) && timerange.Until.After(endTime) { + log.Debug().Str("room", plannedRoom.RoomName).Msg("found reservation") + reservationFound++ + continue PLANNEDROOM + } + } + + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("No Reservation for room %s found in slot (%d/%d)"), + aurora.Magenta(plannedRoom.RoomName), aurora.Blue(plannedRoom.Day), aurora.Blue(plannedRoom.Slot))) + } + + if len(validationMessages) > 0 { + spinner.StopFailMessage(aurora.Sprintf(aurora.Red("%d problems found"), len(validationMessages))) + err = spinner.StopFail() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + for _, msg := range validationMessages { + fmt.Printf(" ↪ %s\n", msg) + } + + } else { + spinner.StopMessage(aurora.Sprintf(aurora.Green("found %d reservations"), reservationFound)) + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + } + + return nil +} func (p *Plexams) ValidateRoomsPerExam() error { ctx := context.Background() From 884efcf30e350f7895851b22456d8cec3c0c03f7 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Thu, 4 Jan 2024 15:29:10 +0100 Subject: [PATCH 62/78] csv exahm --- cmd/csv.go | 13 +++++++++- plexams/csv.go | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/cmd/csv.go b/cmd/csv.go index f2456f5..5aa1666 100644 --- a/cmd/csv.go +++ b/cmd/csv.go @@ -13,7 +13,8 @@ var ( Use: "csv", Short: "csv [subcommand]", Long: `Generate various CSVs. - draft [program] - generate csv for program`, + draft [program] - generate csv for program + exahm - csv for EXaHM/SEB exams.`, Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { plexams := initPlexamsConfig() @@ -32,6 +33,16 @@ var ( os.Exit(1) } + case "exahm": + if len(Outfile) == 0 { + Outfile = fmt.Sprintf("Prüfungsplanung_EXaHM_SEB_FK07.csv") + } + fmt.Printf("generating %s\n", Outfile) + err := plexams.CsvForEXaHM(Outfile) + if err != nil { + os.Exit(1) + } + default: fmt.Println("pdf called with unknown sub command") } diff --git a/plexams/csv.go b/plexams/csv.go index 8df3515..2e429ce 100644 --- a/plexams/csv.go +++ b/plexams/csv.go @@ -2,9 +2,11 @@ package plexams import ( "context" + "fmt" "os" "sort" + set "github.com/deckarep/golang-set/v2" "github.com/jszwec/csvutil" "github.com/rs/zerolog/log" ) @@ -68,3 +70,71 @@ func (p *Plexams) CsvForProgram(program, filename string) error { return os.WriteFile(filename, b, 0644) } + +type CsvExamEXaHM struct { + Ancode int `csv:"Ancode"` + Module string `csv:"Modul"` + MainExamer string `csv:"Erstprüfer:in"` + ExamDate string `csv:"Termin"` + MaxDuration int `csv:"Maximale Länge"` + Students int `csv:"Anmeldungen"` + Rooms string `csv:"Räume"` + Type string `csv:"Typ"` +} + +func (p *Plexams) CsvForEXaHM(filename string) error { + ctx := context.Background() + exams, err := p.PlannedExams(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get planned exams") + return err + } + + exahmExams := make([]CsvExamEXaHM, 0) + + for _, exam := range exams { + if exam.Constraints == nil || exam.Constraints.RoomConstraints == nil || + (!exam.Constraints.RoomConstraints.ExahmRooms && !exam.Constraints.RoomConstraints.Seb) { + continue + } + + examDate := "fehlt" + if exam.PlanEntry != nil { + examDate = exam.PlanEntry.Starttime.Local().Format("02.01.06, 15:04 Uhr") + } + + var rooms []string + if len(exam.PlannedRooms) == 0 { + rooms = []string{"noch nicht geplant"} + } else { + roomSet := set.NewSet[string]() + for _, room := range exam.PlannedRooms { + roomSet.Add(room.RoomName) + } + rooms = roomSet.ToSlice() + } + + typeOfExam := "EXaHM" + if exam.Constraints.RoomConstraints.Seb { + typeOfExam = "SEB" + } + + exahmExams = append(exahmExams, CsvExamEXaHM{ + Ancode: exam.Ancode, + Module: exam.ZpaExam.Module, + MainExamer: exam.ZpaExam.MainExamer, + ExamDate: examDate, + MaxDuration: exam.MaxDuration, + Students: exam.StudentRegsCount, + Rooms: fmt.Sprintf("%v", rooms), + Type: typeOfExam, + }) + } + + b, err := csvutil.Marshal(exahmExams) + if err != nil { + log.Error().Err(err).Msg("error when marshaling to csv") + } + + return os.WriteFile(filename, b, 0644) +} From 148a54fbe75f48af3299c912ae57fcfb059705c7 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Sat, 6 Jan 2024 12:30:42 +0100 Subject: [PATCH 63/78] pimp validate zpa --rooms --- cmd/validate.go | 3 +- plexams/validate_zpa.go | 75 +++++++++++++++++++--- plexams/zpa_post.go | 137 ++++++++++++++++++++++++++++------------ 3 files changed, 163 insertions(+), 52 deletions(-) diff --git a/cmd/validate.go b/cmd/validate.go index bc23bf1..9e26613 100644 --- a/cmd/validate.go +++ b/cmd/validate.go @@ -63,7 +63,6 @@ var ( log.Fatal(err) } if Rooms || Invigilators { - fmt.Println("validating zpa rooms") err := plexams.ValidateZPARooms() if err != nil { log.Fatal(err) @@ -124,7 +123,7 @@ func init() { validateCmd.Flags().IntVarP(&Sleep, "sleep", "s", 0, "sleep [s] seconds and validate again") validateCmd.Flags().IntVarP(&Ancode, "ancode", "a", 0, "show only constraints for given ancode") validateCmd.Flags().BoolVarP(&Clear, "clear", "c", false, "clear screen before output") - validateCmd.Flags().BoolVarP(&Rooms, "room", "r", false, "validate zpa rooms") + validateCmd.Flags().BoolVarP(&Rooms, "rooms", "r", false, "validate zpa rooms") validateCmd.Flags().BoolVarP(&Invigilators, "invigilators", "i", false, "validate zpa invigilators") validateCmd.Flags().BoolVarP(&OnlyPlannedByMe, "onlyplannedbyme", "o", false, "check no conflicts if both exams are not planned by me") } diff --git a/plexams/validate_zpa.go b/plexams/validate_zpa.go index 1f61e64..fae4a1c 100644 --- a/plexams/validate_zpa.go +++ b/plexams/validate_zpa.go @@ -37,7 +37,7 @@ func (p *Plexams) ValidateZPADateTimes() error { validationMessages := make([]string, 0) - spinner.Message(aurora.Sprintf(aurora.Yellow("fetching exam from ZPA"))) + spinner.Message(aurora.Sprintf(aurora.Yellow("fetching exams from ZPA"))) if err := p.SetZPA(); err != nil { return err } @@ -126,28 +126,64 @@ func (p *Plexams) ValidateZPADateTimes() error { } func (p *Plexams) ValidateZPARooms() error { + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Cyan(" validating zpa rooms")), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + validationMessages := make([]string, 0) + + spinner.Message(aurora.Sprintf(aurora.Yellow("fetching exams from ZPA"))) + if err := p.SetZPA(); err != nil { + return err + } + plannedExamsFromZPA, err := p.zpa.client.GetPlannedExams() if err != nil { return err } - plannedExams, err := p.ExamsInPlan(context.Background()) + spinner.Message(aurora.Sprintf(aurora.Yellow("fetching planned exams from db"))) + plannedExams, err := p.PlannedExams(context.Background()) if err != nil { return err } - problems := 0 + notPlannedByMe := 0 + roomsChecked := 0 // check if plexams data is on zpa for _, plannedExam := range plannedExams { - roomsForAncode, err := p.dbClient.RoomsForAncode(context.Background(), plannedExam.Exam.Ancode) + if plannedExam.Constraints != nil && plannedExam.Constraints.NotPlannedByMe { + notPlannedByMe++ + continue + } + + roomsForAncode, err := p.dbClient.PlannedRoomsForAncode(context.Background(), plannedExam.Ancode) if err != nil { - log.Error().Err(err).Int("ancode", plannedExam.Exam.Ancode).Msg("cannot get planned rooms for ancode") + log.Error().Err(err).Int("ancode", plannedExam.Ancode).Msg("cannot get planned rooms for ancode") } for _, room := range roomsForAncode { if room.RoomName == "No Room" { continue } + roomsChecked++ found := false for _, zpaExam := range plannedExamsFromZPA { if room.Ancode == zpaExam.Ancode && @@ -155,21 +191,40 @@ func (p *Plexams) ValidateZPARooms() error { room.Duration == zpaExam.Duration && room.Handicap == zpaExam.IsHandicap && room.Reserve == zpaExam.IsReserve && - (room.SeatsPlanned == zpaExam.Number || zpaExam.RoomName == "ONLINE") { + (len(room.StudentsInRoom) <= zpaExam.Number || // if more than one NTA in the room + zpaExam.RoomName == "ONLINE") { found = true break } } if !found { - problems++ - color.Red.Printf("room not found in ZPA\n %+v\n", room) + validationMessages = append(validationMessages, aurora.Sprintf( + aurora.Red("room %s for exam %d. %s (%s) not found in ZPA"), + aurora.Magenta(room.RoomName), + aurora.Cyan(plannedExam.Ancode), aurora.Cyan(plannedExam.ZpaExam.Module), aurora.Cyan(plannedExam.ZpaExam.MainExamer))) } } } - if problems == 0 { - color.Green.Println("all rooms planned found in zpa") + if len(validationMessages) > 0 { + spinner.StopFailMessage(aurora.Sprintf(aurora.Red("%d problems found"), len(validationMessages))) + err = spinner.StopFail() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + for _, msg := range validationMessages { + fmt.Printf(" ↪ %s\n", msg) + } + + } else { + spinner.StopMessage(aurora.Sprintf( + aurora.Green("%d planned exams (%d not planned by me) with %d room entries are correct"), + len(plannedExams), notPlannedByMe, roomsChecked)) + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } } // TODO: check if zpa data is in plexams diff --git a/plexams/zpa_post.go b/plexams/zpa_post.go index abe7fa3..bb7213b 100644 --- a/plexams/zpa_post.go +++ b/plexams/zpa_post.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "strings" set "github.com/deckarep/golang-set/v2" "github.com/obcode/plexams.go/graph/model" @@ -154,46 +155,102 @@ func (p *Plexams) UploadPlan(ctx context.Context, withRooms, withInvigilators, u // reserveInvigilatorID = invigilator.ID // } - // if withRooms { - // roomsForAncode, err := p.dbClient.RoomsForAncode(ctx, exam.Exam.Ancode) - // if err != nil { - // log.Error().Err(err).Int("ancode", exam.Exam.Ancode).Msg("cannot get rooms for ancode") - // } else { - // if len(roomsForAncode) > 0 { - // rooms = make([]*model.ZPAExamPlanRoom, 0, len(roomsForAncode)) - // for _, roomForAncode := range roomsForAncode { - // if roomForAncode.RoomName == "No Room" { - // continue - // } - - // invigilatorID := 0 - // if withInvigilators { - // invigilator, err := p.GetInvigilatorInSlot(ctx, roomForAncode.RoomName, slot.DayNumber, slot.SlotNumber) - // if err != nil { - // log.Error().Err(err).Int("ancode", exam.Exam.Ancode).Str("room", roomForAncode.RoomName). - // Msg("cannot get invigilator for room") - // return nil, err - // } - // invigilatorID = invigilator.ID - // } - - // roomName := roomForAncode.RoomName - // if strings.HasPrefix(roomName, "ONLINE") { - // roomName = "ONLINE" - // } - - // rooms = append(rooms, &model.ZPAExamPlanRoom{ - // RoomName: roomName, - // InvigilatorID: invigilatorID, - // Duration: roomForAncode.Duration, - // IsReserve: roomForAncode.Reserve, - // StudentCount: roomForAncode.SeatsPlanned, - // IsHandicap: roomForAncode.Handicap, - // }) - // } - // } - // } - // } + if withRooms { + roomsForAncode, err := p.dbClient.PlannedRoomsForAncode(ctx, exam.Ancode) + if err != nil { + log.Error().Err(err).Int("ancode", exam.Ancode).Msg("cannot get rooms for ancode") + } else { + if len(roomsForAncode) > 0 { + type roomNameWithDuration struct { + name string + duration int + } + roomsMap := make(map[roomNameWithDuration][]*model.ZPAExamPlanRoom) + + for _, roomForAncode := range roomsForAncode { + if roomForAncode.RoomName == "No Room" { + continue + } + + // invigilatorID := 0 + // if withInvigilators { + // invigilator, err := p.GetInvigilatorInSlot(ctx, roomForAncode.RoomName, slot.DayNumber, slot.SlotNumber) + // if err != nil { + // log.Error().Err(err).Int("ancode", exam.Exam.Ancode).Str("room", roomForAncode.RoomName). + // Msg("cannot get invigilator for room") + // return nil, err + // } + // invigilatorID = invigilator.ID + // } + + roomName := roomForAncode.RoomName + if strings.HasPrefix(roomName, "ONLINE") { + roomName = "ONLINE" + } + + roomNameWithDuration := roomNameWithDuration{ + name: roomName, + duration: roomForAncode.Duration, + } + + roomWithDuration, ok := roomsMap[roomNameWithDuration] + if !ok { + roomWithDuration = make([]*model.ZPAExamPlanRoom, 0, 1) + } + roomsMap[roomNameWithDuration] = append(roomWithDuration, &model.ZPAExamPlanRoom{ + RoomName: roomName, + InvigilatorID: 0, // invigilatorID, + Duration: roomForAncode.Duration, + IsReserve: roomForAncode.Reserve, + StudentCount: len(roomForAncode.StudentsInRoom), + IsHandicap: roomForAncode.Handicap, + }) + } + + mergeRooms := func(roomWithSameDuration []*model.ZPAExamPlanRoom) []*model.ZPAExamPlanRoom { + for i := 0; i < len(roomWithSameDuration); i++ { + current := roomWithSameDuration[i] + if current == nil { + continue + } + for j := i + 1; j < len(roomWithSameDuration); j++ { + other := roomWithSameDuration[j] + if other == nil { + continue + } + if current.IsHandicap && other.IsHandicap || + !current.IsHandicap && !other.IsHandicap { + log.Debug().Int("ancode", exam.Ancode).Str("room", current.RoomName).Msg("found rooms to merge") + roomWithSameDuration[i].StudentCount += other.StudentCount + roomWithSameDuration[i].IsReserve = false + roomWithSameDuration[j] = nil + } + } + } + + rooms := make([]*model.ZPAExamPlanRoom, 0) + for _, room := range roomWithSameDuration { + if room != nil { + rooms = append(rooms, room) + } + } + return rooms + } + rooms = make([]*model.ZPAExamPlanRoom, 0, len(roomsForAncode)) + for _, roomWithSameDuration := range roomsMap { + if len(roomWithSameDuration) == 0 { + continue + } + if len(roomWithSameDuration) == 1 { + rooms = append(rooms, roomWithSameDuration...) + } else { + log.Debug().Int("ancode", exam.Ancode).Interface("roomWithSameDuration", roomWithSameDuration).Msg("more than one room with same duration") + rooms = append(rooms, mergeRooms(roomWithSameDuration)...) + } + } + } + } + } exams = append(exams, &model.ZPAExamPlan{ Semester: p.semester, From 32ec48cb7c7587f46e629b1d2af4a62309ae8f42 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Sat, 6 Jan 2024 12:33:13 +0100 Subject: [PATCH 64/78] make linter happy --- cmd/csv.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/csv.go b/cmd/csv.go index 5aa1666..55036f3 100644 --- a/cmd/csv.go +++ b/cmd/csv.go @@ -35,7 +35,7 @@ var ( case "exahm": if len(Outfile) == 0 { - Outfile = fmt.Sprintf("Prüfungsplanung_EXaHM_SEB_FK07.csv") + Outfile = "Prüfungsplanung_EXaHM_SEB_FK07.csv" } fmt.Printf("generating %s\n", Outfile) err := plexams.CsvForEXaHM(Outfile) From e1af49611984062ed718025f512ba2393647bf64 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Sat, 6 Jan 2024 18:59:59 +0100 Subject: [PATCH 65/78] validate db and fix starttime --- cmd/validate.go | 4 ++ graph/plan.graphqls | 1 + plexams/plannedExams.go | 10 +++++ plexams/validate_db.go | 91 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+) create mode 100644 plexams/validate_db.go diff --git a/cmd/validate.go b/cmd/validate.go index 9e26613..73ca49d 100644 --- a/cmd/validate.go +++ b/cmd/validate.go @@ -18,6 +18,7 @@ var ( all --- guess what :-) conflicts --- check conflicts for each student constraints --- check if constraints hold + db --- data base entries rooms --- check room constraints zpa --- check if the plan on ZPA is the same here invigilator-reqs @@ -48,6 +49,9 @@ var ( case "constraints": validations = append(validations, plexams.ValidateConstraints) + case "db": + validations = append(validations, plexams.ValidateDB) + case "rooms": validations = append(validations, []func() error{ diff --git a/graph/plan.graphqls b/graph/plan.graphqls index 78c6e65..70e9eb8 100644 --- a/graph/plan.graphqls +++ b/graph/plan.graphqls @@ -79,6 +79,7 @@ type ExamerInPlan { mainExamerID: Int! } +# TODO: remove starttime!!! type PlanEntry { dayNumber: Int! slotNumber: Int! diff --git a/plexams/plannedExams.go b/plexams/plannedExams.go index c980854..b3e5b7d 100644 --- a/plexams/plannedExams.go +++ b/plexams/plannedExams.go @@ -45,6 +45,15 @@ func (p *Plexams) PlannedExam(ctx context.Context, ancode int) (*model.PlannedEx }, err } +func (p *Plexams) setCorrectStarttime(planEntry *model.PlanEntry) { + slottime := p.getSlotTime(planEntry.DayNumber, planEntry.SlotNumber) + if !slottime.Equal(planEntry.Starttime) { + log.Error().Int("ancode", planEntry.Ancode).Int("day", planEntry.DayNumber).Int("slot", planEntry.SlotNumber). + Str("starttime", planEntry.Starttime.Format("02.01.06, 15:04")).Str("slottime", slottime.Format("02.01.06, 15:04")).Msg("starttime not correct in plan entry") + planEntry.Starttime = slottime + } +} + func (p *Plexams) PlannedExams(ctx context.Context) ([]*model.PlannedExam, error) { exams, err := p.GeneratedExams(ctx) if err != nil { @@ -60,6 +69,7 @@ func (p *Plexams) PlannedExams(ctx context.Context) ([]*model.PlannedExam, error planEntryMap := make(map[int]*model.PlanEntry) for _, planEntry := range planEntries { + p.setCorrectStarttime(planEntry) planEntryMap[planEntry.Ancode] = planEntry } diff --git a/plexams/validate_db.go b/plexams/validate_db.go new file mode 100644 index 0000000..82ada6a --- /dev/null +++ b/plexams/validate_db.go @@ -0,0 +1,91 @@ +package plexams + +import ( + "context" + "fmt" + "time" + + "github.com/logrusorgru/aurora" + "github.com/obcode/plexams.go/graph/model" + "github.com/rs/zerolog/log" + "github.com/theckman/yacspin" +) + +func (p *Plexams) ValidateDB() error { + ctx := context.Background() + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Cyan(" validating data base entries")), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + validationMessages := make([]string, 0) + + planEntries, err := p.dbClient.PlanEntries(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get planEntries") + } + + spinner.Message(aurora.Sprintf(aurora.Yellow(" validating only one plan entry per ancode"))) + planEntryMap := make(map[int]*model.PlanEntry) + for _, planEntry := range planEntries { + otherEntry, ok := planEntryMap[planEntry.Ancode] + if ok { + validationMessages = append(validationMessages, aurora.Sprintf( + aurora.Red("more than one plan entry for ancode %d: %v and %v"), + aurora.Magenta(planEntry.Ancode), + aurora.Cyan(otherEntry), aurora.Cyan(planEntry), + )) + } + } + + spinner.Message(aurora.Sprintf(aurora.Yellow(" validating correct start times"))) + for _, planEntry := range planEntries { + slottime := p.getSlotTime(planEntry.DayNumber, planEntry.SlotNumber) + if !slottime.Equal(planEntry.Starttime) { + validationMessages = append(validationMessages, aurora.Sprintf( + aurora.Red("wrong starttime for ancode %d: want %s, got %s"), + aurora.Magenta(planEntry.Ancode), + aurora.Cyan(slottime.Local().Format("02.01.06, 15:04")), + aurora.Cyan(planEntry.Starttime.Local().Format("02.01.06, 15:04")), + )) + } + } + + if len(validationMessages) > 0 { + spinner.StopFailMessage(aurora.Sprintf(aurora.Red("%d problems"), + len(validationMessages))) + err = spinner.StopFail() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + for _, msg := range validationMessages { + fmt.Printf("%s\n", msg) + } + + } else { + spinner.StopMessage(aurora.Sprintf(aurora.Green("%d plan entries are okay"), + len(planEntries))) + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + } + + return nil +} From 703b596e01d161b31aa65b1bf3842fa05336d850 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Sun, 7 Jan 2024 13:32:52 +0100 Subject: [PATCH 66/78] add to validate all --- cmd/validate.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/validate.go b/cmd/validate.go index 73ca49d..82e9d2d 100644 --- a/cmd/validate.go +++ b/cmd/validate.go @@ -34,9 +34,11 @@ var ( switch arg { case "all": validations = append(validations, []func() error{ + plexams.ValidateDB, func() error { return plexams.ValidateConflicts(OnlyPlannedByMe, Ancode) }, plexams.ValidateConstraints, plexams.ValidateRoomsPerSlot, + plexams.ValidateRoomsNeedRequest, plexams.ValidateRoomsPerExam, plexams.ValidateRoomsTimeDistance, }...) From 341cfac334000c5ff38a8191f22f38ce7fc65a5c Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Mon, 8 Jan 2024 15:25:25 +0100 Subject: [PATCH 67/78] use slot time and not plannedEntry time --- plexams/plannedExams.go | 12 ------------ plexams/plexams.go | 2 +- plexams/validate_zpa.go | 5 +++-- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/plexams/plannedExams.go b/plexams/plannedExams.go index b3e5b7d..ee10882 100644 --- a/plexams/plannedExams.go +++ b/plexams/plannedExams.go @@ -2,7 +2,6 @@ package plexams import ( "context" - "time" "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" @@ -121,14 +120,3 @@ func (p *Plexams) PlannedExamsForProgram(ctx context.Context, program string, on return plannedExamsForProgram, nil } - -// TODO: needed? -// nolint -func (p *Plexams) getTimeForSlot(dayNumber, slotNumber int) *time.Time { - for _, slot := range p.semesterConfig.Slots { - if slot.DayNumber == dayNumber && slot.SlotNumber == slotNumber { - return &slot.Starttime - } - } - return nil -} diff --git a/plexams/plexams.go b/plexams/plexams.go index b338d2d..331efb4 100644 --- a/plexams/plexams.go +++ b/plexams/plexams.go @@ -225,7 +225,7 @@ func (p *Plexams) GetSemesterConfig() *model.SemesterConfig { func (p *Plexams) getSlotTime(dayNumber, slotNumber int) time.Time { for _, slot := range p.semesterConfig.Slots { if slot.DayNumber == dayNumber && slot.SlotNumber == slotNumber { - return slot.Starttime + return slot.Starttime.Local() } } return time.Date(0, 0, 0, 0, 0, 0, 0, nil) diff --git a/plexams/validate_zpa.go b/plexams/validate_zpa.go index fae4a1c..27100aa 100644 --- a/plexams/validate_zpa.go +++ b/plexams/validate_zpa.go @@ -78,8 +78,9 @@ func (p *Plexams) ValidateZPADateTimes() error { plannedExamDate := "-" plannedExamStarttime := "-" if !shouldHaveNoTimeAndDate && plannedExam.PlanEntry != nil { - plannedExamDate = plannedExam.PlanEntry.Starttime.Local().Format("2006-01-02") - plannedExamStarttime = plannedExam.PlanEntry.Starttime.Local().Format("15:04:05") + starttime := p.getSlotTime(plannedExam.PlanEntry.DayNumber, plannedExam.PlanEntry.SlotNumber) + plannedExamDate = starttime.Local().Format("2006-01-02") + plannedExamStarttime = starttime.Local().Format("15:04:05") } if zpaExam.Date != plannedExamDate || From 41c4ee0fbe5310f2553fc6eba82746a5aa9ab448 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Mon, 8 Jan 2024 20:57:14 +0100 Subject: [PATCH 68/78] rm starttime from plan entry --- graph/generated/generated.go | 62 ++---------------------------------- graph/model/models_gen.go | 9 +++--- graph/plan.graphqls | 2 +- plexams/csv.go | 6 ++-- plexams/pdfDraft.go | 3 +- plexams/plan.go | 1 - plexams/plannedExams.go | 10 ------ plexams/validate_db.go | 13 -------- plexams/zpa_post.go | 6 ++-- 9 files changed, 17 insertions(+), 95 deletions(-) diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 98fe94b..9239b2a 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -342,7 +342,6 @@ type ComplexityRoot struct { DayNumber func(childComplexity int) int Locked func(childComplexity int) int SlotNumber func(childComplexity int) int - Starttime func(childComplexity int) int } PlannedExam struct { @@ -2191,13 +2190,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PlanEntry.SlotNumber(childComplexity), true - case "PlanEntry.starttime": - if e.complexity.PlanEntry.Starttime == nil { - break - } - - return e.complexity.PlanEntry.Starttime(childComplexity), true - case "PlannedExam.ancode": if e.complexity.PlannedExam.Ancode == nil { break @@ -4387,10 +4379,11 @@ type ExamerInPlan { mainExamerID: Int! } +# TODO: remove starttime!!! type PlanEntry { dayNumber: Int! slotNumber: Int! - starttime: Time! + # starttime: Time! ancode: Int! locked: Boolean! } @@ -14894,50 +14887,6 @@ func (ec *executionContext) fieldContext_PlanEntry_slotNumber(ctx context.Contex return fc, nil } -func (ec *executionContext) _PlanEntry_starttime(ctx context.Context, field graphql.CollectedField, obj *model.PlanEntry) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_PlanEntry_starttime(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Starttime, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(time.Time) - fc.Result = res - return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_PlanEntry_starttime(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "PlanEntry", - Field: field, - IsMethod: false, - IsResolver: false, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Time does not have child fields") - }, - } - return fc, nil -} - func (ec *executionContext) _PlanEntry_ancode(ctx context.Context, field graphql.CollectedField, obj *model.PlanEntry) (ret graphql.Marshaler) { fc, err := ec.fieldContext_PlanEntry_ancode(ctx, field) if err != nil { @@ -15503,8 +15452,6 @@ func (ec *executionContext) fieldContext_PlannedExam_planEntry(ctx context.Conte return ec.fieldContext_PlanEntry_dayNumber(ctx, field) case "slotNumber": return ec.fieldContext_PlanEntry_slotNumber(ctx, field) - case "starttime": - return ec.fieldContext_PlanEntry_starttime(ctx, field) case "ancode": return ec.fieldContext_PlanEntry_ancode(ctx, field) case "locked": @@ -30571,11 +30518,6 @@ func (ec *executionContext) _PlanEntry(ctx context.Context, sel ast.SelectionSet if out.Values[i] == graphql.Null { out.Invalids++ } - case "starttime": - out.Values[i] = ec._PlanEntry_starttime(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } case "ancode": out.Values[i] = ec._PlanEntry_ancode(ctx, field, obj) if out.Values[i] == graphql.Null { diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index 18ef7d6..2e4f3a7 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -261,11 +261,10 @@ type Plan struct { } type PlanEntry struct { - DayNumber int `json:"dayNumber"` - SlotNumber int `json:"slotNumber"` - Starttime time.Time `json:"starttime"` - Ancode int `json:"ancode"` - Locked bool `json:"locked"` + DayNumber int `json:"dayNumber"` + SlotNumber int `json:"slotNumber"` + Ancode int `json:"ancode"` + Locked bool `json:"locked"` } type PlannedExam struct { diff --git a/graph/plan.graphqls b/graph/plan.graphqls index 70e9eb8..42429e9 100644 --- a/graph/plan.graphqls +++ b/graph/plan.graphqls @@ -83,7 +83,7 @@ type ExamerInPlan { type PlanEntry { dayNumber: Int! slotNumber: Int! - starttime: Time! + # starttime: Time! ancode: Int! locked: Boolean! } diff --git a/plexams/csv.go b/plexams/csv.go index 2e429ce..fed92fd 100644 --- a/plexams/csv.go +++ b/plexams/csv.go @@ -45,7 +45,8 @@ func (p *Plexams) CsvForProgram(program, filename string) error { examDate := "fehlt" if exam.PlanEntry != nil { - examDate = exam.PlanEntry.Starttime.Local().Format("02.01.06, 15:04 Uhr") + starttime := p.getSlotTime(exam.PlanEntry.DayNumber, exam.PlanEntry.SlotNumber) + examDate = starttime.Local().Format("02.01.06, 15:04 Uhr") } csvExams[primussAncode] = CsvExam{ @@ -100,7 +101,8 @@ func (p *Plexams) CsvForEXaHM(filename string) error { examDate := "fehlt" if exam.PlanEntry != nil { - examDate = exam.PlanEntry.Starttime.Local().Format("02.01.06, 15:04 Uhr") + starttime := p.getSlotTime(exam.PlanEntry.DayNumber, exam.PlanEntry.SlotNumber) + examDate = starttime.Local().Format("02.01.06, 15:04 Uhr") } var rooms []string diff --git a/plexams/pdfDraft.go b/plexams/pdfDraft.go index 877a85e..f62a4eb 100644 --- a/plexams/pdfDraft.go +++ b/plexams/pdfDraft.go @@ -243,9 +243,10 @@ func (p *Plexams) tableForProgram(ctx context.Context, program, programLong stri []string{strconv.Itoa(exam.Ancode), exam.ZpaExam.Module, exam.ZpaExam.MainExamer, "fehlt noch"}) } else { + starttime := p.getSlotTime(exam.PlanEntry.DayNumber, exam.PlanEntry.SlotNumber) contents = append(contents, []string{strconv.Itoa(exam.Ancode), exam.ZpaExam.Module, exam.ZpaExam.MainExamer, - r.Replace(exam.PlanEntry.Starttime.Local().Format("Mon. 02.01.06, 15:04 Uhr"))}) + r.Replace(starttime.Local().Format("Mon. 02.01.06, 15:04 Uhr"))}) } } diff --git a/plexams/plan.go b/plexams/plan.go index 7f2892b..f42107d 100644 --- a/plexams/plan.go +++ b/plexams/plan.go @@ -56,7 +56,6 @@ func (p *Plexams) AddExamToSlot(ctx context.Context, ancode int, dayNumber int, return p.dbClient.AddExamToSlot(ctx, &model.PlanEntry{ DayNumber: slot.DayNumber, SlotNumber: slot.SlotNumber, - Starttime: slot.Starttime, Ancode: ancode, Locked: false, }) diff --git a/plexams/plannedExams.go b/plexams/plannedExams.go index ee10882..53ea87f 100644 --- a/plexams/plannedExams.go +++ b/plexams/plannedExams.go @@ -44,15 +44,6 @@ func (p *Plexams) PlannedExam(ctx context.Context, ancode int) (*model.PlannedEx }, err } -func (p *Plexams) setCorrectStarttime(planEntry *model.PlanEntry) { - slottime := p.getSlotTime(planEntry.DayNumber, planEntry.SlotNumber) - if !slottime.Equal(planEntry.Starttime) { - log.Error().Int("ancode", planEntry.Ancode).Int("day", planEntry.DayNumber).Int("slot", planEntry.SlotNumber). - Str("starttime", planEntry.Starttime.Format("02.01.06, 15:04")).Str("slottime", slottime.Format("02.01.06, 15:04")).Msg("starttime not correct in plan entry") - planEntry.Starttime = slottime - } -} - func (p *Plexams) PlannedExams(ctx context.Context) ([]*model.PlannedExam, error) { exams, err := p.GeneratedExams(ctx) if err != nil { @@ -68,7 +59,6 @@ func (p *Plexams) PlannedExams(ctx context.Context) ([]*model.PlannedExam, error planEntryMap := make(map[int]*model.PlanEntry) for _, planEntry := range planEntries { - p.setCorrectStarttime(planEntry) planEntryMap[planEntry.Ancode] = planEntry } diff --git a/plexams/validate_db.go b/plexams/validate_db.go index 82ada6a..c066d78 100644 --- a/plexams/validate_db.go +++ b/plexams/validate_db.go @@ -54,19 +54,6 @@ func (p *Plexams) ValidateDB() error { } } - spinner.Message(aurora.Sprintf(aurora.Yellow(" validating correct start times"))) - for _, planEntry := range planEntries { - slottime := p.getSlotTime(planEntry.DayNumber, planEntry.SlotNumber) - if !slottime.Equal(planEntry.Starttime) { - validationMessages = append(validationMessages, aurora.Sprintf( - aurora.Red("wrong starttime for ancode %d: want %s, got %s"), - aurora.Magenta(planEntry.Ancode), - aurora.Cyan(slottime.Local().Format("02.01.06, 15:04")), - aurora.Cyan(planEntry.Starttime.Local().Format("02.01.06, 15:04")), - )) - } - } - if len(validationMessages) > 0 { spinner.StopFailMessage(aurora.Sprintf(aurora.Red("%d problems"), len(validationMessages))) diff --git a/plexams/zpa_post.go b/plexams/zpa_post.go index bb7213b..2712746 100644 --- a/plexams/zpa_post.go +++ b/plexams/zpa_post.go @@ -252,11 +252,13 @@ func (p *Plexams) UploadPlan(ctx context.Context, withRooms, withInvigilators, u } } + starttime := p.getSlotTime(exam.PlanEntry.DayNumber, exam.PlanEntry.SlotNumber) + exams = append(exams, &model.ZPAExamPlan{ Semester: p.semester, AnCode: exam.ZpaExam.AnCode, - Date: exam.PlanEntry.Starttime.Local().Format("02.01.2006"), - Time: exam.PlanEntry.Starttime.Local().Format("15:04"), + Date: starttime.Local().Format("02.01.2006"), + Time: starttime.Local().Format("15:04"), StudentCount: exam.StudentRegsCount, ReserveInvigilatorID: reserveInvigilatorID, Rooms: rooms, From 7c55165f3ed2f91917b638c8ea4ed65238c90d95 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Tue, 9 Jan 2024 21:01:44 +0100 Subject: [PATCH 69/78] export rooms for MUC.DAI --- cmd/csv.go | 17 +++++++++-------- plexams/csv.go | 44 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/cmd/csv.go b/cmd/csv.go index 55036f3..13f02de 100644 --- a/cmd/csv.go +++ b/cmd/csv.go @@ -24,21 +24,21 @@ var ( log.Fatal("need program") } program := args[1] - if len(Outfile) == 0 { - Outfile = fmt.Sprintf("VorläufigePrüfungsplanung_FK07_%s.csv", program) + if len(Csvfile) == 0 { + Csvfile = fmt.Sprintf("VorläufigePrüfungsplanung_FK07_%s.csv", program) } - fmt.Printf("generating %s\n", Outfile) - err := plexams.CsvForProgram(program, Outfile) + fmt.Printf("generating %s\n", Csvfile) + err := plexams.CsvForProgram(program, Csvfile) if err != nil { os.Exit(1) } case "exahm": - if len(Outfile) == 0 { - Outfile = "Prüfungsplanung_EXaHM_SEB_FK07.csv" + if len(Csvfile) == 0 { + Csvfile = "Prüfungsplanung_EXaHM_SEB_FK07.csv" } - fmt.Printf("generating %s\n", Outfile) - err := plexams.CsvForEXaHM(Outfile) + fmt.Printf("generating %s\n", Csvfile) + err := plexams.CsvForEXaHM(Csvfile) if err != nil { os.Exit(1) } @@ -53,4 +53,5 @@ var ( func init() { rootCmd.AddCommand(csvCmd) + csvCmd.Flags().StringVarP(&Csvfile, "out", "o", "", "output (csv) file") } diff --git a/plexams/csv.go b/plexams/csv.go index fed92fd..d860371 100644 --- a/plexams/csv.go +++ b/plexams/csv.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "sort" + "strings" set "github.com/deckarep/golang-set/v2" "github.com/jszwec/csvutil" @@ -16,6 +17,8 @@ type CsvExam struct { Module string `csv:"Modul"` MainExamer string `csv:"Erstprüfer:in"` ExamDate string `csv:"Termin"` + Rooms string `csv:"Räume"` + Comment string `csv:"Anmerkungen"` } func (p *Plexams) CsvForProgram(program, filename string) error { @@ -26,7 +29,7 @@ func (p *Plexams) CsvForProgram(program, filename string) error { return err } - csvExams := make(map[int]CsvExam, 0) + csvExams := make(map[int][]CsvExam, 0) ancodes := make([]int, 0, len(exams)) for _, exam := range exams { @@ -49,11 +52,38 @@ func (p *Plexams) CsvForProgram(program, filename string) error { examDate = starttime.Local().Format("02.01.06, 15:04 Uhr") } - csvExams[primussAncode] = CsvExam{ - Ancode: primussAncode, - Module: exam.ZpaExam.Module, - MainExamer: exam.ZpaExam.MainExamer, - ExamDate: examDate, + if exam.PlannedRooms != nil { + csvEntries := make([]CsvExam, 0, len(exam.PlannedRooms)) + for _, room := range exam.PlannedRooms { + var sb strings.Builder + if room.Handicap { + sb.WriteString(fmt.Sprintf("NTA %d Min., ", room.Duration)) + } + if room.Reserve { + sb.WriteString("Reserveraum, nicht veröffentlichen, ") + } + sb.WriteString(fmt.Sprintf("%d Studierende eingeplant", len(room.StudentsInRoom))) + csvEntries = append(csvEntries, CsvExam{ + Ancode: primussAncode, + Module: exam.ZpaExam.Module, + MainExamer: exam.ZpaExam.MainExamer, + ExamDate: examDate, + Rooms: room.RoomName, + Comment: sb.String(), + }) + } + + // examRooms = sb.String() + + csvExams[primussAncode] = csvEntries + } else { + csvExams[primussAncode] = []CsvExam{{ + Ancode: primussAncode, + Module: exam.ZpaExam.Module, + MainExamer: exam.ZpaExam.MainExamer, + ExamDate: examDate, + Rooms: "fehlen noch", + }} } } @@ -61,7 +91,7 @@ func (p *Plexams) CsvForProgram(program, filename string) error { csvExamsSlice := make([]CsvExam, 0, len(exams)) for _, ancode := range ancodes { - csvExamsSlice = append(csvExamsSlice, csvExams[ancode]) + csvExamsSlice = append(csvExamsSlice, csvExams[ancode]...) } b, err := csvutil.Marshal(csvExamsSlice) From c87d9a24aa23de7afd36795ff35bc00d907965d3 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Wed, 10 Jan 2024 13:26:50 +0100 Subject: [PATCH 70/78] fix exam days for in invigilators --- db/generatedExams.go | 21 +++++ db/plannedExams.go | 4 +- graph/generated/generated.go | 152 ++++++++++++++++---------------- graph/invigilation.graphqls | 1 + graph/invigilation.resolvers.go | 5 ++ graph/query.graphqls | 1 - graph/query.resolvers.go | 5 -- plexams/generatedExams.go | 6 +- plexams/invigilators.go | 20 +++-- plexams/plannedExams.go | 21 +++++ 10 files changed, 145 insertions(+), 91 deletions(-) diff --git a/db/generatedExams.go b/db/generatedExams.go index 1991dbf..1f2a5a7 100644 --- a/db/generatedExams.go +++ b/db/generatedExams.go @@ -53,6 +53,27 @@ func (db *DB) GetGeneratedExams(ctx context.Context) ([]*model.GeneratedExam, er return exams, nil } +func (db *DB) GetGeneratedExamsForExamer(ctx context.Context, examerID int) ([]*model.GeneratedExam, error) { + collection := db.Client.Database(db.databaseName).Collection(collectionGeneratedExams) + + cur, err := collection.Find(ctx, bson.D{{Key: "zpaexam.mainexamerid", Value: examerID}}) + if err != nil { + log.Error().Err(err).Msg("cannot get generated exams") + return nil, err + } + defer cur.Close(ctx) + + exams := make([]*model.GeneratedExam, 0) + + err = cur.All(ctx, &exams) + if err != nil { + log.Error().Err(err).Msg("cannot decode generated exams") + return nil, err + } + + return exams, nil +} + func (db *DB) GetGeneratedExam(ctx context.Context, ancode int) (*model.GeneratedExam, error) { collection := db.Client.Database(db.databaseName).Collection(collectionGeneratedExams) diff --git a/db/plannedExams.go b/db/plannedExams.go index 8e6b888..e4042eb 100644 --- a/db/plannedExams.go +++ b/db/plannedExams.go @@ -35,7 +35,7 @@ func (db *DB) ExamsInSlot(ctx context.Context, day int, time int) ([]*model.Exam return exams, nil } -// TODO: rewrite me +// Deprecated: rm me func (db *DB) PlannedExamsByMainExamer(ctx context.Context, examerID int) ([]*model.ExamInPlan, error) { collection := db.getCollectionSemester(collectionExamsInPlan) @@ -57,3 +57,5 @@ func (db *DB) PlannedExamsByMainExamer(ctx context.Context, examerID int) ([]*mo return exams, nil } + +// func (db *DB) diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 9239b2a..60700c4 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -719,7 +719,6 @@ type QueryResolver interface { ExamsInSlotWithRooms(ctx context.Context, day int, time int) ([]*model.ExamWithRegsAndRooms, error) RoomsWithConstraints(ctx context.Context, handicap bool, lab bool, placesWithSocket bool, exahm *bool) ([]*model.Room, error) RoomsForSlot(ctx context.Context, day int, time int) (*model.SlotWithRooms, error) - InvigilatorsWithReq(ctx context.Context) ([]*model.Invigilator, error) RoomsWithInvigilationsForSlot(ctx context.Context, day int, time int) (*model.InvigilationSlot, error) InvigilatorsForDay(ctx context.Context, day int) (*model.InvigilatorsForDay, error) DayOkForInvigilator(ctx context.Context, day int, invigilatorID int) (*bool, error) @@ -734,6 +733,7 @@ type QueryResolver interface { Exam(ctx context.Context, ancode int) (*model.Exam, error) Exams(ctx context.Context) ([]*model.Exam, error) InvigilatorTodos(ctx context.Context) (*model.InvigilationTodos, error) + InvigilatorsWithReq(ctx context.Context) ([]*model.Invigilator, error) Ntas(ctx context.Context) ([]*model.NTA, error) NtasWithRegs(ctx context.Context) ([]*model.Student, error) AllProgramsInPlan(ctx context.Context) ([]string, error) @@ -4140,6 +4140,7 @@ type Exam { `, BuiltIn: false}, {Name: "../invigilation.graphqls", Input: `extend type Query { invigilatorTodos: InvigilationTodos + invigilatorsWithReq: [Invigilator!]! } type Invigilation { @@ -4511,7 +4512,6 @@ type ConflictsPerProgramAncode { roomsForSlot(day: Int!, time: Int!): SlotWithRooms # Invigilators - invigilatorsWithReq: [Invigilator!]! roomsWithInvigilationsForSlot(day: Int!, time: Int!): InvigilationSlot invigilatorsForDay(day: Int!): InvigilatorsForDay dayOkForInvigilator(day: Int!, invigilatorID: Int!): Boolean @@ -18292,58 +18292,6 @@ func (ec *executionContext) fieldContext_Query_roomsForSlot(ctx context.Context, return fc, nil } -func (ec *executionContext) _Query_invigilatorsWithReq(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_invigilatorsWithReq(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().InvigilatorsWithReq(rctx) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.([]*model.Invigilator) - fc.Result = res - return ec.marshalNInvigilator2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilatorᚄ(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_invigilatorsWithReq(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "teacher": - return ec.fieldContext_Invigilator_teacher(ctx, field) - case "requirements": - return ec.fieldContext_Invigilator_requirements(ctx, field) - case "todos": - return ec.fieldContext_Invigilator_todos(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type Invigilator", field.Name) - }, - } - return fc, nil -} - func (ec *executionContext) _Query_roomsWithInvigilationsForSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_roomsWithInvigilationsForSlot(ctx, field) if err != nil { @@ -19221,6 +19169,58 @@ func (ec *executionContext) fieldContext_Query_invigilatorTodos(ctx context.Cont return fc, nil } +func (ec *executionContext) _Query_invigilatorsWithReq(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_invigilatorsWithReq(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().InvigilatorsWithReq(rctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.Invigilator) + fc.Result = res + return ec.marshalNInvigilator2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilatorᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_invigilatorsWithReq(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "teacher": + return ec.fieldContext_Invigilator_teacher(ctx, field) + case "requirements": + return ec.fieldContext_Invigilator_requirements(ctx, field) + case "todos": + return ec.fieldContext_Invigilator_todos(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Invigilator", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _Query_ntas(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_ntas(ctx, field) if err != nil { @@ -31489,28 +31489,6 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "invigilatorsWithReq": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_invigilatorsWithReq(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } - return res - } - - rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, - func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "roomsWithInvigilationsForSlot": field := field @@ -31792,6 +31770,28 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "invigilatorsWithReq": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_invigilatorsWithReq(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "ntas": field := field diff --git a/graph/invigilation.graphqls b/graph/invigilation.graphqls index b67fc24..b697f8c 100644 --- a/graph/invigilation.graphqls +++ b/graph/invigilation.graphqls @@ -1,5 +1,6 @@ extend type Query { invigilatorTodos: InvigilationTodos + invigilatorsWithReq: [Invigilator!]! } type Invigilation { diff --git a/graph/invigilation.resolvers.go b/graph/invigilation.resolvers.go index fb649cb..44c81ef 100644 --- a/graph/invigilation.resolvers.go +++ b/graph/invigilation.resolvers.go @@ -14,3 +14,8 @@ import ( func (r *queryResolver) InvigilatorTodos(ctx context.Context) (*model.InvigilationTodos, error) { return r.plexams.InvigilationTodos(ctx) } + +// InvigilatorsWithReq is the resolver for the invigilatorsWithReq field. +func (r *queryResolver) InvigilatorsWithReq(ctx context.Context) ([]*model.Invigilator, error) { + return r.plexams.InvigilatorsWithReq(ctx) +} diff --git a/graph/query.graphqls b/graph/query.graphqls index 5cbe71a..9bfd8ca 100644 --- a/graph/query.graphqls +++ b/graph/query.graphqls @@ -43,7 +43,6 @@ type Query { roomsForSlot(day: Int!, time: Int!): SlotWithRooms # Invigilators - invigilatorsWithReq: [Invigilator!]! roomsWithInvigilationsForSlot(day: Int!, time: Int!): InvigilationSlot invigilatorsForDay(day: Int!): InvigilatorsForDay dayOkForInvigilator(day: Int!, invigilatorID: Int!): Boolean diff --git a/graph/query.resolvers.go b/graph/query.resolvers.go index 9ca65c4..3483514 100644 --- a/graph/query.resolvers.go +++ b/graph/query.resolvers.go @@ -127,11 +127,6 @@ func (r *queryResolver) RoomsForSlot(ctx context.Context, day int, time int) (*m return r.plexams.RoomsForSlot(ctx, day, time) } -// InvigilatorsWithReq is the resolver for the invigilatorsWithReq field. -func (r *queryResolver) InvigilatorsWithReq(ctx context.Context) ([]*model.Invigilator, error) { - return r.plexams.InvigilatorsWithReq(ctx) -} - // RoomsWithInvigilationsForSlot is the resolver for the roomsWithInvigilationsForSlot field. func (r *queryResolver) RoomsWithInvigilationsForSlot(ctx context.Context, day int, time int) (*model.InvigilationSlot, error) { return r.plexams.RoomsWithInvigilationsForSlot(ctx, day, time) diff --git a/plexams/generatedExams.go b/plexams/generatedExams.go index 928f1b9..6f26d71 100644 --- a/plexams/generatedExams.go +++ b/plexams/generatedExams.go @@ -334,12 +334,14 @@ func (p *Plexams) GeneratedExams(ctx context.Context) ([]*model.GeneratedExam, e return p.dbClient.GetGeneratedExams(ctx) } -// GeneratedExam is the resolver for the generatedExam field. +func (p *Plexams) GeneratedExamsForExamer(ctx context.Context, examerID int) ([]*model.GeneratedExam, error) { + return p.dbClient.GetGeneratedExamsForExamer(ctx, examerID) +} + func (p *Plexams) GeneratedExam(ctx context.Context, ancode int) (*model.GeneratedExam, error) { return p.dbClient.GetGeneratedExam(ctx, ancode) } -// ConflictingAncodes is the resolver for the conflictingAncodes field. func (p *Plexams) ConflictingAncodes(ctx context.Context, ancode int) ([]*model.Conflict, error) { exam, err := p.dbClient.GetGeneratedExam(ctx, ancode) if err != nil { diff --git a/plexams/invigilators.go b/plexams/invigilators.go index b9d2c4f..0f614b3 100644 --- a/plexams/invigilators.go +++ b/plexams/invigilators.go @@ -65,7 +65,8 @@ func (p *Plexams) InvigilatorsWithReq(ctx context.Context) ([]*model.Invigilator excludedDates := make([]*time.Time, 0, len(reqs.ExcludedDates)) for _, day := range reqs.ExcludedDates { - t, err := time.Parse("02.01.06", day) + loc, _ := time.LoadLocation("Europe/Berlin") + t, err := time.ParseInLocation("02.01.06", day, loc) if err != nil { log.Error().Err(err).Str("day", day).Msg("cannot parse date") } else { @@ -74,12 +75,19 @@ func (p *Plexams) InvigilatorsWithReq(ctx context.Context) ([]*model.Invigilator } examDateTimes := make([]*time.Time, 0) - exams, err := p.dbClient.PlannedExamsByMainExamer(ctx, teacher.ID) + exams, err := p.GeneratedExamsForExamer(ctx, teacher.ID) if err != nil { log.Error().Err(err).Str("name", teacher.Shortname).Msg("cannit get exams by main examer") } else { for _, exam := range exams { - examDateTimes = append(examDateTimes, &exam.Slot.Starttime) + planEntry, err := p.dbClient.PlanEntry(ctx, exam.Ancode) + if err != nil { + log.Error().Err(err).Int("ancode", exam.Ancode).Msg("cannot get plan entry for ancode") + } + if planEntry != nil { + starttime := p.getSlotTime(planEntry.DayNumber, planEntry.SlotNumber) + examDateTimes = append(examDateTimes, &starttime) + } } } @@ -141,7 +149,7 @@ func (p *Plexams) datesToDay(dates []*time.Time) []int { } func (p *Plexams) InvigilationTodos(ctx context.Context) (*model.InvigilationTodos, error) { - selfInvigilations, err := p.GetSelfInvigilations(ctx) + selfInvigilations, err := p.MakeSelfInvigilations(ctx) if err != nil { log.Error().Err(err).Msg("cannot get self invigilations") } @@ -315,7 +323,7 @@ func dayOkForInvigilator(day int, invigilator *model.Invigilator) (wantDay, canD func (p *Plexams) PrepareSelfInvigilation() error { ctx := context.Background() - selfInvigilations, err := p.GetSelfInvigilations(ctx) + selfInvigilations, err := p.MakeSelfInvigilations(ctx) if err != nil { return err } @@ -331,7 +339,7 @@ func (p *Plexams) PrepareSelfInvigilation() error { return p.dbClient.DropAndSave(context.WithValue(ctx, db.CollectionName("collectionName"), "invigilations_self"), toSave) } -func (p *Plexams) GetSelfInvigilations(ctx context.Context) ([]*model.Invigilation, error) { +func (p *Plexams) MakeSelfInvigilations(ctx context.Context) ([]*model.Invigilation, error) { invigilators, err := p.InvigilatorsWithReq(ctx) if err != nil || invigilators == nil { log.Error().Err(err).Msg("cannot get invigilators") diff --git a/plexams/plannedExams.go b/plexams/plannedExams.go index 53ea87f..39e1a7c 100644 --- a/plexams/plannedExams.go +++ b/plexams/plannedExams.go @@ -88,6 +88,27 @@ func (p *Plexams) PlannedExams(ctx context.Context) ([]*model.PlannedExam, error return plannedExams, nil } +func (p *Plexams) PlannedExamsByExamer(ctx context.Context, examerID int) ([]*model.PlannedExam, error) { + plannedExams, err := p.PlannedExams(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get planned exams") + return nil, err + } + + plannedExamsForExamer := make([]*model.PlannedExam, 0) + for _, plannedExam := range plannedExams { + if plannedExam.Constraints != nil && plannedExam.Constraints.NotPlannedByMe { + continue + } + if plannedExam.ZpaExam.MainExamerID == examerID { + plannedExamsForExamer = append(plannedExamsForExamer, plannedExam) + break + } + } + + return plannedExamsForExamer, nil +} + func (p *Plexams) PlannedExamsForProgram(ctx context.Context, program string, onlyPlannedByMe bool) ([]*model.PlannedExam, error) { plannedExams, err := p.PlannedExams(ctx) if err != nil { From b6d86ead5b56672e555ff0c33f3f50c65bd13409 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Wed, 10 Jan 2024 20:15:36 +0100 Subject: [PATCH 71/78] cache invigilation todos --- cmd/prepare.go | 24 +- db/collection.go | 1 + db/invigilator.go | 47 ++++ graph/generated/generated.go | 351 ++++++++++++++-------------- graph/invigilation.graphqls | 2 + graph/invigilation.resolvers.go | 12 +- graph/model/models_gen.go | 2 +- graph/query.graphqls | 2 - graph/query.resolvers.go | 10 - graph/room.graphqls | 3 +- plexams/invigilators.go | 389 +++++++++++++++++++++++++------- plexams/rooms.go | 1 - plexams/validate_db.go | 1 + 13 files changed, 564 insertions(+), 281 deletions(-) diff --git a/cmd/prepare.go b/cmd/prepare.go index 889a1ab..8eb8abb 100644 --- a/cmd/prepare.go +++ b/cmd/prepare.go @@ -32,16 +32,18 @@ var ( Add exam after planning has started: - connected-exam --- prepare a connected exam for ancode - exam-group --- group of exams out of ancodes + # connected-exam --- prepare a connected exam for ancode + # exam-group --- group of exams out of ancodes For planning rooms: - exams-in-plan --- split exam-groups into exams - rooms-for-semester --- prepare rooms which are allowed to use - rooms-for-exams --- rooms for exams + # exams-in-plan --- split exam-groups into exams + rooms-for-semester --- prepare rooms which are allowed to use + rooms-for-ntas --- rooms for ntas alone + rooms-for-exams --- rooms for exams - invigilate-self --- set main examer as invigilator if possible + # invigilate-self --- set main examer as invigilator if possible + invigilator-todos --- cache snapshot `, Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { @@ -195,8 +197,14 @@ var ( os.Exit(1) } - case "invigilate-self": - err := plexams.PrepareSelfInvigilation() + // case "invigilate-self": + // err := plexams.PrepareSelfInvigilation() + // if err != nil { + // os.Exit(1) + // } + + case "invigilator-todos": + _, err := plexams.PrepareInvigilationTodos(context.Background()) if err != nil { os.Exit(1) } diff --git a/db/collection.go b/db/collection.go index 1e248bd..8d8db16 100644 --- a/db/collection.go +++ b/db/collection.go @@ -41,6 +41,7 @@ const ( collectionRoomsForExams = "rooms_for_exams" // Deprecated: ? collectionInvigilatorRequirements = "invigilator_requirements" + collectionInvigilatorTodos = "invigilator_todos" collectionOtherInvigilations = "invigilations_other" collectionSelfInvigilations = "invigilations_self" ) diff --git a/db/invigilator.go b/db/invigilator.go index d1df239..4f3d50c 100644 --- a/db/invigilator.go +++ b/db/invigilator.go @@ -2,6 +2,7 @@ package db import ( "context" + "fmt" "github.com/obcode/plexams.go/graph/model" "github.com/obcode/plexams.go/zpa" @@ -74,3 +75,49 @@ func (db *DB) getInvigilatorForRoom(ctx context.Context, collectionName, name st return db.GetTeacher(ctx, invigilation.InvigilatorID) } + +func (db *DB) CacheInvigilatorTodos(ctx context.Context, todos *model.InvigilationTodos) error { + collection := db.Client.Database(db.databaseName).Collection(collectionInvigilatorTodos) + + err := collection.Drop(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot drop invigilator todos collection") + return err + } + _, err = collection.InsertOne(ctx, todos) + if err != nil { + log.Error().Err(err).Msg("cannot cache invigilator todos") + return err + } + + return err +} + +func (db *DB) GetInvigilationTodos(ctx context.Context) (*model.InvigilationTodos, error) { + collection := db.Client.Database(db.databaseName).Collection(collectionInvigilatorTodos) + + cur, err := collection.Find(ctx, bson.M{}) + if err != nil { + log.Error().Err(err).Msg("cannot find invigilator todos") + return nil, err + } + + todos := make([]*model.InvigilationTodos, 0) + + err = cur.All(ctx, &todos) + if err != nil { + log.Error().Err(err).Msg("cannot decode invigilator todos") + return nil, err + } + + if len(todos) == 0 { + return nil, nil + } + if len(todos) > 1 { + err := fmt.Errorf("found more than one todo") + log.Error().Err(err).Msg("cannot decode invigilator todos") + return nil, err + } + + return todos[0], nil +} diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 60700c4..74d103a 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -719,8 +719,6 @@ type QueryResolver interface { ExamsInSlotWithRooms(ctx context.Context, day int, time int) ([]*model.ExamWithRegsAndRooms, error) RoomsWithConstraints(ctx context.Context, handicap bool, lab bool, placesWithSocket bool, exahm *bool) ([]*model.Room, error) RoomsForSlot(ctx context.Context, day int, time int) (*model.SlotWithRooms, error) - RoomsWithInvigilationsForSlot(ctx context.Context, day int, time int) (*model.InvigilationSlot, error) - InvigilatorsForDay(ctx context.Context, day int) (*model.InvigilatorsForDay, error) DayOkForInvigilator(ctx context.Context, day int, invigilatorID int) (*bool, error) ConnectedExam(ctx context.Context, ancode int) (*model.ConnectedExam, error) ConnectedExams(ctx context.Context) ([]*model.ConnectedExam, error) @@ -734,6 +732,8 @@ type QueryResolver interface { Exams(ctx context.Context) ([]*model.Exam, error) InvigilatorTodos(ctx context.Context) (*model.InvigilationTodos, error) InvigilatorsWithReq(ctx context.Context) ([]*model.Invigilator, error) + RoomsWithInvigilationsForSlot(ctx context.Context, day int, time int) (*model.InvigilationSlot, error) + InvigilatorsForDay(ctx context.Context, day int) (*model.InvigilatorsForDay, error) Ntas(ctx context.Context) ([]*model.NTA, error) NtasWithRegs(ctx context.Context) ([]*model.Student, error) AllProgramsInPlan(ctx context.Context) ([]string, error) @@ -4141,6 +4141,8 @@ type Exam { {Name: "../invigilation.graphqls", Input: `extend type Query { invigilatorTodos: InvigilationTodos invigilatorsWithReq: [Invigilator!]! + roomsWithInvigilationsForSlot(day: Int!, time: Int!): InvigilationSlot + invigilatorsForDay(day: Int!): InvigilatorsForDay } type Invigilation { @@ -4512,8 +4514,6 @@ type ConflictsPerProgramAncode { roomsForSlot(day: Int!, time: Int!): SlotWithRooms # Invigilators - roomsWithInvigilationsForSlot(day: Int!, time: Int!): InvigilationSlot - invigilatorsForDay(day: Int!): InvigilatorsForDay dayOkForInvigilator(day: Int!, invigilatorID: Int!): Boolean } `, BuiltIn: false}, @@ -4596,9 +4596,8 @@ input RoomForExamInput { mktnrs: [String!] } -# Deprecated: rm me type RoomAndExam { - room: RoomForExam! + room: PlannedRoom! exam: ZPAExam! } `, BuiltIn: false}, @@ -18292,122 +18291,6 @@ func (ec *executionContext) fieldContext_Query_roomsForSlot(ctx context.Context, return fc, nil } -func (ec *executionContext) _Query_roomsWithInvigilationsForSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_roomsWithInvigilationsForSlot(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().RoomsWithInvigilationsForSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.(*model.InvigilationSlot) - fc.Result = res - return ec.marshalOInvigilationSlot2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilationSlot(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_roomsWithInvigilationsForSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "reserve": - return ec.fieldContext_InvigilationSlot_reserve(ctx, field) - case "roomsWithInvigilators": - return ec.fieldContext_InvigilationSlot_roomsWithInvigilators(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type InvigilationSlot", field.Name) - }, - } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_roomsWithInvigilationsForSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } - return fc, nil -} - -func (ec *executionContext) _Query_invigilatorsForDay(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_invigilatorsForDay(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().InvigilatorsForDay(rctx, fc.Args["day"].(int)) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.(*model.InvigilatorsForDay) - fc.Result = res - return ec.marshalOInvigilatorsForDay2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilatorsForDay(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_invigilatorsForDay(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "want": - return ec.fieldContext_InvigilatorsForDay_want(ctx, field) - case "can": - return ec.fieldContext_InvigilatorsForDay_can(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type InvigilatorsForDay", field.Name) - }, - } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_invigilatorsForDay_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } - return fc, nil -} - func (ec *executionContext) _Query_dayOkForInvigilator(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_dayOkForInvigilator(ctx, field) if err != nil { @@ -19221,6 +19104,122 @@ func (ec *executionContext) fieldContext_Query_invigilatorsWithReq(ctx context.C return fc, nil } +func (ec *executionContext) _Query_roomsWithInvigilationsForSlot(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_roomsWithInvigilationsForSlot(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().RoomsWithInvigilationsForSlot(rctx, fc.Args["day"].(int), fc.Args["time"].(int)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.InvigilationSlot) + fc.Result = res + return ec.marshalOInvigilationSlot2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilationSlot(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_roomsWithInvigilationsForSlot(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "reserve": + return ec.fieldContext_InvigilationSlot_reserve(ctx, field) + case "roomsWithInvigilators": + return ec.fieldContext_InvigilationSlot_roomsWithInvigilators(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type InvigilationSlot", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_roomsWithInvigilationsForSlot_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_invigilatorsForDay(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_invigilatorsForDay(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().InvigilatorsForDay(rctx, fc.Args["day"].(int)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.InvigilatorsForDay) + fc.Result = res + return ec.marshalOInvigilatorsForDay2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐInvigilatorsForDay(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_invigilatorsForDay(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "want": + return ec.fieldContext_InvigilatorsForDay_want(ctx, field) + case "can": + return ec.fieldContext_InvigilatorsForDay_can(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type InvigilatorsForDay", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_invigilatorsForDay_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Query_ntas(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_ntas(ctx, field) if err != nil { @@ -21580,9 +21579,9 @@ func (ec *executionContext) _RoomAndExam_room(ctx context.Context, field graphql } return graphql.Null } - res := resTmp.(*model.RoomForExam) + res := resTmp.(*model.PlannedRoom) fc.Result = res - return ec.marshalNRoomForExam2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐRoomForExam(ctx, field.Selections, res) + return ec.marshalNPlannedRoom2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐPlannedRoom(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_RoomAndExam_room(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -21593,22 +21592,28 @@ func (ec *executionContext) fieldContext_RoomAndExam_room(ctx context.Context, f IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "ancode": - return ec.fieldContext_RoomForExam_ancode(ctx, field) + case "day": + return ec.fieldContext_PlannedRoom_day(ctx, field) + case "slot": + return ec.fieldContext_PlannedRoom_slot(ctx, field) case "room": - return ec.fieldContext_RoomForExam_room(ctx, field) - case "seatsPlanned": - return ec.fieldContext_RoomForExam_seatsPlanned(ctx, field) + return ec.fieldContext_PlannedRoom_room(ctx, field) + case "ancode": + return ec.fieldContext_PlannedRoom_ancode(ctx, field) case "duration": - return ec.fieldContext_RoomForExam_duration(ctx, field) + return ec.fieldContext_PlannedRoom_duration(ctx, field) case "handicap": - return ec.fieldContext_RoomForExam_handicap(ctx, field) + return ec.fieldContext_PlannedRoom_handicap(ctx, field) + case "handicapRoomAlone": + return ec.fieldContext_PlannedRoom_handicapRoomAlone(ctx, field) case "reserve": - return ec.fieldContext_RoomForExam_reserve(ctx, field) - case "students": - return ec.fieldContext_RoomForExam_students(ctx, field) + return ec.fieldContext_PlannedRoom_reserve(ctx, field) + case "studentsInRoom": + return ec.fieldContext_PlannedRoom_studentsInRoom(ctx, field) + case "ntaMtknr": + return ec.fieldContext_PlannedRoom_ntaMtknr(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type RoomForExam", field.Name) + return nil, fmt.Errorf("no field named %q was found under type PlannedRoom", field.Name) }, } return fc, nil @@ -31489,44 +31494,6 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "roomsWithInvigilationsForSlot": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_roomsWithInvigilationsForSlot(ctx, field) - return res - } - - rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, - func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - } - - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "invigilatorsForDay": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_invigilatorsForDay(ctx, field) - return res - } - - rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, - func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "dayOkForInvigilator": field := field @@ -31792,6 +31759,44 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "roomsWithInvigilationsForSlot": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_roomsWithInvigilationsForSlot(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "invigilatorsForDay": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_invigilatorsForDay(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "ntas": field := field diff --git a/graph/invigilation.graphqls b/graph/invigilation.graphqls index b697f8c..5c93beb 100644 --- a/graph/invigilation.graphqls +++ b/graph/invigilation.graphqls @@ -1,6 +1,8 @@ extend type Query { invigilatorTodos: InvigilationTodos invigilatorsWithReq: [Invigilator!]! + roomsWithInvigilationsForSlot(day: Int!, time: Int!): InvigilationSlot + invigilatorsForDay(day: Int!): InvigilatorsForDay } type Invigilation { diff --git a/graph/invigilation.resolvers.go b/graph/invigilation.resolvers.go index 44c81ef..60b62d4 100644 --- a/graph/invigilation.resolvers.go +++ b/graph/invigilation.resolvers.go @@ -12,10 +12,20 @@ import ( // InvigilatorTodos is the resolver for the invigilatorTodos field. func (r *queryResolver) InvigilatorTodos(ctx context.Context) (*model.InvigilationTodos, error) { - return r.plexams.InvigilationTodos(ctx) + return r.plexams.GetInvigilationTodos(ctx) } // InvigilatorsWithReq is the resolver for the invigilatorsWithReq field. func (r *queryResolver) InvigilatorsWithReq(ctx context.Context) ([]*model.Invigilator, error) { return r.plexams.InvigilatorsWithReq(ctx) } + +// RoomsWithInvigilationsForSlot is the resolver for the roomsWithInvigilationsForSlot field. +func (r *queryResolver) RoomsWithInvigilationsForSlot(ctx context.Context, day int, time int) (*model.InvigilationSlot, error) { + return r.plexams.RoomsWithInvigilationsForSlot(ctx, day, time) +} + +// InvigilatorsForDay is the resolver for the invigilatorsForDay field. +func (r *queryResolver) InvigilatorsForDay(ctx context.Context, day int) (*model.InvigilatorsForDay, error) { + return r.plexams.InvigilatorsForDay(ctx, day) +} diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index 2e4f3a7..45d402f 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -324,7 +324,7 @@ type Room struct { } type RoomAndExam struct { - Room *RoomForExam `json:"room"` + Room *PlannedRoom `json:"room"` Exam *ZPAExam `json:"exam"` } diff --git a/graph/query.graphqls b/graph/query.graphqls index 9bfd8ca..5fe636c 100644 --- a/graph/query.graphqls +++ b/graph/query.graphqls @@ -43,7 +43,5 @@ type Query { roomsForSlot(day: Int!, time: Int!): SlotWithRooms # Invigilators - roomsWithInvigilationsForSlot(day: Int!, time: Int!): InvigilationSlot - invigilatorsForDay(day: Int!): InvigilatorsForDay dayOkForInvigilator(day: Int!, invigilatorID: Int!): Boolean } diff --git a/graph/query.resolvers.go b/graph/query.resolvers.go index 3483514..028c16f 100644 --- a/graph/query.resolvers.go +++ b/graph/query.resolvers.go @@ -127,16 +127,6 @@ func (r *queryResolver) RoomsForSlot(ctx context.Context, day int, time int) (*m return r.plexams.RoomsForSlot(ctx, day, time) } -// RoomsWithInvigilationsForSlot is the resolver for the roomsWithInvigilationsForSlot field. -func (r *queryResolver) RoomsWithInvigilationsForSlot(ctx context.Context, day int, time int) (*model.InvigilationSlot, error) { - return r.plexams.RoomsWithInvigilationsForSlot(ctx, day, time) -} - -// InvigilatorsForDay is the resolver for the invigilatorsForDay field. -func (r *queryResolver) InvigilatorsForDay(ctx context.Context, day int) (*model.InvigilatorsForDay, error) { - return r.plexams.InvigilatorsForDay(ctx, day) -} - // DayOkForInvigilator is the resolver for the dayOkForInvigilator field. func (r *queryResolver) DayOkForInvigilator(ctx context.Context, day int, invigilatorID int) (*bool, error) { panic(fmt.Errorf("not implemented: DayOkForInvigilator - dayOkForInvigilator")) diff --git a/graph/room.graphqls b/graph/room.graphqls index 28ac6bb..097fa7e 100644 --- a/graph/room.graphqls +++ b/graph/room.graphqls @@ -77,8 +77,7 @@ input RoomForExamInput { mktnrs: [String!] } -# Deprecated: rm me type RoomAndExam { - room: RoomForExam! + room: PlannedRoom! exam: ZPAExam! } diff --git a/plexams/invigilators.go b/plexams/invigilators.go index 0f614b3..b501d33 100644 --- a/plexams/invigilators.go +++ b/plexams/invigilators.go @@ -148,7 +148,32 @@ func (p *Plexams) datesToDay(dates []*time.Time) []int { return days } -func (p *Plexams) InvigilationTodos(ctx context.Context) (*model.InvigilationTodos, error) { +func (p *Plexams) GetInvigilationTodos(ctx context.Context) (*model.InvigilationTodos, error) { + todos, err := p.dbClient.GetInvigilationTodos(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get invigilation todos") + return nil, err + } + if todos == nil { + return p.PrepareInvigilationTodos(ctx) + } + + err = p.AddInvigilatorsToInvigilationTodos(ctx, todos) + if err != nil { + log.Error().Err(err).Msg("cannot add invigilators to invigilation todos") + return nil, err + } + + err = p.dbClient.CacheInvigilatorTodos(ctx, todos) + if err != nil { + log.Error().Err(err).Msg("cannot cache invigilation todos") + return nil, err + } + + return todos, nil +} + +func (p *Plexams) PrepareInvigilationTodos(ctx context.Context) (*model.InvigilationTodos, error) { selfInvigilations, err := p.MakeSelfInvigilations(ctx) if err != nil { log.Error().Err(err).Msg("cannot get self invigilations") @@ -273,9 +298,202 @@ func (p *Plexams) InvigilationTodos(ctx context.Context) (*model.InvigilationTod } } + err = p.dbClient.CacheInvigilatorTodos(ctx, &todos) + if err != nil { + log.Error().Err(err).Msg("cannot cache invigilation todos") + return &todos, err + } + return &todos, nil } +func (p *Plexams) AddInvigilatorsToInvigilationTodos(ctx context.Context, todos *model.InvigilationTodos) error { + reqs, err := p.InvigilatorsWithReq(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get invigilators with regs") + return err + } + + todos.Invigilators = reqs + + for _, invigilator := range todos.Invigilators { + + enough := false + totalMinutes := todos.TodoPerInvigilatorOvertimeCutted + if invigilator.Requirements != nil { + totalMinutes = int(float64(totalMinutes) * invigilator.Requirements.Factor) + } + + if invigilator.Requirements != nil { + totalMinutes -= invigilator.Requirements.AllContributions + + if totalMinutes < 0 { + totalMinutes = 0 + enough = true + } + } + + invigilationsForInvigilator, err := p.dbClient.InvigilationsForInvigilator(ctx, invigilator.Teacher.ID) + if err != nil { + log.Error().Err(err).Str("invigilator", invigilator.Teacher.Shortname). + Msg("cannot get invigilations") + return err + } + + invigilationSet := set.NewSet[int]() + doingMinutes := 0 + + for _, invigilation := range invigilationsForInvigilator { + invigilationSet.Add(invigilation.Slot.DayNumber) + if !invigilation.IsSelfInvigilation { + doingMinutes += invigilation.Duration + } + } + invigilationDays := invigilationSet.ToSlice() + sort.Ints(invigilationDays) + + invigilator.Todos = &model.InvigilatorTodos{ + TotalMinutes: totalMinutes, + DoingMinutes: doingMinutes, + Enough: enough, + InvigilationDays: invigilationDays, + Invigilations: invigilationsForInvigilator, + } + } + + return nil +} + +// Deprecated: split to other functions +func (p *Plexams) InvigilationTodos(ctx context.Context) (*model.InvigilationTodos, error) { + // selfInvigilations, err := p.MakeSelfInvigilations(ctx) + // if err != nil { + // log.Error().Err(err).Msg("cannot get self invigilations") + // } + + // todos := model.InvigilationTodos{} + + // for _, slot := range p.semesterConfig.Slots { + // roomsInSlot, err := p.PlannedRoomsInSlot(ctx, slot.DayNumber, slot.SlotNumber) + // if err != nil { + // log.Error().Err(err).Int("day", slot.DayNumber).Int("time", slot.SlotNumber). + // Msg("cannot get rooms for slot") + // } else { + // if len(roomsInSlot) == 0 { + // continue + // } + // roomMap := make(map[string]int) + // OUTER: + // for _, room := range roomsInSlot { + // for _, selfInvigilation := range selfInvigilations { + // if selfInvigilation.Slot.DayNumber == slot.DayNumber && + // selfInvigilation.Slot.SlotNumber == slot.SlotNumber && + // *selfInvigilation.RoomName == room.RoomName { + // log.Debug().Int("day", slot.DayNumber).Int("slot", slot.SlotNumber).Str("room", room.RoomName). + // Msg("found self invigilation") + // continue OUTER + // } + // } + // maxDuration, ok := roomMap[room.RoomName] + // if !ok || maxDuration < room.Duration { + // roomMap[room.RoomName] = room.Duration + // } + // } + + // for _, maxDuration := range roomMap { + // todos.SumExamRooms += maxDuration + // } + // todos.SumReserve += 60 // FIXME: Maybe some other time? half of max duration in slot? + // } + // } + + // reqs, err := p.InvigilatorsWithReq(ctx) + // if err != nil { + // log.Error().Err(err).Msg("cannot get invigilators with regs") + // } + + // todos.Invigilators = reqs + + // for _, invigilator := range reqs { + // if invigilator.Requirements != nil { + // todos.SumOtherContributions += invigilator.Requirements.AllContributions + // } + // } + + // todos.InvigilatorCount = len(reqs) + // adjustedInvigilatorCount := 0.0 + + // for _, invigilator := range reqs { + // if invigilator.Requirements != nil { + // adjustedInvigilatorCount += invigilator.Requirements.Factor + // } + // } + + // todos.TodoPerInvigilator = int(math.Ceil(float64(todos.SumExamRooms+todos.SumReserve+todos.SumOtherContributions) / adjustedInvigilatorCount)) + + // sumOtherContributionsOvertimeCutted := 0 + // for _, invigilator := range reqs { + // if invigilator.Requirements != nil { + // if otherContributions := invigilator.Requirements.OralExamsContribution + + // invigilator.Requirements.LiveCodingContribution + + // invigilator.Requirements.MasterContribution; otherContributions > todos.TodoPerInvigilator { + // sumOtherContributionsOvertimeCutted += todos.TodoPerInvigilator + // } else { + // sumOtherContributionsOvertimeCutted += otherContributions + // } + // } + // } + // todos.SumOtherContributionsOvertimeCutted = sumOtherContributionsOvertimeCutted + // todos.TodoPerInvigilatorOvertimeCutted = int(math.Ceil(float64(todos.SumExamRooms+todos.SumReserve+sumOtherContributionsOvertimeCutted) / adjustedInvigilatorCount)) + + // for _, invigilator := range todos.Invigilators { + + // enough := false + // totalMinutes := todos.TodoPerInvigilatorOvertimeCutted + // if invigilator.Requirements != nil { + // totalMinutes = int(float64(totalMinutes) * invigilator.Requirements.Factor) + // } + + // if invigilator.Requirements != nil { + // totalMinutes -= invigilator.Requirements.AllContributions + + // if totalMinutes < 0 { + // totalMinutes = 0 + // enough = true + // } + // } + + // invigilationsForInvigilator, err := p.dbClient.InvigilationsForInvigilator(ctx, invigilator.Teacher.ID) + // if err != nil { + // log.Error().Err(err).Str("invigilator", invigilator.Teacher.Shortname). + // Msg("cannot get invigilations") + // } + + // invigilationSet := set.NewSet[int]() + // doingMinutes := 0 + + // for _, invigilation := range invigilationsForInvigilator { + // invigilationSet.Add(invigilation.Slot.DayNumber) + // if !invigilation.IsSelfInvigilation { + // doingMinutes += invigilation.Duration + // } + // } + // invigilationDays := invigilationSet.ToSlice() + // sort.Ints(invigilationDays) + + // invigilator.Todos = &model.InvigilatorTodos{ + // TotalMinutes: totalMinutes, + // DoingMinutes: doingMinutes, + // Enough: enough, + // InvigilationDays: invigilationDays, + // Invigilations: invigilationsForInvigilator, + // } + // } + + // return &todos, nil + return nil, nil +} + func (p *Plexams) InvigilatorsForDay(ctx context.Context, day int) (*model.InvigilatorsForDay, error) { invigilationTodos, err := p.InvigilationTodos(ctx) if err != nil { @@ -321,6 +539,7 @@ func dayOkForInvigilator(day int, invigilator *model.Invigilator) (wantDay, canD return false, true } +// Deprecated: rm me func (p *Plexams) PrepareSelfInvigilation() error { ctx := context.Background() selfInvigilations, err := p.MakeSelfInvigilations(ctx) @@ -339,6 +558,7 @@ func (p *Plexams) PrepareSelfInvigilation() error { return p.dbClient.DropAndSave(context.WithValue(ctx, db.CollectionName("collectionName"), "invigilations_self"), toSave) } +// Deprecated: rm me func (p *Plexams) MakeSelfInvigilations(ctx context.Context) ([]*model.Invigilation, error) { invigilators, err := p.InvigilatorsWithReq(ctx) if err != nil || invigilators == nil { @@ -355,49 +575,49 @@ func (p *Plexams) MakeSelfInvigilations(ctx context.Context) ([]*model.Invigilat invigilations := make([]*model.Invigilation, 0) for _, slot := range p.semesterConfig.Slots { - examsInSlot, err := p.ExamsInSlot(ctx, slot.DayNumber, slot.SlotNumber) + examsInSlot, err := p.GetExamsInSlot(ctx, slot.DayNumber, slot.SlotNumber) if err != nil { log.Error().Err(err).Int("day", slot.DayNumber).Int("time", slot.SlotNumber). Msg("cannot get exams in slot") continue } - examerWithExams := make(map[int][]*model.ExamInPlan) + examerWithExams := make(map[int][]*model.PlannedExam) OUTER: for _, exam := range examsInSlot { - invigilator, ok := invigilatorMap[exam.Exam.ZpaExam.MainExamerID] + invigilator, ok := invigilatorMap[exam.ZpaExam.MainExamerID] if !ok { - log.Debug().Str("name", exam.Exam.ZpaExam.MainExamer).Msg("ist keine Aufsicht") + log.Debug().Str("name", exam.ZpaExam.MainExamer).Msg("ist keine Aufsicht") + continue + } + if exam.Constraints != nil && exam.Constraints.NotPlannedByMe { + continue + } + if len(exam.PlannedRooms) == 0 { continue } if invigilator.Requirements != nil { for _, day := range invigilator.Requirements.ExcludedDays { - if day == exam.Slot.DayNumber { - log.Debug().Str("name", exam.Exam.ZpaExam.MainExamer).Interface("slot", exam.Slot). + if day == exam.PlanEntry.DayNumber { + log.Debug().Str("name", exam.ZpaExam.MainExamer).Interface("slot", exam.PlanEntry). Msg("Tag ist gesperrt für Aufsicht") continue OUTER } } } - exams, ok := examerWithExams[exam.Exam.ZpaExam.MainExamerID] + exams, ok := examerWithExams[exam.ZpaExam.MainExamerID] if !ok { - examerWithExams[exam.Exam.ZpaExam.MainExamerID] = []*model.ExamInPlan{exam} + examerWithExams[exam.ZpaExam.MainExamerID] = []*model.PlannedExam{exam} } else { - examerWithExams[exam.Exam.ZpaExam.MainExamerID] = append(exams, exam) + examerWithExams[exam.ZpaExam.MainExamerID] = append(exams, exam) } } for examer, exams := range examerWithExams { roomNames := set.NewSet[string]() for _, exam := range exams { - rooms, err := p.dbClient.RoomsForAncode(ctx, exam.Exam.Ancode) - - if err != nil { - log.Error().Err(err).Int("ancode", exam.Exam.Ancode).Msg("cannot get rooms for ancode") - } else { - for _, room := range rooms { - roomNames.Add(room.RoomName) - } + for _, room := range exam.PlannedRooms { + roomNames.Add(room.RoomName) } } @@ -423,77 +643,80 @@ func (p *Plexams) MakeSelfInvigilations(ctx context.Context) ([]*model.Invigilat // TODO: rewrite me func (p *Plexams) RoomsWithInvigilationsForSlot(ctx context.Context, day int, time int) (*model.InvigilationSlot, error) { - // rooms, err := p.PlannedRoomsInSlot(ctx, day, time) - // if err != nil { - // log.Error().Err(err).Int("day", day).Int("time", time). - // Msg("cannot get rooms for slot") - // return nil, err - // } + rooms, err := p.PlannedRoomsInSlot(ctx, day, time) + if err != nil { + log.Error().Err(err).Int("day", day).Int("time", time). + Msg("cannot get rooms for slot") + return nil, err + } - // reserve, err := p.dbClient.GetInvigilatorInSlot(ctx, "reserve", day, time) - // if err != nil { - // log.Error().Err(err).Int("day", day).Int("time", time). - // Msg("cannot get reserve for slot") - // return nil, err - // } + if len(rooms) == 0 { + return nil, nil // okay? + } - // slot := &model.InvigilationSlot{ - // Reserve: reserve, - // RoomsWithInvigilators: []*model.RoomWithInvigilator{}, - // } + reserve, err := p.dbClient.GetInvigilatorInSlot(ctx, "reserve", day, time) + if err != nil { + log.Error().Err(err).Int("day", day).Int("time", time). + Msg("cannot get reserve for slot") + return nil, err + } - // roomMap := make(map[string][]*model.RoomForExam) + slot := &model.InvigilationSlot{ + Reserve: reserve, + RoomsWithInvigilators: []*model.RoomWithInvigilator{}, + } - // for _, room := range rooms { - // roomsForExam, ok := roomMap[room.RoomName] - // if !ok { - // roomsForExam = make([]*model.RoomForExam, 0, 1) - // } - // roomMap[room.RoomName] = append(roomsForExam, room) - // } + roomMap := make(map[string][]*model.PlannedRoom) - // keys := make([]string, 0, len(roomMap)) - // for k := range roomMap { - // keys = append(keys, k) - // } - // sort.Strings(keys) + for _, room := range rooms { + roomsForExam, ok := roomMap[room.RoomName] + if !ok { + roomsForExam = make([]*model.PlannedRoom, 0, 1) + } + roomMap[room.RoomName] = append(roomsForExam, room) + } - // for _, name := range keys { - // roomsForExam := roomMap[name] - // invigilator, err := p.dbClient.GetInvigilatorForRoom(ctx, name, day, time) - // if err != nil { - // log.Error().Err(err).Int("day", day).Int("slot", time).Str("room", name). - // Msg("cannot get invigilator for rooms in slot") - // } + keys := make([]string, 0, len(roomMap)) + for k := range roomMap { + keys = append(keys, k) + } + sort.Strings(keys) - // roomAndExams := make([]*model.RoomAndExam, 0) - // maxDuration := 0 - // studentCount := 0 - // for _, roomForExam := range roomsForExam { - // exam, err := p.dbClient.GetZpaExamByAncode(ctx, roomForExam.Ancode) - // if err != nil { - // log.Error().Err(err).Int("ancode", roomForExam.Ancode). - // Msg("cannot get zpa exam") - // return nil, err - // } - // roomAndExams = append(roomAndExams, &model.RoomAndExam{ - // Room: roomForExam, - // Exam: exam, - // }) - // if roomForExam.Duration > maxDuration { - // maxDuration = roomForExam.Duration - // } - // studentCount += roomForExam.SeatsPlanned - // } + for _, name := range keys { + roomsForExam := roomMap[name] + invigilator, err := p.dbClient.GetInvigilatorForRoom(ctx, name, day, time) + if err != nil { + log.Error().Err(err).Int("day", day).Int("slot", time).Str("room", name). + Msg("cannot get invigilator for rooms in slot") + } - // slot.RoomsWithInvigilators = append(slot.RoomsWithInvigilators, &model.RoomWithInvigilator{ - // Name: name, - // MaxDuration: maxDuration, - // StudentCount: studentCount, - // RoomAndExams: roomAndExams, - // Invigilator: invigilator, - // }) - // } - // return slot, nil - return nil, nil + roomAndExams := make([]*model.RoomAndExam, 0) + maxDuration := 0 + studentCount := 0 + for _, roomForExam := range roomsForExam { + exam, err := p.dbClient.GetZpaExamByAncode(ctx, roomForExam.Ancode) + if err != nil { + log.Error().Err(err).Int("ancode", roomForExam.Ancode). + Msg("cannot get zpa exam") + return nil, err + } + roomAndExams = append(roomAndExams, &model.RoomAndExam{ + Room: roomForExam, + Exam: exam, + }) + if roomForExam.Duration > maxDuration { + maxDuration = roomForExam.Duration + } + studentCount += len(roomForExam.StudentsInRoom) + } + + slot.RoomsWithInvigilators = append(slot.RoomsWithInvigilators, &model.RoomWithInvigilator{ + Name: name, + MaxDuration: maxDuration, + StudentCount: studentCount, + RoomAndExams: roomAndExams, + Invigilator: invigilator, + }) + } + return slot, nil } diff --git a/plexams/rooms.go b/plexams/rooms.go index 4d72828..3c296e0 100644 --- a/plexams/rooms.go +++ b/plexams/rooms.go @@ -482,7 +482,6 @@ func (p *Plexams) PlannedRoomNames(ctx context.Context) ([]string, error) { return p.dbClient.PlannedRoomNames(ctx) } -// TODO: rewrite me func (p *Plexams) PlannedRoomsInSlot(ctx context.Context, day int, time int) ([]*model.PlannedRoom, error) { rooms, err := p.dbClient.PlannedRoomsInSlot(ctx, day, time) if err != nil { diff --git a/plexams/validate_db.go b/plexams/validate_db.go index c066d78..8529aa9 100644 --- a/plexams/validate_db.go +++ b/plexams/validate_db.go @@ -11,6 +11,7 @@ import ( "github.com/theckman/yacspin" ) +// TODO: all planned_rooms okay? especially after moving an exam? check room -> slot -> ancode sameslot? func (p *Plexams) ValidateDB() error { ctx := context.Background() cfg := yacspin.Config{ From 12822775732eb1d880c2d6f0712ef56ab97ce69a Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Thu, 11 Jan 2024 20:29:39 +0100 Subject: [PATCH 72/78] more rewrite for invigilations --- cmd/prepare.go | 12 +++--- db/invigilation.go | 10 +++-- plexams/invigilation.go | 4 +- plexams/invigilators.go | 45 ++++++++++++++++---- plexams/validate_invigilation.go | 72 ++++++++++++++++++++++++++------ 5 files changed, 112 insertions(+), 31 deletions(-) diff --git a/cmd/prepare.go b/cmd/prepare.go index 8eb8abb..6fbc7f9 100644 --- a/cmd/prepare.go +++ b/cmd/prepare.go @@ -42,7 +42,7 @@ var ( rooms-for-ntas --- rooms for ntas alone rooms-for-exams --- rooms for exams - # invigilate-self --- set main examer as invigilator if possible + self-invigilations --- set main examer as invigilator if possible invigilator-todos --- cache snapshot `, Args: cobra.MinimumNArgs(1), @@ -197,11 +197,11 @@ var ( os.Exit(1) } - // case "invigilate-self": - // err := plexams.PrepareSelfInvigilation() - // if err != nil { - // os.Exit(1) - // } + case "self-invigilations": + err := plexams.PrepareSelfInvigilation() + if err != nil { + os.Exit(1) + } case "invigilator-todos": _, err := plexams.PrepareInvigilationTodos(context.Background()) diff --git a/db/invigilation.go b/db/invigilation.go index 420141f..bc0b9ee 100644 --- a/db/invigilation.go +++ b/db/invigilation.go @@ -181,10 +181,12 @@ func (db *DB) AddInvigilation(ctx context.Context, room string, day, slot, invig func (db *DB) getMaxDurationForRoomInSlot(ctx context.Context, roomname string, day, slot int) int { maxDuration := 0 - plannedRooms, _ := db.RoomsPlannedInSlot(ctx, day, slot) - for _, room := range plannedRooms { - if roomname == room.RoomName && maxDuration < room.Duration { - maxDuration = room.Duration + examsInSlot, _ := db.GetExamsInSlot(ctx, day, slot) + for _, exam := range examsInSlot { + for _, room := range exam.PlannedRooms { + if roomname == room.RoomName && maxDuration < room.Duration { + maxDuration = room.Duration + } } } diff --git a/plexams/invigilation.go b/plexams/invigilation.go index bc2d148..9663517 100644 --- a/plexams/invigilation.go +++ b/plexams/invigilation.go @@ -18,7 +18,7 @@ func (p *Plexams) AddInvigilation(ctx context.Context, room string, day, slot, i return err } // check if (day,slot) needs a reserve, i.e. contains exams - examsInSlot, err := p.ExamsInSlot(ctx, day, slot) + examsInSlot, err := p.GetExamsInSlot(ctx, day, slot) if err != nil { return err } @@ -48,7 +48,7 @@ func (p *Plexams) AddInvigilation(ctx context.Context, room string, day, slot, i } func (p *Plexams) GetInvigilator(ctx context.Context, invigilatorID int) (*model.Invigilator, error) { - invigilationTodos, err := p.InvigilationTodos(ctx) + invigilationTodos, err := p.dbClient.GetInvigilationTodos(ctx) if err != nil { log.Error().Err(err).Msg("cannot get invigilation todos") return nil, err diff --git a/plexams/invigilators.go b/plexams/invigilators.go index b501d33..4b02e2e 100644 --- a/plexams/invigilators.go +++ b/plexams/invigilators.go @@ -495,7 +495,7 @@ func (p *Plexams) InvigilationTodos(ctx context.Context) (*model.InvigilationTod } func (p *Plexams) InvigilatorsForDay(ctx context.Context, day int) (*model.InvigilatorsForDay, error) { - invigilationTodos, err := p.InvigilationTodos(ctx) + invigilationTodos, err := p.dbClient.GetInvigilationTodos(ctx) if err != nil { log.Error().Err(err).Msg("cannot get invigilation todos") return nil, err @@ -539,7 +539,6 @@ func dayOkForInvigilator(day int, invigilator *model.Invigilator) (wantDay, canD return false, true } -// Deprecated: rm me func (p *Plexams) PrepareSelfInvigilation() error { ctx := context.Background() selfInvigilations, err := p.MakeSelfInvigilations(ctx) @@ -558,7 +557,6 @@ func (p *Plexams) PrepareSelfInvigilation() error { return p.dbClient.DropAndSave(context.WithValue(ctx, db.CollectionName("collectionName"), "invigilations_self"), toSave) } -// Deprecated: rm me func (p *Plexams) MakeSelfInvigilations(ctx context.Context) ([]*model.Invigilation, error) { invigilators, err := p.InvigilatorsWithReq(ctx) if err != nil || invigilators == nil { @@ -573,7 +571,14 @@ func (p *Plexams) MakeSelfInvigilations(ctx context.Context) ([]*model.Invigilat invigilatorMap[invigilator.Teacher.ID] = invigilator } - invigilations := make([]*model.Invigilation, 0) + type key struct { + roomName string + day int + slot int + } + + invigilationsMap := make(map[key][]*model.Invigilation) + for _, slot := range p.semesterConfig.Slots { examsInSlot, err := p.GetExamsInSlot(ctx, slot.DayNumber, slot.SlotNumber) if err != nil { @@ -624,20 +629,46 @@ func (p *Plexams) MakeSelfInvigilations(ctx context.Context) ([]*model.Invigilat if roomNames.Cardinality() == 1 { log.Debug().Int("examerid", examer).Interface("room", roomNames).Interface("slot", slot). Msg("found self invigilation") - invigilation := model.Invigilation{ + key := key{ + roomName: roomNames.ToSlice()[0], + day: slot.DayNumber, + slot: slot.SlotNumber, + } + invigilationsForKey, ok := invigilationsMap[key] + if !ok { + invigilationsForKey = make([]*model.Invigilation, 0, 1) + } + invigilationsMap[key] = append(invigilationsForKey, &model.Invigilation{ RoomName: &roomNames.ToSlice()[0], Duration: 0, // FIXME: ?? self-invigilation does not count InvigilatorID: examer, Slot: slot, IsReserve: false, IsSelfInvigilation: true, - } - invigilations = append(invigilations, &invigilation) + }) } } } + + invigilations := make([]*model.Invigilation, 0) + for _, invigs := range invigilationsMap { + // if len(invigs) == 1 { + // invigilations = append(invigilations, invigs...) + // } else { + if len(invigs) > 1 { + log.Debug().Interface("invigs", invigs).Msg("found more self invigs") + } + // // TODO: find examer with most studs in room + // // for _, invig := range invigs { + + // // } + // } + invigilations = append(invigilations, invigs[0]) + } + log.Debug().Int("count", len(invigilations)).Msg("found self invigilations") + return invigilations, nil } diff --git a/plexams/validate_invigilation.go b/plexams/validate_invigilation.go index 5382bf2..2e95679 100644 --- a/plexams/validate_invigilation.go +++ b/plexams/validate_invigilation.go @@ -4,30 +4,57 @@ import ( "context" "fmt" "sort" + "time" set "github.com/deckarep/golang-set/v2" "github.com/gookit/color" + "github.com/logrusorgru/aurora" "github.com/rs/zerolog/log" + "github.com/theckman/yacspin" ) func (p *Plexams) ValidateInvigilatorRequirements() error { - color.Style{color.FgRed, color.BgGreen, color.OpBold}. - Printf(" --- validating invigilator requirements --- \n") + + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Cyan(" validating invigilator requirements")), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + validationMessages := make([]string, 0) ctx := context.Background() - invigilationTodos, err := p.InvigilationTodos(ctx) + spinner.Message(aurora.Sprintf(aurora.Magenta("recalculating todos"))) + invigilationTodos, err := p.GetInvigilationTodos(ctx) if err != nil { return err } for _, invigilator := range invigilationTodos.Invigilators { + spinner.Message(aurora.Sprintf(aurora.Cyan("checking %s"), aurora.Magenta(invigilator.Teacher.Fullname))) log.Debug().Str("name", invigilator.Teacher.Shortname).Msg("checking constraints") // days ok for _, invigilationDay := range invigilator.Todos.InvigilationDays { for _, excludedDay := range invigilator.Requirements.ExcludedDays { if invigilationDay == excludedDay { - color.Red.Printf("%s has invigilation on excluded day %d\n", invigilator.Teacher.Shortname, invigilationDay) + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("%s has invigilation on excluded day %d"), + aurora.Cyan(invigilator.Teacher.Fullname), aurora.Cyan(invigilationDay))) } } } @@ -43,8 +70,8 @@ func (p *Plexams) ValidateInvigilatorRequirements() error { } } if !slotOk { - color.Red.Printf("%s has invigilation in not allowed slot [%d,%d]\n", invigilator.Teacher.Shortname, - invigilation.Slot.DayNumber, invigilation.Slot.SlotNumber) + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("%s has invigilation not allowed slot (%d,%d)"), + aurora.Cyan(invigilator.Teacher.Fullname), aurora.Cyan(invigilation.Slot.DayNumber), aurora.Cyan(invigilation.Slot.SlotNumber))) } } } @@ -54,8 +81,8 @@ func (p *Plexams) ValidateInvigilatorRequirements() error { for _, invigilation := range invigilator.Todos.Invigilations { combinedNumber := invigilation.Slot.DayNumber*10 + invigilation.Slot.SlotNumber if invigilationSlots.Contains(combinedNumber) { - color.Red.Printf("%s has more than one invigilation in slot (%d,%d)\n", invigilator.Teacher.Shortname, - invigilation.Slot.DayNumber, invigilation.Slot.SlotNumber) + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("%s has more than one invigilation in slot (%d,%d)"), + aurora.Cyan(invigilator.Teacher.Fullname), aurora.Cyan(invigilation.Slot.DayNumber), aurora.Cyan(invigilation.Slot.SlotNumber))) } invigilationSlots.Add(combinedNumber) @@ -72,8 +99,9 @@ func (p *Plexams) ValidateInvigilatorRequirements() error { if exam.Slot.DayNumber == invigilation.Slot.DayNumber && exam.Slot.SlotNumber == invigilation.Slot.SlotNumber { if invigilation.IsReserve { - color.Red.Printf("%s has reserve invigilation during own exam %d. %s in slot (%d,%d)\n", invigilator.Teacher.Shortname, - exam.Constraints.Ancode, exam.Exam.ZpaExam.Module, exam.Slot.DayNumber, exam.Slot.SlotNumber) + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("%s has reserve invigilation during own exam %d. %s in slot (%d,%d)"), + aurora.Cyan(invigilator.Teacher.Fullname), aurora.Cyan(exam.Constraints.Ancode), aurora.Cyan(exam.Exam.ZpaExam.Module), + aurora.Cyan(invigilation.Slot.DayNumber), aurora.Cyan(invigilation.Slot.SlotNumber))) } roomsForExam, err := p.dbClient.RoomsForAncode(ctx, exam.Exam.Ancode) @@ -86,8 +114,9 @@ func (p *Plexams) ValidateInvigilatorRequirements() error { log.Error().Err(err).Int("ancode", exam.Exam.Ancode).Msg("cannot get rooms for exam") } else { if rooms.Cardinality() > 1 { - color.Red.Printf("%s has invigilation during own exam with more than one room: %d. %s in slot (%d,%d): found rooms %v\n", invigilator.Teacher.Shortname, - exam.Constraints.Ancode, exam.Exam.ZpaExam.Module, exam.Slot.DayNumber, exam.Slot.SlotNumber, rooms) + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("%s has invigilation during own exam with more than one room: %d. %s in slot (%d,%d): found rooms %v"), + aurora.Cyan(invigilator.Teacher.Fullname), aurora.Cyan(exam.Constraints.Ancode), aurora.Cyan(exam.Exam.ZpaExam.Module), + aurora.Cyan(invigilation.Slot.DayNumber), aurora.Cyan(invigilation.Slot.SlotNumber), aurora.Cyan(rooms))) } } @@ -97,6 +126,25 @@ func (p *Plexams) ValidateInvigilatorRequirements() error { } + if len(validationMessages) > 0 { + spinner.StopFailMessage(aurora.Sprintf(aurora.Red("%d problems found"), + len(validationMessages))) + err = spinner.StopFail() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + for _, msg := range validationMessages { + fmt.Printf("%s\n", msg) + } + + } else { + spinner.StopMessage(aurora.Sprintf(aurora.Green("no problems found"))) + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + } + return nil } From a72ee7378ce752e88060f2b6b4c7b3f0399fe129 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Fri, 12 Jan 2024 23:35:39 +0100 Subject: [PATCH 73/78] more invigilation --- cmd/validate.go | 6 +- db/invigilation.go | 55 ++++++++++ plexams/invigilators.go | 8 +- plexams/validate_invigilation.go | 179 +++++++++++++++++++++++++++---- 4 files changed, 221 insertions(+), 27 deletions(-) diff --git a/cmd/validate.go b/cmd/validate.go index 82e9d2d..3f98025 100644 --- a/cmd/validate.go +++ b/cmd/validate.go @@ -83,7 +83,10 @@ var ( } case "invigilator-reqs": - validations = append(validations, plexams.ValidateInvigilatorRequirements) + validations = append(validations, + plexams.ValidateInvigilatorRequirements, + plexams.ValidateInvigilationDups, + ) case "invigilator-slots": validations = append(validations, plexams.ValidateInvigilatorSlots) @@ -120,6 +123,7 @@ func validate(funcs []func() error) { if Sleep == 0 { return } + fmt.Printf("\n... sleeping %d seconds ...\n\n", Sleep) time.Sleep(time.Duration(Sleep) * time.Second) } } diff --git a/db/invigilation.go b/db/invigilation.go index bc0b9ee..04e3d73 100644 --- a/db/invigilation.go +++ b/db/invigilation.go @@ -121,6 +121,61 @@ func (db *DB) invigilationsForInvigilator(ctx context.Context, collectionName st return invigilations, nil } +func (db *DB) GetAllInvigilations(ctx context.Context) ([]*model.Invigilation, error) { + selfInvigilations, err := db.GetSelfInvigilations(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get self invigilations") + return nil, err + } + otherInvigilations, err := db.GetOtherInvigilations(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get other invigilations") + return nil, err + } + + return append(selfInvigilations, otherInvigilations...), nil +} + +func (db *DB) GetSelfInvigilations(ctx context.Context) ([]*model.Invigilation, error) { + collection := db.getCollectionSemester(collectionSelfInvigilations) + + cur, err := collection.Find(ctx, bson.M{}) + if err != nil { + log.Error().Err(err).Msg("cannot get invgilations") + return nil, err + } + defer cur.Close(ctx) + + invigilations := make([]*model.Invigilation, 0) + err = cur.All(ctx, &invigilations) + if err != nil { + log.Error().Err(err).Msg("cannot get decode invgilations") + return nil, err + } + + return invigilations, nil +} + +func (db *DB) GetOtherInvigilations(ctx context.Context) ([]*model.Invigilation, error) { + collection := db.getCollectionSemester(collectionOtherInvigilations) + + cur, err := collection.Find(ctx, bson.M{}) + if err != nil { + log.Error().Err(err).Msg("cannot get invgilations") + return nil, err + } + defer cur.Close(ctx) + + invigilations := make([]*model.Invigilation, 0) + err = cur.All(ctx, &invigilations) + if err != nil { + log.Error().Err(err).Msg("cannot get decode invgilations") + return nil, err + } + + return invigilations, nil +} + func (db *DB) AddInvigilation(ctx context.Context, room string, day, slot, invigilatorID int) error { collection := db.getCollectionSemester(collectionOtherInvigilations) diff --git a/plexams/invigilators.go b/plexams/invigilators.go index 4b02e2e..26e447e 100644 --- a/plexams/invigilators.go +++ b/plexams/invigilators.go @@ -137,15 +137,17 @@ func (p *Plexams) InvigilatorsWithReq(ctx context.Context) ([]*model.Invigilator } func (p *Plexams) datesToDay(dates []*time.Time) []int { - days := make([]int, 0, len(dates)) + days := set.NewSet[int]() for _, date := range dates { for _, day := range p.semesterConfig.Days { if day.Date.Month() == date.Month() && day.Date.Day() == date.Day() { - days = append(days, day.Number) + days.Add(day.Number) } } } - return days + daysSlice := days.ToSlice() + sort.Ints(daysSlice) + return daysSlice } func (p *Plexams) GetInvigilationTodos(ctx context.Context) (*model.InvigilationTodos, error) { diff --git a/plexams/validate_invigilation.go b/plexams/validate_invigilation.go index 2e95679..65a174e 100644 --- a/plexams/validate_invigilation.go +++ b/plexams/validate_invigilation.go @@ -4,11 +4,12 @@ import ( "context" "fmt" "sort" + "strings" "time" set "github.com/deckarep/golang-set/v2" - "github.com/gookit/color" "github.com/logrusorgru/aurora" + "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" "github.com/theckman/yacspin" ) @@ -54,7 +55,7 @@ func (p *Plexams) ValidateInvigilatorRequirements() error { for _, excludedDay := range invigilator.Requirements.ExcludedDays { if invigilationDay == excludedDay { validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("%s has invigilation on excluded day %d"), - aurora.Cyan(invigilator.Teacher.Fullname), aurora.Cyan(invigilationDay))) + aurora.Magenta(invigilator.Teacher.Fullname), aurora.Cyan(invigilationDay))) } } } @@ -71,7 +72,7 @@ func (p *Plexams) ValidateInvigilatorRequirements() error { } if !slotOk { validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("%s has invigilation not allowed slot (%d,%d)"), - aurora.Cyan(invigilator.Teacher.Fullname), aurora.Cyan(invigilation.Slot.DayNumber), aurora.Cyan(invigilation.Slot.SlotNumber))) + aurora.Magenta(invigilator.Teacher.Fullname), aurora.Cyan(invigilation.Slot.DayNumber), aurora.Cyan(invigilation.Slot.SlotNumber))) } } } @@ -82,7 +83,7 @@ func (p *Plexams) ValidateInvigilatorRequirements() error { combinedNumber := invigilation.Slot.DayNumber*10 + invigilation.Slot.SlotNumber if invigilationSlots.Contains(combinedNumber) { validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("%s has more than one invigilation in slot (%d,%d)"), - aurora.Cyan(invigilator.Teacher.Fullname), aurora.Cyan(invigilation.Slot.DayNumber), aurora.Cyan(invigilation.Slot.SlotNumber))) + aurora.Magenta(invigilator.Teacher.Fullname), aurora.Cyan(invigilation.Slot.DayNumber), aurora.Cyan(invigilation.Slot.SlotNumber))) } invigilationSlots.Add(combinedNumber) @@ -100,7 +101,7 @@ func (p *Plexams) ValidateInvigilatorRequirements() error { exam.Slot.SlotNumber == invigilation.Slot.SlotNumber { if invigilation.IsReserve { validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("%s has reserve invigilation during own exam %d. %s in slot (%d,%d)"), - aurora.Cyan(invigilator.Teacher.Fullname), aurora.Cyan(exam.Constraints.Ancode), aurora.Cyan(exam.Exam.ZpaExam.Module), + aurora.Magenta(invigilator.Teacher.Fullname), aurora.Cyan(exam.Constraints.Ancode), aurora.Cyan(exam.Exam.ZpaExam.Module), aurora.Cyan(invigilation.Slot.DayNumber), aurora.Cyan(invigilation.Slot.SlotNumber))) } @@ -115,7 +116,7 @@ func (p *Plexams) ValidateInvigilatorRequirements() error { } else { if rooms.Cardinality() > 1 { validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("%s has invigilation during own exam with more than one room: %d. %s in slot (%d,%d): found rooms %v"), - aurora.Cyan(invigilator.Teacher.Fullname), aurora.Cyan(exam.Constraints.Ancode), aurora.Cyan(exam.Exam.ZpaExam.Module), + aurora.Magenta(invigilator.Teacher.Fullname), aurora.Cyan(exam.Constraints.Ancode), aurora.Cyan(exam.Exam.ZpaExam.Module), aurora.Cyan(invigilation.Slot.DayNumber), aurora.Cyan(invigilation.Slot.SlotNumber), aurora.Cyan(rooms))) } } @@ -147,19 +148,134 @@ func (p *Plexams) ValidateInvigilatorRequirements() error { return nil } +func (p *Plexams) ValidateInvigilationDups() error { + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Cyan(" validating invigilator duplicates")), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + validationMessages := make([]string, 0) + + ctx := context.Background() + spinner.Message(aurora.Sprintf(aurora.Magenta("getting all invigilations"))) + invigilations, err := p.dbClient.GetAllInvigilations(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get all invigilations") + return err + } + + type key struct { + room string + day int + slot int + } + + invigilationsMap := make(map[key]*model.Invigilation) + + spinner.Message(aurora.Sprintf(aurora.Cyan("checking %d invigilations"), aurora.Magenta(len(invigilations)))) + for _, invigilation := range invigilations { + var room string + if invigilation.RoomName == nil { + room = "null" + } else { + room = *invigilation.RoomName + } + key := key{ + room: room, + day: invigilation.Slot.DayNumber, + slot: invigilation.Slot.SlotNumber, + } + + _, ok := invigilationsMap[key] + if ok { + var roomName string + if invigilation.RoomName == nil { + roomName = "null" + } else { + roomName = fmt.Sprintf("\"%s\"", *invigilation.RoomName) + } + validationMessages = append(validationMessages, + aurora.Sprintf(aurora.Red("double entry for {roomname: %s, \"slot.daynumber\": %d, \"slot.slotnumber\": %d}"), + aurora.Magenta(roomName), aurora.Cyan(invigilation.Slot.DayNumber), aurora.Cyan(invigilation.Slot.SlotNumber))) + } else { + invigilationsMap[key] = invigilation + } + } + + if len(validationMessages) > 0 { + spinner.StopFailMessage(aurora.Sprintf(aurora.Red("%d invigilations, %d problems found"), + len(invigilations), len(validationMessages))) + err = spinner.StopFail() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + for _, msg := range validationMessages { + fmt.Printf("%s\n", msg) + } + + } else { + spinner.StopMessage(aurora.Sprintf(aurora.Green("%d invigilations, no problems found"), len(invigilations))) + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + } + + return nil +} // TODO: NTA- und Reserve-Aufsicht (wenn NTA) nicht im folgenden Slot einteilen! func (p *Plexams) ValidateInvigilatorSlots() error { - color.Style{color.FgRed, color.BgGreen, color.OpBold}. - Printf(" --- validating invigilator for all slots --- \n") + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Cyan(" validating invigilator for all slots")), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + validationMessages := make([]string, 0) ctx := context.Background() + // count rooms and reserves without and print number roomWithoutInvigilatorDay := make(map[int]int) slotWithoutReserveDay := make(map[int]int) // all rooms and reserve max one invigilator for _, slot := range p.semesterConfig.Slots { + spinner.Message(aurora.Sprintf(aurora.Magenta("checking slot (%d,%d)"), + aurora.Cyan(slot.DayNumber), aurora.Cyan(slot.SlotNumber))) + rooms, err := p.PlannedRoomNamesInSlot(ctx, slot.DayNumber, slot.SlotNumber) if err != nil { log.Error().Err(err).Int("day", slot.DayNumber).Int("slot", slot.SlotNumber).Msg("cannot get rooms for") @@ -175,10 +291,8 @@ func (p *Plexams) ValidateInvigilatorSlots() error { if len(invigilations) == 0 { slotWithoutReserveDay[slot.DayNumber]++ } else if len(invigilations) > 1 { - color.Red.Printf("more than one reserve invigilator in slot (%d,%d): ", slot.DayNumber, slot.SlotNumber) - for _, invigilation := range invigilations { - color.Red.Printf("%d, ", invigilation.InvigilatorID) - } + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("more than one reserve invigilator in slot (%d,%d)"), + aurora.Magenta(slot.DayNumber), aurora.Magenta(slot.SlotNumber))) } for _, room := range rooms { @@ -193,12 +307,8 @@ func (p *Plexams) ValidateInvigilatorSlots() error { if len(invigilations) == 0 { roomWithoutInvigilatorDay[slot.DayNumber]++ } else if len(invigilations) > 1 { - color.Red.Printf("more than one invigilator for room %s in slot (%d,%d): ", room, - slot.DayNumber, slot.SlotNumber) - for _, invigilation := range invigilations { - color.Red.Printf("%d, ", invigilation.InvigilatorID) - } - fmt.Println() + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red("more than one invigilator for room %s in slot (%d,%d)"), + aurora.Magenta(room), aurora.Magenta(slot.DayNumber), aurora.Magenta(slot.SlotNumber))) } } } @@ -220,19 +330,42 @@ func (p *Plexams) ValidateInvigilatorSlots() error { slotsWithoutReserve := slotWithoutReserveDay[day] if roomsWithoutInvig+slotsWithoutReserve > 0 { - color.Red.Printf("Day %2d: %2d open invigilations, ", day, roomsWithoutInvig+slotsWithoutReserve) + var msg strings.Builder + msg.WriteString(aurora.Sprintf(aurora.Red("Day %2d: %2d open invigilations, "), + aurora.Magenta(day), aurora.Cyan(roomsWithoutInvig+slotsWithoutReserve))) + if roomsWithoutInvig > 0 { - color.Red.Printf("%2d rooms without invigilator", roomsWithoutInvig) + msg.WriteString(aurora.Sprintf(aurora.Red("%2d rooms without invigilator,"), aurora.Cyan(roomsWithoutInvig))) } else { - fmt.Print(" ") + msg.WriteString(" ") } if slotsWithoutReserve > 0 { - color.Red.Printf(", %2d slots without reserve", slotsWithoutReserve) + msg.WriteString(aurora.Sprintf(aurora.Red("%2d slots without reserve"), aurora.Cyan(slotsWithoutReserve))) } - fmt.Println() + + validationMessages = append(validationMessages, msg.String()) } } } + if len(validationMessages) > 0 { + spinner.StopFailMessage(aurora.Sprintf(aurora.Red("%d problems found"), + len(validationMessages))) + err = spinner.StopFail() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + for _, msg := range validationMessages { + fmt.Printf("%s\n", msg) + } + + } else { + spinner.StopMessage(aurora.Sprintf(aurora.Green("no problems found"))) + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + } + return nil } From bde6d8c4c8becbd0a8b09360a6a7396ed2d32fd0 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Sat, 13 Jan 2024 00:51:32 +0100 Subject: [PATCH 74/78] validate zpa invigilators --- cmd/validate.go | 1 - plexams/validate_zpa.go | 122 +++++++++++++++++++++++++++++++++------- plexams/zpa_post.go | 40 ++++++------- 3 files changed, 121 insertions(+), 42 deletions(-) diff --git a/cmd/validate.go b/cmd/validate.go index 3f98025..8e88fe6 100644 --- a/cmd/validate.go +++ b/cmd/validate.go @@ -75,7 +75,6 @@ var ( } } if Invigilators { - fmt.Println("validating zpa invigilators") err := plexams.ValidateZPAInvigilators() if err != nil { log.Fatal(err) diff --git a/plexams/validate_zpa.go b/plexams/validate_zpa.go index 27100aa..ae0510d 100644 --- a/plexams/validate_zpa.go +++ b/plexams/validate_zpa.go @@ -175,6 +175,8 @@ func (p *Plexams) ValidateZPARooms() error { notPlannedByMe++ continue } + spinner.Message(aurora.Sprintf(aurora.Yellow("checking exam %d. %s (%s)"), + plannedExam.Ancode, plannedExam.ZpaExam.Module, plannedExam.ZpaExam.MainExamer)) roomsForAncode, err := p.dbClient.PlannedRoomsForAncode(context.Background(), plannedExam.Ancode) if err != nil { @@ -237,69 +239,147 @@ func (p *Plexams) ValidateZPARooms() error { } func (p *Plexams) ValidateZPAInvigilators() error { - ctx := context.Background() + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Cyan(" validating zpa invigilations")), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + validationMessages := make([]string, 0) + + spinner.Message(aurora.Sprintf(aurora.Yellow("fetching exams from ZPA"))) + if err := p.SetZPA(); err != nil { + return err + } + plannedExamsFromZPA, err := p.zpa.client.GetPlannedExams() if err != nil { return err } - plannedExams, err := p.ExamsInPlan(ctx) + spinner.Message(aurora.Sprintf(aurora.Yellow("fetching planned exams from db"))) + plannedExams, err := p.PlannedExams(context.Background()) if err != nil { return err } - problems := 0 + ctx := context.Background() + // plannedExamsFromZPA, err := p.zpa.client.GetPlannedExams() + // if err != nil { + // return err + // } + + // plannedExams, err := p.ExamsInPlan(ctx) + // if err != nil { + // return err + // } + + // problems := 0 // check if plexams data is on zpa + notPlannedByMe := 0 + for _, plannedExam := range plannedExams { - roomsForAncode, err := p.dbClient.RoomsForAncode(ctx, plannedExam.Exam.Ancode) - if err != nil { - log.Error().Err(err).Int("ancode", plannedExam.Exam.Ancode).Msg("cannot get planned rooms for ancode") - problems++ + if plannedExam.Constraints != nil && plannedExam.Constraints.NotPlannedByMe { + notPlannedByMe++ + continue } - reserveInvigilator, err := p.GetInvigilatorInSlot(ctx, "reserve", plannedExam.Slot.DayNumber, plannedExam.Slot.SlotNumber) + + spinner.Message(aurora.Sprintf(aurora.Yellow("checking exam %d. %s (%s)"), + plannedExam.Ancode, plannedExam.ZpaExam.Module, plannedExam.ZpaExam.MainExamer)) + + roomsForAncode := plannedExam.PlannedRooms + reserveInvigilator, err := p.GetInvigilatorInSlot(ctx, "reserve", plannedExam.PlanEntry.DayNumber, plannedExam.PlanEntry.SlotNumber) if err != nil { - log.Error().Err(err).Int("day", plannedExam.Slot.DayNumber).Int("slot", plannedExam.Slot.SlotNumber). + log.Error().Err(err).Int("day", plannedExam.PlanEntry.DayNumber).Int("slot", plannedExam.PlanEntry.SlotNumber). Msg("cannot get reserve invigilator for slot") - problems++ } for _, room := range roomsForAncode { if room.RoomName == "No Room" { continue } - invigilator, err := p.GetInvigilatorInSlot(ctx, room.RoomName, plannedExam.Slot.DayNumber, plannedExam.Slot.SlotNumber) + invigilator, err := p.GetInvigilatorInSlot(ctx, room.RoomName, plannedExam.PlanEntry.DayNumber, plannedExam.PlanEntry.SlotNumber) if err != nil { - log.Error().Err(err).Int("day", plannedExam.Slot.DayNumber).Int("slot", plannedExam.Slot.SlotNumber). + log.Error().Err(err).Int("day", plannedExam.PlanEntry.DayNumber).Int("slot", plannedExam.PlanEntry.SlotNumber). Msg("cannot get reserve invigilator for slot") - problems++ } found := false for _, zpaExam := range plannedExamsFromZPA { if room.Ancode == zpaExam.Ancode && - roomNameOK(room.RoomName, zpaExam.RoomName) && - zpaExam.ReserveSupervisor == reserveInvigilator.Shortname && - zpaExam.Supervisor == invigilator.Shortname { + roomNameOK(room.RoomName, zpaExam.RoomName) { + if zpaExam.ReserveSupervisor != reserveInvigilator.Shortname { + validationMessages = append(validationMessages, + aurora.Sprintf(aurora.Red("%d. %s (%s), %s %s: wrong reserve invigilator in zpa: %s, wanted: %s"), + aurora.Magenta(zpaExam.Ancode), aurora.Magenta(zpaExam.Module), aurora.Magenta(zpaExam.MainExamer), + aurora.Magenta(zpaExam.Date), aurora.Magenta(zpaExam.Starttime), + aurora.Cyan(zpaExam.ReserveSupervisor), aurora.Cyan(reserveInvigilator.Shortname))) + } + if zpaExam.Supervisor != invigilator.Shortname { + validationMessages = append(validationMessages, + aurora.Sprintf(aurora.Red("%d. %s (%s), %s %s: wrong invigilator in zpa: %s, wanted: %s"), + aurora.Magenta(zpaExam.Ancode), aurora.Magenta(zpaExam.Module), aurora.Magenta(zpaExam.MainExamer), + aurora.Magenta(zpaExam.Date), aurora.Magenta(zpaExam.Starttime), + aurora.Magenta(zpaExam.Supervisor), aurora.Cyan(invigilator.Shortname))) + } found = true - break } } if !found { - problems++ + validationMessages = append(validationMessages, + aurora.Sprintf(aurora.Red("%d. %s (%s), (%d/%d): ancode or room not found"), + aurora.Magenta(plannedExam.Ancode), aurora.Magenta(plannedExam.ZpaExam.Module), aurora.Magenta(plannedExam.ZpaExam.MainExamer), + aurora.Magenta(plannedExam.PlanEntry.DayNumber), aurora.Magenta(plannedExam.PlanEntry.SlotNumber))) color.Red.Printf("supervisor or reserve supervisor not found in ZPA\n %+v\n", room) } } } - if problems == 0 { - color.Green.Println("all invigilators planned found in zpa") - } + // if problems == 0 { + // color.Green.Println("all invigilators planned found in zpa") + // } // TODO: check if zpa data is in plexams // for _, zpaExam := range plannedExamsFromZPA { // } + if len(validationMessages) > 0 { + spinner.StopFailMessage(aurora.Sprintf(aurora.Red("%d planned exams (%d not planned by me), %d problems found"), + len(plannedExams), notPlannedByMe, len(validationMessages))) + err = spinner.StopFail() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + for _, msg := range validationMessages { + fmt.Printf(" ↪ %s\n", msg) + } + + } else { + spinner.StopMessage(aurora.Sprintf( + aurora.Green("%d planned exams (%d not planned by me), no problems found"), + len(plannedExams), notPlannedByMe)) + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + } + return nil } diff --git a/plexams/zpa_post.go b/plexams/zpa_post.go index 2712746..3642c52 100644 --- a/plexams/zpa_post.go +++ b/plexams/zpa_post.go @@ -145,15 +145,15 @@ func (p *Plexams) UploadPlan(ctx context.Context, withRooms, withInvigilators, u // FIXME: with rooms -> zpa var rooms []*model.ZPAExamPlanRoom reserveInvigilatorID := 0 - // if withInvigilators { - // invigilator, err := p.GetInvigilatorInSlot(ctx, "reserve", slot.DayNumber, slot.SlotNumber) - // if err != nil { - // log.Error().Err(err).Int("ancode", exam.Exam.Ancode).Int("day", slot.DayNumber).Int("slot", slot.SlotNumber). - // Msg("cannot get reserve invigilator for slot") - // return nil, err - // } - // reserveInvigilatorID = invigilator.ID - // } + if withInvigilators { + invigilator, err := p.GetInvigilatorInSlot(ctx, "reserve", exam.PlanEntry.DayNumber, exam.PlanEntry.SlotNumber) + if err != nil { + log.Error().Err(err).Int("ancode", exam.Ancode).Int("day", exam.PlanEntry.DayNumber).Int("slot", exam.PlanEntry.SlotNumber). + Msg("cannot get reserve invigilator for slot") + return nil, err + } + reserveInvigilatorID = invigilator.ID + } if withRooms { roomsForAncode, err := p.dbClient.PlannedRoomsForAncode(ctx, exam.Ancode) @@ -172,16 +172,16 @@ func (p *Plexams) UploadPlan(ctx context.Context, withRooms, withInvigilators, u continue } - // invigilatorID := 0 - // if withInvigilators { - // invigilator, err := p.GetInvigilatorInSlot(ctx, roomForAncode.RoomName, slot.DayNumber, slot.SlotNumber) - // if err != nil { - // log.Error().Err(err).Int("ancode", exam.Exam.Ancode).Str("room", roomForAncode.RoomName). - // Msg("cannot get invigilator for room") - // return nil, err - // } - // invigilatorID = invigilator.ID - // } + invigilatorID := 0 + if withInvigilators { + invigilator, err := p.GetInvigilatorInSlot(ctx, roomForAncode.RoomName, exam.PlanEntry.DayNumber, exam.PlanEntry.SlotNumber) + if err != nil { + log.Error().Err(err).Int("ancode", exam.Ancode).Str("room", roomForAncode.RoomName). + Msg("cannot get invigilator for room") + return nil, err + } + invigilatorID = invigilator.ID + } roomName := roomForAncode.RoomName if strings.HasPrefix(roomName, "ONLINE") { @@ -199,7 +199,7 @@ func (p *Plexams) UploadPlan(ctx context.Context, withRooms, withInvigilators, u } roomsMap[roomNameWithDuration] = append(roomWithDuration, &model.ZPAExamPlanRoom{ RoomName: roomName, - InvigilatorID: 0, // invigilatorID, + InvigilatorID: invigilatorID, Duration: roomForAncode.Duration, IsReserve: roomForAncode.Reserve, StudentCount: len(roomForAncode.StudentsInRoom), From 05a0f9d436d397274b6b9f844a6254781fdd7d2a Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Sat, 13 Jan 2024 17:07:39 +0100 Subject: [PATCH 75/78] ValidateInvigilationsTimeDistance --- cmd/validate.go | 1 + plexams/validate_invigilation.go | 152 +++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+) diff --git a/cmd/validate.go b/cmd/validate.go index 8e88fe6..603120f 100644 --- a/cmd/validate.go +++ b/cmd/validate.go @@ -85,6 +85,7 @@ var ( validations = append(validations, plexams.ValidateInvigilatorRequirements, plexams.ValidateInvigilationDups, + plexams.ValidateInvigilationsTimeDistance, ) case "invigilator-slots": diff --git a/plexams/validate_invigilation.go b/plexams/validate_invigilation.go index 65a174e..c319b3b 100644 --- a/plexams/validate_invigilation.go +++ b/plexams/validate_invigilation.go @@ -11,6 +11,7 @@ import ( "github.com/logrusorgru/aurora" "github.com/obcode/plexams.go/graph/model" "github.com/rs/zerolog/log" + "github.com/spf13/viper" "github.com/theckman/yacspin" ) @@ -369,3 +370,154 @@ func (p *Plexams) ValidateInvigilatorSlots() error { return nil } + +func (p *Plexams) ValidateInvigilationsTimeDistance() error { + ctx := context.Background() + timelag := viper.GetInt("rooms.timelag") + + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Cyan(" validating time lag of invigilations (%d minutes)"), timelag), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + validationMessages := make([]string, 0) + spinner.Message(aurora.Sprintf(aurora.Yellow("prepare invigilations)"))) + + allInvigilations, err := p.dbClient.GetAllInvigilations(ctx) + if err != nil { + log.Error().Err(err).Msg("cannot get all invigilations") + } + + type slot struct { + day int + slot int + } + + invigilations := make(map[slot][]*model.Invigilation) + for _, invigilation := range allInvigilations { + slot := slot{ + day: invigilation.Slot.DayNumber, + slot: invigilation.Slot.SlotNumber, + } + + invigilationsInSlot, ok := invigilations[slot] + if !ok { + invigilationsInSlot = make([]*model.Invigilation, 0, 1) + } + invigilations[slot] = append(invigilationsInSlot, invigilation) + } + + for _, day := range p.semesterConfig.Days { + spinner.Message(aurora.Sprintf(aurora.Yellow("checking day %d (%s)"), day.Number, day.Date.Format("02.01.06"))) + + for i := range p.semesterConfig.Starttimes { + if i == len(p.semesterConfig.Days)-1 { + continue + } + slot1, slot2 := slot{day: day.Number, slot: i + 1}, slot{day: day.Number, slot: i + 2} + log.Debug().Interface("slot 1", slot1).Interface("slot 2", slot2).Msg("checking slot") + + invigilationsSlot1, ok := invigilations[slot1] + if !ok || len(invigilationsSlot1) == 0 { + log.Debug().Interface("slot", slot1).Msg("no invigilations in slot") + continue + } + + invigilationsSlot2, ok := invigilations[slot2] + if !ok || len(invigilationsSlot2) == 0 { + log.Debug().Interface("slot", slot2).Msg("no invigilations in slot") + continue + } + + for _, invigilation1 := range invigilationsSlot1 { + for _, invigilation2 := range invigilationsSlot2 { + if invigilation1.InvigilatorID != invigilation2.InvigilatorID { + continue + } + + startSlot1 := p.getSlotTime(invigilation1.Slot.DayNumber, invigilation1.Slot.SlotNumber) + startSlot2 := p.getSlotTime(invigilation2.Slot.DayNumber, invigilation2.Slot.SlotNumber) + + realtime := invigilation1.Duration // TODO: calculate me + + if invigilation1.IsSelfInvigilation { + roomsInSlot, err := p.dbClient.PlannedRoomsInSlot(ctx, slot1.day, slot1.slot) + if err != nil { + log.Error().Err(err).Interface("slot", slot1).Msg("cannot get rooms in slot") + } + for _, room := range roomsInSlot { + if invigilation1.RoomName == &room.RoomName { + if room.Duration > realtime { + realtime = room.Duration + } + } + } + } + + if invigilation1.IsReserve { + roomsInSlot, err := p.dbClient.PlannedRoomsInSlot(ctx, slot1.day, slot1.slot) + if err != nil { + log.Error().Err(err).Interface("slot", slot1).Msg("cannot get rooms in slot") + } + for _, room := range roomsInSlot { + if room.Duration > realtime { + realtime = room.Duration + } + } + } + + endSlot1 := startSlot1.Add(time.Duration(realtime) * time.Minute) + + if startSlot2.Before(endSlot1.Add(time.Duration(timelag) * time.Minute)) { + comment := "" + if invigilation1.IsReserve { + comment = "(reserve in first slot)" + } + + validationMessages = append(validationMessages, aurora.Sprintf(aurora.Red( + "Not enough time for invigilator %4d between slot (%2d/%d) ends %s and slot (%2d/%d) begins %s: %2g minutes between %s"), + aurora.Magenta(invigilation1.InvigilatorID), aurora.BrightBlue(day.Number), aurora.BrightBlue(slot1.slot), aurora.Magenta(endSlot1.Format("15:04")), + aurora.BrightBlue(day.Number), aurora.BrightBlue(slot2.slot), aurora.Magenta(startSlot2.Format("15:04")), + aurora.Magenta(startSlot2.Sub(endSlot1).Minutes()), aurora.Cyan(comment), + )) + } + } + } + } + } + + if len(validationMessages) > 0 { + spinner.StopFailMessage(aurora.Sprintf(aurora.Red("%d problems found"), len(validationMessages))) + err = spinner.StopFail() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + for _, msg := range validationMessages { + fmt.Printf(" ↪ %s\n", msg) + } + + } else { + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + } + + return nil +} From 69174fc6475ec72c7086be6ad584163ba880456c Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Mon, 22 Jan 2024 10:10:33 +0100 Subject: [PATCH 76/78] save studentregs.json --- cmd/zpa.go | 18 ++++++++++++++++-- plexams/zpa_post.go | 18 +++++++++--------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/cmd/zpa.go b/cmd/zpa.go index 216c8d9..bbe343f 100644 --- a/cmd/zpa.go +++ b/cmd/zpa.go @@ -55,11 +55,25 @@ var ( fmt.Printf("fetched %d invigilator requirements\n", len(invigs)) case "studentregs": - count, regsWithErrors, err := plexams.PostStudentRegsToZPA(context.Background()) + regsPosted, regsWithErrors, err := plexams.PostStudentRegsToZPA(context.Background()) if err != nil { log.Fatal().Err(err).Msg("cannot get student regs") } - fmt.Printf("%d successfully imported, %d errors\n", count, len(regsWithErrors)) + fmt.Printf("%d successfully imported, %d errors\n", len(regsPosted), len(regsWithErrors)) + + if len(jsonOutputFile) == 0 { + jsonOutputFile = "studentregs.json" + } + json, err := json.MarshalIndent(regsPosted, "", " ") + if err != nil { + log.Error().Err(err).Msg("cannot marshal studentregs into json") + } + err = os.WriteFile(jsonOutputFile, json, 0644) + if err != nil { + log.Error().Err(err).Msg("cannot write studentregs to file") + } else { + fmt.Printf(" saved copy to %s\n", jsonOutputFile) + } case "upload-plan": diff --git a/plexams/zpa_post.go b/plexams/zpa_post.go index 3642c52..277358c 100644 --- a/plexams/zpa_post.go +++ b/plexams/zpa_post.go @@ -12,9 +12,9 @@ import ( "github.com/spf13/viper" ) -func (p *Plexams) PostStudentRegsToZPA(ctx context.Context) (int, []*model.RegWithError, error) { +func (p *Plexams) PostStudentRegsToZPA(ctx context.Context) ([]*model.ZPAStudentReg, []*model.RegWithError, error) { if err := p.SetZPA(); err != nil { - return 0, nil, err + return nil, nil, err } zpaStudentRegs := make([]*model.ZPAStudentReg, 0) @@ -23,7 +23,7 @@ func (p *Plexams) PostStudentRegsToZPA(ctx context.Context) (int, []*model.RegWi studentRegs, err := p.dbClient.StudentRegsForProgram(ctx, program) if err != nil { log.Error().Err(err).Str("program", program).Msg("error while getting student regs") - return 0, nil, err + return nil, nil, err } for _, studentReg := range studentRegs { zpaStudentRegs = append(zpaStudentRegs, p.zpa.client.StudentReg2ZPAStudentReg(studentReg)) @@ -51,11 +51,11 @@ func (p *Plexams) PostStudentRegsToZPA(ctx context.Context) (int, []*model.RegWi log.Debug().Str("status", status).Bytes("body", body).Msg("got answer from ZPA") regsWithErrors := make([]*model.RegWithError, 0) - chunkSize := 500 + chunkSize := 77 log.Info().Int("count", len(zpaStudentRegs)).Int("chunk size", chunkSize).Msg("Uploading a lot of regs in chunks.") - for from := 0; from <= len(zpaStudentRegs); from = from + chunkSize { + for from := 0; from <= len(zpaStudentRegs); from += chunkSize { to := from + chunkSize if to > len(zpaStudentRegs) { to = len(zpaStudentRegs) @@ -66,14 +66,14 @@ func (p *Plexams) PostStudentRegsToZPA(ctx context.Context) (int, []*model.RegWi _, body, err := p.zpa.client.PostStudentRegsToZPA(zpaStudentRegs[from:to]) if err != nil { log.Error().Err(err).Msg("error while posting student regs to zpa") - return 0, nil, err + return nil, nil, err } zpaStudentRegErrors := make([]*model.ZPAStudentRegError, 0) err = json.Unmarshal(body, &zpaStudentRegErrors) if err != nil { log.Error().Err(err).Interface("zpa-errors", zpaStudentRegErrors).Msg("error while unmarshalling errors from ZPA") - return 0, nil, err + return nil, nil, err } for i, e := range zpaStudentRegErrors { @@ -89,10 +89,10 @@ func (p *Plexams) PostStudentRegsToZPA(ctx context.Context) (int, []*model.RegWi err = p.dbClient.SetRegsWithErrors(ctx, regsWithErrors) if err != nil { - return 0, nil, err + return nil, nil, err } - return len(zpaStudentRegs) - len(regsWithErrors), regsWithErrors, nil + return zpaStudentRegs, regsWithErrors, nil } func noZPAStudRegError(zpaStudentRegError *model.ZPAStudentRegError) bool { From b42130f72ede19b774409cdf797d120f39a6b46c Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Fri, 26 Jan 2024 16:02:50 +0100 Subject: [PATCH 77/78] mainExamer in generated exam --- graph/exam.graphqls | 2 + graph/exam.resolvers.go | 34 ++++ graph/generated/generated.go | 380 +++++++++++++++++++++++++++++++++-- graph/model/exam.go | 24 +++ graph/model/models_gen.go | 31 --- graph/model/plan.go | 8 + graph/plan.graphqls | 2 +- graph/plan.resolvers.go | 12 ++ plexams/plexams.go | 10 + 9 files changed, 452 insertions(+), 51 deletions(-) create mode 100644 graph/model/plan.go diff --git a/graph/exam.graphqls b/graph/exam.graphqls index 8da75d7..345c0c8 100644 --- a/graph/exam.graphqls +++ b/graph/exam.graphqls @@ -112,6 +112,7 @@ type ConnectedExam { type GeneratedExam { ancode: Int! zpaExam: ZPAExam! + mainExamer: Teacher! primussExams: [EnhancedPrimussExam!]! constraints: Constraints conflicts: [ZPAConflict!]! @@ -129,6 +130,7 @@ type ZPAConflict { type PlannedExam { ancode: Int! zpaExam: ZPAExam! + mainExamer: Teacher! primussExams: [EnhancedPrimussExam!]! constraints: Constraints conflicts: [ZPAConflict!]! diff --git a/graph/exam.resolvers.go b/graph/exam.resolvers.go index 3f7e03d..ab63aac 100644 --- a/graph/exam.resolvers.go +++ b/graph/exam.resolvers.go @@ -6,10 +6,22 @@ package graph import ( "context" + "fmt" + "github.com/obcode/plexams.go/graph/generated" "github.com/obcode/plexams.go/graph/model" ) +// MainExamer is the resolver for the mainExamer field. +func (r *generatedExamResolver) MainExamer(ctx context.Context, obj *model.GeneratedExam) (*model.Teacher, error) { + return r.plexams.GetTeacher(ctx, obj.ZpaExam.MainExamerID) +} + +// MainExamer is the resolver for the mainExamer field. +func (r *plannedExamResolver) MainExamer(ctx context.Context, obj *model.PlannedExam) (*model.Teacher, error) { + return r.plexams.GetTeacher(ctx, obj.ZpaExam.MainExamerID) +} + // ConnectedExam is the resolver for the connectedExam field. func (r *queryResolver) ConnectedExam(ctx context.Context, ancode int) (*model.ConnectedExam, error) { return r.plexams.GetConnectedExam(ctx, ancode) @@ -63,3 +75,25 @@ func (r *queryResolver) Exam(ctx context.Context, ancode int) (*model.Exam, erro func (r *queryResolver) Exams(ctx context.Context) ([]*model.Exam, error) { return r.plexams.CachedExams(ctx) } + +// GeneratedExam returns generated.GeneratedExamResolver implementation. +func (r *Resolver) GeneratedExam() generated.GeneratedExamResolver { return &generatedExamResolver{r} } + +// PlannedExam returns generated.PlannedExamResolver implementation. +func (r *Resolver) PlannedExam() generated.PlannedExamResolver { return &plannedExamResolver{r} } + +type generatedExamResolver struct{ *Resolver } +type plannedExamResolver struct{ *Resolver } + +// !!! WARNING !!! +// The code below was going to be deleted when updating resolvers. It has been copied here so you have +// one last chance to move it out of harms way if you want. There are two reasons this happens: +// - When renaming or deleting a resolver the old code will be put in here. You can safely delete +// it when you're done. +// - You have helper methods in this file. Move them out to keep these resolver files clean. +func (r *plannedExamResolver) PlanEntry(ctx context.Context, obj *model.PlannedExam) (*model.PlanEntry, error) { + panic(fmt.Errorf("not implemented: PlanEntry - planEntry")) +} +func (r *plannedExamResolver) PlannedRooms(ctx context.Context, obj *model.PlannedExam) ([]*model.PlannedRoom, error) { + panic(fmt.Errorf("not implemented: PlannedRooms - plannedRooms")) +} diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 74d103a..75c37d1 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -37,7 +37,10 @@ type Config struct { } type ResolverRoot interface { + GeneratedExam() GeneratedExamResolver Mutation() MutationResolver + PlanEntry() PlanEntryResolver + PlannedExam() PlannedExamResolver PlannedRoom() PlannedRoomResolver Query() QueryResolver RoomForExam() RoomForExamResolver @@ -204,6 +207,7 @@ type ComplexityRoot struct { Ancode func(childComplexity int) int Conflicts func(childComplexity int) int Constraints func(childComplexity int) int + MainExamer func(childComplexity int) int MaxDuration func(childComplexity int) int Ntas func(childComplexity int) int PrimussExams func(childComplexity int) int @@ -342,12 +346,14 @@ type ComplexityRoot struct { DayNumber func(childComplexity int) int Locked func(childComplexity int) int SlotNumber func(childComplexity int) int + Starttime func(childComplexity int) int } PlannedExam struct { Ancode func(childComplexity int) int Conflicts func(childComplexity int) int Constraints func(childComplexity int) int + MainExamer func(childComplexity int) int MaxDuration func(childComplexity int) int Ntas func(childComplexity int) int PlanEntry func(childComplexity int) int @@ -669,6 +675,9 @@ type ComplexityRoot struct { } } +type GeneratedExamResolver interface { + MainExamer(ctx context.Context, obj *model.GeneratedExam) (*model.Teacher, error) +} type MutationResolver interface { SetSemester(ctx context.Context, input string) (*model.Semester, error) ZpaExamsToPlan(ctx context.Context, input []int) ([]*model.ZPAExam, error) @@ -692,6 +701,12 @@ type MutationResolver interface { AddExamToSlot(ctx context.Context, day int, time int, ancode int) (bool, error) RmExamFromSlot(ctx context.Context, ancode int) (bool, error) } +type PlanEntryResolver interface { + Starttime(ctx context.Context, obj *model.PlanEntry) (*time.Time, error) +} +type PlannedExamResolver interface { + MainExamer(ctx context.Context, obj *model.PlannedExam) (*model.Teacher, error) +} type PlannedRoomResolver interface { Room(ctx context.Context, obj *model.PlannedRoom) (*model.Room, error) } @@ -1434,6 +1449,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.GeneratedExam.Constraints(childComplexity), true + case "GeneratedExam.mainExamer": + if e.complexity.GeneratedExam.MainExamer == nil { + break + } + + return e.complexity.GeneratedExam.MainExamer(childComplexity), true + case "GeneratedExam.maxDuration": if e.complexity.GeneratedExam.MaxDuration == nil { break @@ -2190,6 +2212,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PlanEntry.SlotNumber(childComplexity), true + case "PlanEntry.starttime": + if e.complexity.PlanEntry.Starttime == nil { + break + } + + return e.complexity.PlanEntry.Starttime(childComplexity), true + case "PlannedExam.ancode": if e.complexity.PlannedExam.Ancode == nil { break @@ -2211,6 +2240,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PlannedExam.Constraints(childComplexity), true + case "PlannedExam.mainExamer": + if e.complexity.PlannedExam.MainExamer == nil { + break + } + + return e.complexity.PlannedExam.MainExamer(childComplexity), true + case "PlannedExam.maxDuration": if e.complexity.PlannedExam.MaxDuration == nil { break @@ -4096,6 +4132,7 @@ type ConnectedExam { type GeneratedExam { ancode: Int! zpaExam: ZPAExam! + mainExamer: Teacher! primussExams: [EnhancedPrimussExam!]! constraints: Constraints conflicts: [ZPAConflict!]! @@ -4113,6 +4150,7 @@ type ZPAConflict { type PlannedExam { ancode: Int! zpaExam: ZPAExam! + mainExamer: Teacher! primussExams: [EnhancedPrimussExam!]! constraints: Constraints conflicts: [ZPAConflict!]! @@ -4386,7 +4424,7 @@ type ExamerInPlan { type PlanEntry { dayNumber: Int! slotNumber: Int! - # starttime: Time! + starttime: Time! ancode: Int! locked: Boolean! } @@ -9596,6 +9634,8 @@ func (ec *executionContext) fieldContext_ExamWithRegsAndRooms_exam(ctx context.C return ec.fieldContext_PlannedExam_ancode(ctx, field) case "zpaExam": return ec.fieldContext_PlannedExam_zpaExam(ctx, field) + case "mainExamer": + return ec.fieldContext_PlannedExam_mainExamer(ctx, field) case "primussExams": return ec.fieldContext_PlannedExam_primussExams(ctx, field) case "constraints": @@ -10263,6 +10303,72 @@ func (ec *executionContext) fieldContext_GeneratedExam_zpaExam(ctx context.Conte return fc, nil } +func (ec *executionContext) _GeneratedExam_mainExamer(ctx context.Context, field graphql.CollectedField, obj *model.GeneratedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_GeneratedExam_mainExamer(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.GeneratedExam().MainExamer(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Teacher) + fc.Result = res + return ec.marshalNTeacher2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐTeacher(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_GeneratedExam_mainExamer(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "GeneratedExam", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "shortname": + return ec.fieldContext_Teacher_shortname(ctx, field) + case "fullname": + return ec.fieldContext_Teacher_fullname(ctx, field) + case "isProf": + return ec.fieldContext_Teacher_isProf(ctx, field) + case "isLBA": + return ec.fieldContext_Teacher_isLBA(ctx, field) + case "isProfHC": + return ec.fieldContext_Teacher_isProfHC(ctx, field) + case "isStaff": + return ec.fieldContext_Teacher_isStaff(ctx, field) + case "lastSemester": + return ec.fieldContext_Teacher_lastSemester(ctx, field) + case "fk": + return ec.fieldContext_Teacher_fk(ctx, field) + case "id": + return ec.fieldContext_Teacher_id(ctx, field) + case "email": + return ec.fieldContext_Teacher_email(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Teacher", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _GeneratedExam_primussExams(ctx context.Context, field graphql.CollectedField, obj *model.GeneratedExam) (ret graphql.Marshaler) { fc, err := ec.fieldContext_GeneratedExam_primussExams(ctx, field) if err != nil { @@ -14886,6 +14992,50 @@ func (ec *executionContext) fieldContext_PlanEntry_slotNumber(ctx context.Contex return fc, nil } +func (ec *executionContext) _PlanEntry_starttime(ctx context.Context, field graphql.CollectedField, obj *model.PlanEntry) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlanEntry_starttime(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.PlanEntry().Starttime(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*time.Time) + fc.Result = res + return ec.marshalNTime2ᚖtimeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlanEntry_starttime(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlanEntry", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Time does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _PlanEntry_ancode(ctx context.Context, field graphql.CollectedField, obj *model.PlanEntry) (ret graphql.Marshaler) { fc, err := ec.fieldContext_PlanEntry_ancode(ctx, field) if err != nil { @@ -15088,6 +15238,72 @@ func (ec *executionContext) fieldContext_PlannedExam_zpaExam(ctx context.Context return fc, nil } +func (ec *executionContext) _PlannedExam_mainExamer(ctx context.Context, field graphql.CollectedField, obj *model.PlannedExam) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PlannedExam_mainExamer(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.PlannedExam().MainExamer(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Teacher) + fc.Result = res + return ec.marshalNTeacher2ᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐTeacher(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PlannedExam_mainExamer(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PlannedExam", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "shortname": + return ec.fieldContext_Teacher_shortname(ctx, field) + case "fullname": + return ec.fieldContext_Teacher_fullname(ctx, field) + case "isProf": + return ec.fieldContext_Teacher_isProf(ctx, field) + case "isLBA": + return ec.fieldContext_Teacher_isLBA(ctx, field) + case "isProfHC": + return ec.fieldContext_Teacher_isProfHC(ctx, field) + case "isStaff": + return ec.fieldContext_Teacher_isStaff(ctx, field) + case "lastSemester": + return ec.fieldContext_Teacher_lastSemester(ctx, field) + case "fk": + return ec.fieldContext_Teacher_fk(ctx, field) + case "id": + return ec.fieldContext_Teacher_id(ctx, field) + case "email": + return ec.fieldContext_Teacher_email(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Teacher", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _PlannedExam_primussExams(ctx context.Context, field graphql.CollectedField, obj *model.PlannedExam) (ret graphql.Marshaler) { fc, err := ec.fieldContext_PlannedExam_primussExams(ctx, field) if err != nil { @@ -15451,6 +15667,8 @@ func (ec *executionContext) fieldContext_PlannedExam_planEntry(ctx context.Conte return ec.fieldContext_PlanEntry_dayNumber(ctx, field) case "slotNumber": return ec.fieldContext_PlanEntry_slotNumber(ctx, field) + case "starttime": + return ec.fieldContext_PlanEntry_starttime(ctx, field) case "ancode": return ec.fieldContext_PlanEntry_ancode(ctx, field) case "locked": @@ -18558,6 +18776,8 @@ func (ec *executionContext) fieldContext_Query_generatedExams(ctx context.Contex return ec.fieldContext_GeneratedExam_ancode(ctx, field) case "zpaExam": return ec.fieldContext_GeneratedExam_zpaExam(ctx, field) + case "mainExamer": + return ec.fieldContext_GeneratedExam_mainExamer(ctx, field) case "primussExams": return ec.fieldContext_GeneratedExam_primussExams(ctx, field) case "constraints": @@ -18617,6 +18837,8 @@ func (ec *executionContext) fieldContext_Query_generatedExam(ctx context.Context return ec.fieldContext_GeneratedExam_ancode(ctx, field) case "zpaExam": return ec.fieldContext_GeneratedExam_zpaExam(ctx, field) + case "mainExamer": + return ec.fieldContext_GeneratedExam_mainExamer(ctx, field) case "primussExams": return ec.fieldContext_GeneratedExam_primussExams(ctx, field) case "constraints": @@ -18690,6 +18912,8 @@ func (ec *executionContext) fieldContext_Query_plannedExams(ctx context.Context, return ec.fieldContext_PlannedExam_ancode(ctx, field) case "zpaExam": return ec.fieldContext_PlannedExam_zpaExam(ctx, field) + case "mainExamer": + return ec.fieldContext_PlannedExam_mainExamer(ctx, field) case "primussExams": return ec.fieldContext_PlannedExam_primussExams(ctx, field) case "constraints": @@ -18753,6 +18977,8 @@ func (ec *executionContext) fieldContext_Query_plannedExam(ctx context.Context, return ec.fieldContext_PlannedExam_ancode(ctx, field) case "zpaExam": return ec.fieldContext_PlannedExam_zpaExam(ctx, field) + case "mainExamer": + return ec.fieldContext_PlannedExam_mainExamer(ctx, field) case "primussExams": return ec.fieldContext_PlannedExam_primussExams(ctx, field) case "constraints": @@ -19509,6 +19735,8 @@ func (ec *executionContext) fieldContext_Query_examsInSlot(ctx context.Context, return ec.fieldContext_PlannedExam_ancode(ctx, field) case "zpaExam": return ec.fieldContext_PlannedExam_zpaExam(ctx, field) + case "mainExamer": + return ec.fieldContext_PlannedExam_mainExamer(ctx, field) case "primussExams": return ec.fieldContext_PlannedExam_primussExams(ctx, field) case "constraints": @@ -19586,6 +19814,8 @@ func (ec *executionContext) fieldContext_Query_examsWithoutSlot(ctx context.Cont return ec.fieldContext_PlannedExam_ancode(ctx, field) case "zpaExam": return ec.fieldContext_PlannedExam_zpaExam(ctx, field) + case "mainExamer": + return ec.fieldContext_PlannedExam_mainExamer(ctx, field) case "primussExams": return ec.fieldContext_PlannedExam_primussExams(ctx, field) case "constraints": @@ -29538,39 +29768,75 @@ func (ec *executionContext) _GeneratedExam(ctx context.Context, sel ast.Selectio case "ancode": out.Values[i] = ec._GeneratedExam_ancode(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "zpaExam": out.Values[i] = ec._GeneratedExam_zpaExam(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } + case "mainExamer": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._GeneratedExam_mainExamer(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) case "primussExams": out.Values[i] = ec._GeneratedExam_primussExams(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "constraints": out.Values[i] = ec._GeneratedExam_constraints(ctx, field, obj) case "conflicts": out.Values[i] = ec._GeneratedExam_conflicts(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "studentRegsCount": out.Values[i] = ec._GeneratedExam_studentRegsCount(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "ntas": out.Values[i] = ec._GeneratedExam_ntas(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "maxDuration": out.Values[i] = ec._GeneratedExam_maxDuration(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } default: panic("unknown field " + strconv.Quote(field.Name)) @@ -30516,22 +30782,58 @@ func (ec *executionContext) _PlanEntry(ctx context.Context, sel ast.SelectionSet case "dayNumber": out.Values[i] = ec._PlanEntry_dayNumber(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "slotNumber": out.Values[i] = ec._PlanEntry_slotNumber(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) + } + case "starttime": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._PlanEntry_starttime(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) case "ancode": out.Values[i] = ec._PlanEntry_ancode(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "locked": out.Values[i] = ec._PlanEntry_locked(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } default: panic("unknown field " + strconv.Quote(field.Name)) @@ -30570,39 +30872,75 @@ func (ec *executionContext) _PlannedExam(ctx context.Context, sel ast.SelectionS case "ancode": out.Values[i] = ec._PlannedExam_ancode(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "zpaExam": out.Values[i] = ec._PlannedExam_zpaExam(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } + case "mainExamer": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._PlannedExam_mainExamer(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) case "primussExams": out.Values[i] = ec._PlannedExam_primussExams(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "constraints": out.Values[i] = ec._PlannedExam_constraints(ctx, field, obj) case "conflicts": out.Values[i] = ec._PlannedExam_conflicts(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "studentRegsCount": out.Values[i] = ec._PlannedExam_studentRegsCount(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "ntas": out.Values[i] = ec._PlannedExam_ntas(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "maxDuration": out.Values[i] = ec._PlannedExam_maxDuration(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "planEntry": out.Values[i] = ec._PlannedExam_planEntry(ctx, field, obj) @@ -36228,6 +36566,10 @@ func (ec *executionContext) marshalNStudentRegsPerAncodeAndProgram2ᚖgithubᚗc return ec._StudentRegsPerAncodeAndProgram(ctx, sel, v) } +func (ec *executionContext) marshalNTeacher2githubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐTeacher(ctx context.Context, sel ast.SelectionSet, v model.Teacher) graphql.Marshaler { + return ec._Teacher(ctx, sel, &v) +} + func (ec *executionContext) marshalNTeacher2ᚕᚖgithubᚗcomᚋobcodeᚋplexamsᚗgoᚋgraphᚋmodelᚐTeacherᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Teacher) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup diff --git a/graph/model/exam.go b/graph/model/exam.go index 36f1cc2..3031f8f 100644 --- a/graph/model/exam.go +++ b/graph/model/exam.go @@ -28,3 +28,27 @@ func (exam *ExamToPlan) IsGO() bool { } return false } + +type GeneratedExam struct { + Ancode int `json:"ancode"` + ZpaExam *ZPAExam `json:"zpaExam"` + PrimussExams []*EnhancedPrimussExam `json:"primussExams"` + Constraints *Constraints `json:"constraints,omitempty"` + Conflicts []*ZPAConflict `json:"conflicts"` + StudentRegsCount int `json:"studentRegsCount"` + Ntas []*NTA `json:"ntas"` + MaxDuration int `json:"maxDuration"` +} + +type PlannedExam struct { + Ancode int `json:"ancode"` + ZpaExam *ZPAExam `json:"zpaExam"` + PrimussExams []*EnhancedPrimussExam `json:"primussExams"` + Constraints *Constraints `json:"constraints,omitempty"` + Conflicts []*ZPAConflict `json:"conflicts"` + StudentRegsCount int `json:"studentRegsCount"` + Ntas []*NTA `json:"ntas"` + MaxDuration int `json:"maxDuration"` + PlanEntry *PlanEntry `json:"planEntry,omitempty"` + PlannedRooms []*PlannedRoom `json:"plannedRooms,omitempty"` +} diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index 45d402f..daa5df6 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -156,17 +156,6 @@ type FK07Program struct { Name string `json:"name"` } -type GeneratedExam struct { - Ancode int `json:"ancode"` - ZpaExam *ZPAExam `json:"zpaExam"` - PrimussExams []*EnhancedPrimussExam `json:"primussExams"` - Constraints *Constraints `json:"constraints,omitempty"` - Conflicts []*ZPAConflict `json:"conflicts"` - StudentRegsCount int `json:"studentRegsCount"` - Ntas []*NTA `json:"ntas"` - MaxDuration int `json:"maxDuration"` -} - type Invigilation struct { RoomName *string `json:"roomName,omitempty"` Duration int `json:"duration"` @@ -260,26 +249,6 @@ type Plan struct { Slots []*SlotWithExamGroups `json:"slots,omitempty"` } -type PlanEntry struct { - DayNumber int `json:"dayNumber"` - SlotNumber int `json:"slotNumber"` - Ancode int `json:"ancode"` - Locked bool `json:"locked"` -} - -type PlannedExam struct { - Ancode int `json:"ancode"` - ZpaExam *ZPAExam `json:"zpaExam"` - PrimussExams []*EnhancedPrimussExam `json:"primussExams"` - Constraints *Constraints `json:"constraints,omitempty"` - Conflicts []*ZPAConflict `json:"conflicts"` - StudentRegsCount int `json:"studentRegsCount"` - Ntas []*NTA `json:"ntas"` - MaxDuration int `json:"maxDuration"` - PlanEntry *PlanEntry `json:"planEntry,omitempty"` - PlannedRooms []*PlannedRoom `json:"plannedRooms,omitempty"` -} - type PlannedExamWithNta struct { Exam *ExamWithRegs `json:"exam"` Constraints *Constraints `json:"constraints,omitempty"` diff --git a/graph/model/plan.go b/graph/model/plan.go new file mode 100644 index 0000000..212f973 --- /dev/null +++ b/graph/model/plan.go @@ -0,0 +1,8 @@ +package model + +type PlanEntry struct { + DayNumber int `json:"dayNumber"` + SlotNumber int `json:"slotNumber"` + Ancode int `json:"ancode"` + Locked bool `json:"locked"` +} diff --git a/graph/plan.graphqls b/graph/plan.graphqls index 42429e9..70e9eb8 100644 --- a/graph/plan.graphqls +++ b/graph/plan.graphqls @@ -83,7 +83,7 @@ type ExamerInPlan { type PlanEntry { dayNumber: Int! slotNumber: Int! - # starttime: Time! + starttime: Time! ancode: Int! locked: Boolean! } diff --git a/graph/plan.resolvers.go b/graph/plan.resolvers.go index fd0aa42..9855446 100644 --- a/graph/plan.resolvers.go +++ b/graph/plan.resolvers.go @@ -7,7 +7,9 @@ package graph import ( "context" "fmt" + "time" + "github.com/obcode/plexams.go/graph/generated" "github.com/obcode/plexams.go/graph/model" ) @@ -21,6 +23,11 @@ func (r *mutationResolver) RmExamFromSlot(ctx context.Context, ancode int) (bool panic(fmt.Errorf("not implemented: RmExamFromSlot - rmExamFromSlot")) } +// Starttime is the resolver for the starttime field. +func (r *planEntryResolver) Starttime(ctx context.Context, obj *model.PlanEntry) (*time.Time, error) { + return r.plexams.GetStarttime(obj.DayNumber, obj.SlotNumber) +} + // AllProgramsInPlan is the resolver for the allProgramsInPlan field. func (r *queryResolver) AllProgramsInPlan(ctx context.Context) ([]string, error) { return r.plexams.AllProgramsInPlan(ctx) @@ -55,3 +62,8 @@ func (r *queryResolver) AllowedSlots(ctx context.Context, ancode int) ([]*model. func (r *queryResolver) AwkwardSlots(ctx context.Context, ancode int) ([]*model.Slot, error) { return r.plexams.AwkwardSlots(ctx, ancode) } + +// PlanEntry returns generated.PlanEntryResolver implementation. +func (r *Resolver) PlanEntry() generated.PlanEntryResolver { return &planEntryResolver{r} } + +type planEntryResolver struct{ *Resolver } diff --git a/plexams/plexams.go b/plexams/plexams.go index 331efb4..301bc14 100644 --- a/plexams/plexams.go +++ b/plexams/plexams.go @@ -222,6 +222,16 @@ func (p *Plexams) GetSemesterConfig() *model.SemesterConfig { return p.semesterConfig } +func (p *Plexams) GetStarttime(dayNumber, slotNumber int) (*time.Time, error) { + for _, slot := range p.semesterConfig.Slots { + if slot.DayNumber == dayNumber && slot.SlotNumber == slotNumber { + time := slot.Starttime.Local() + return &time, nil + } + } + return nil, fmt.Errorf("no starttime for slot (%d/%d)", dayNumber, slotNumber) +} + func (p *Plexams) getSlotTime(dayNumber, slotNumber int) time.Time { for _, slot := range p.semesterConfig.Slots { if slot.DayNumber == dayNumber && slot.SlotNumber == slotNumber { From 9aa92f6b148e5f12f2f21f5b31bbb702ae8f1053 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Fri, 16 Feb 2024 16:12:57 +0100 Subject: [PATCH 78/78] //nolint --- plexams/invigilation.go | 2 +- plexams/validate_invigilation.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plexams/invigilation.go b/plexams/invigilation.go index 9663517..7085447 100644 --- a/plexams/invigilation.go +++ b/plexams/invigilation.go @@ -34,7 +34,7 @@ func (p *Plexams) AddInvigilation(ctx context.Context, room string, day, slot, i } } // no exam in same slot - exams, err := p.dbClient.PlannedExamsByMainExamer(ctx, invigilatorID) + exams, err := p.dbClient.PlannedExamsByMainExamer(ctx, invigilatorID) //nolint if err != nil { return err } diff --git a/plexams/validate_invigilation.go b/plexams/validate_invigilation.go index c319b3b..4a4aba6 100644 --- a/plexams/validate_invigilation.go +++ b/plexams/validate_invigilation.go @@ -91,7 +91,7 @@ func (p *Plexams) ValidateInvigilatorRequirements() error { } // wenn gleichzeitig Prüfung, dann nur self-invigilation - exams, err := p.dbClient.PlannedExamsByMainExamer(ctx, invigilator.Teacher.ID) + exams, err := p.dbClient.PlannedExamsByMainExamer(ctx, invigilator.Teacher.ID) //nolint if err != nil { log.Error().Err(err).Str("name", invigilator.Teacher.Shortname).Msg("cannot get exams") }