Exemplo n.º 1
0
    def _possible_correct_naming(self, file_name, student_names, problems, correct_file_name_end):
        for student_name in file_name.split("_"):
            parts = re.findall(r'[A-Z](?:[a-zöäüß]+|[A-Z]*(?=[A-Z]|$))', student_name)
            if len(parts) > 0:
                student_name = ("-".join(parts))

            student_name = student_name.split("-")
            student_name = " ".join(student_name)
            if len(student_name) > 0:
                student_names.append(student_name)

        students = list()
        needed_manual_help = False
        for student_name in student_names:
            if any(char.isdigit() for char in student_name):
                if self.printer.ask(f"Is '{student_name}' really a student name? (y/n)?") != 'y':
                    self.printer.inform("Skip")
                    continue

            student = select_student_by_name(student_name, self._storage, self.printer, students.append, mode='my')
            if student is None:
                self.printer.error(f"Some error happened processing '{file_name}'")
                self.printer.error(f"Did not find a match for '{student_name}'")
                self.printer.error("Increasing scope ... ")
                student = select_student_by_name(student_name, self._storage, self.printer, students.append,
                                                 mode='all')
                if student is not None:
                    self.printer.inform(f"Found the student - consider to import '{student_name}'")
                else:
                    needed_manual_help = True
                    student = self._manual_student_selection()

                    if student is not None:
                        students.append(student)
                    else:
                        self.printer.error("Manual correction failed!")
        student_names = []

        def to_name(s):
            if type(s) == str:
                return s
            else:
                return s.muesli_name

        for student_name in sorted([to_name(student) for student in students]):
            name_parts = [_ for _ in student_name.split() if len(_) > 0 and '.' not in _]
            student_names.append(f'{name_parts[0].replace("-", "")}-{name_parts[-1].replace("-", "")}')

        if len(student_names) < 2:
            problems.append("Submission groups should consist at least of 2 members!")
        if 3 < len(student_names):
            problems.append("Submission groups should consist at most of 3 members!")

        result = '_'.join(student_names) + correct_file_name_end
        if needed_manual_help:
            problems.append(
                f"Please use the correct file format! For this submission it would have been '{result}.zip'"
            )

        return result
Exemplo n.º 2
0
 def __call__(self, *args):
     if not self._storage.muesli_data.presentation.supports_presentations:
         self.printer.error(
             "Presenting is not supported. Please change config.json if you want to enable it."
         )
     else:
         name = args[0]
         select_student_by_name(name,
                                self._storage,
                                self.printer,
                                self._update_presented_in_muesli,
                                mode='my')
Exemplo n.º 3
0
    def __call__(self, *args):
        if not self._storage.muesli_data.presentation.supports_presentations:
            self.printer.error(
                "Presenting is not supported. Please change config.json if you want to enable it."
            )
        else:
            name = args[0]
            student = select_student_by_name(name,
                                             self._storage,
                                             self.printer,
                                             mode='my')

            if student is None:
                self.printer.warning(f"Student {name} could not be found.")
            else:
                success, update_count = self._muesli. \
                    updated_presented(self.printer,
                                      self._storage.muesli_data.presentation.name,
                                      [student])
                if success:
                    self.printer.confirm(f"MÜSLI: {student} has presented")
                    self._storage.set_presented_for(student)
                else:
                    self.printer.error(
                        "MÜSLI: Some error occurred. Please check connection state."
                    )
    def _identify_students(self, name_part):
        self._printer.inform(f"Finding students in '{self._file_name}'.")

        student_names = []
        for student_name in name_part.split("__"):
            student_name = student_name.replace("_", " ")
            if len(student_name) > 0:
                student_names.append(student_name)

        for student_name in student_names:
            if any(char.isdigit() for char in student_name):
                if self.ask_retry(
                        f"Is '{student_name}' really a student name? (y/n)?",
                        f"'{student_name}' could not be interpreted as a student name."
                ) != 'y':
                    self._printer.inform("Skip")
                    continue

            # Try to find student
            student = select_student_by_name(student_name,
                                             self._storage,
                                             self._printer,
                                             mode='all')
            # Look up matches in previous sheets
            if student is None and student_name in self._storage.student_name_matches:
                student = self._storage.student_name_matches[student_name]
            if student is None:
                student = self._manual_single_student(student_name)
                # Store this match so that no manual correction is needed in the future
                self._storage.add_student_name_match(student_name, student)
            self.students.append(student)
Exemplo n.º 5
0
    def __call__(self, *args, **kwargs):
        value = args[0]
        student = select_student_by_name(value,
                                         self._storage,
                                         self.printer,
                                         self._storage.export_student,
                                         mode='my')

        if student is not None:
            tutorial = self._storage.get_tutorial_by_id(student.tutorial_id)
            self.printer.inform(
                f"The student '{student}' from {tutorial.time} was exported.")
            self.printer.inform(f"Workflow commands will ignore this student.")
Exemplo n.º 6
0
    def __call__(self, *args, **kwargs):
        value = args[0]
        student = select_student_by_name(value,
                                         self._storage,
                                         self.printer,
                                         self._storage.import_student,
                                         mode='other')

        if student is not None:
            tutorial = self._storage.get_tutorial_by_id(student.tutorial_id)
            self.printer.inform(
                f"The student '{student}' from {tutorial.time} was imported.")
            self.printer.inform(
                f"Workflow commands will also consider this student now as your own."
            )
Exemplo n.º 7
0
    def __call__(self, *args, **kwargs):
        value = args[0]
        student = select_student_by_name(value,
                                         self._storage,
                                         self.printer,
                                         mode='my')

        if student is not None:
            self._storage.export_student(student)
            tutorial = self._storage.get_tutorial_by_id(student.tutorial_id)
            self.printer.inform(
                f"The student '{student}' from {tutorial.time} was deregistered from your group."
            )
            self.printer.inform(f"Workflow commands will ignore this student.")
        else:
            self.printer.warning(f"Student {value} could not be found")
Exemplo n.º 8
0
    def __call__(self, *args, **kwargs):
        value = args[0]
        student = select_student_by_name(value,
                                         self._storage,
                                         self.printer,
                                         mode='other')

        if student is not None:
            self._storage.import_student(student)
            tutorial = self._storage.get_tutorial_by_id(student.tutorial_id)
            self.printer.inform(
                f"The student '{student}' from {tutorial.time} was registered as your student."
            )
            self.printer.inform(
                f"Workflow commands will also consider this student now as your own."
            )
        else:
            self.printer.warning(f"Student {value} could not be found.")
Exemplo n.º 9
0
    def _identify_students(self, name_part):
        self._printer.inform(f"Finding students in '{self._file_name}'.")

        student_names = []
        for student_name in name_part.split("_"):
            parts = re.findall(r'[A-Z](?:[a-zöäüß]+|[A-Z]*(?=[A-Z]|$))',
                               student_name)
            if len(parts) > 0:
                student_name = ("-".join(parts))

            student_name = student_name.split("-")
            student_name = " ".join(student_name)
            if len(student_name) > 0:
                student_names.append(student_name)

        for student_name in student_names:
            if any(char.isdigit() for char in student_name):
                if self.ask_retry(
                        f"Is '{student_name}' really a student name? (y/n)?",
                        f"'{student_name}' could not be interpreted as a student name."
                ) != 'y':
                    self._printer.inform("Skip")
                    continue

            # Try to find student
            student = select_student_by_name(student_name,
                                             self._storage,
                                             self._printer,
                                             mode='all')
            if student is None:
                student = self._manual_single_student(student_name)
                if student is None:
                    self._printer.error(
                        "Manual correction failed! Ignoring student.")
            if student is not None:
                self.students.append(student)
Exemplo n.º 10
0
    def __call__(self, present_name):
        folder = Path(self._storage.get_presented_folder(present_name))
        if not folder.is_dir():
            folder.mkdir(parents=True)

        names = {}
        names_file = folder / "names.json"
        if names_file.is_file():
            with open(names_file, "r") as fp:
                names = {
                    name: self._storage.get_student_by_muesli_id(muesli_id)
                    for name, muesli_id in load(fp).items()
                }

            if len(names) > 0:
                self.printer.warning(
                    f"{len(names)} names were already parsed.")
                self.printer.inform("You have the following options:")
                self.printer.indent()
                self.printer.inform("a) Restart from scratch,")
                self.printer.inform("b) Keep existing names and add any new,")
                self.printer.inform("c) Abort.")
                self.printer.outdent()
                while True:
                    answer = self.printer.ask(
                        "Please choose an option (a/b/c):")
                    if answer in "abc":
                        if answer == "a":
                            names = {}
                        elif answer == "b":
                            pass
                        elif answer == "c":
                            return
                        break

        self.printer.inform("Please put .txt files with the students' names "
                            f"into {folder}.")
        self.printer.indent()
        for name_file in folder.glob("*.txt"):
            self.printer.inform(f"- Found: {name_file.name}")
        self.printer.outdent()
        self.printer.inform("You can now put additional files in the folder, "
                            "then hit enter.")
        self.printer.ask("")

        name_files = sorted(folder.glob("*.txt"))
        names_by_file = {}
        for name_file in name_files:
            name_file_names = set()
            with open(name_file, "r") as fp:
                for line in fp:
                    line = line.strip()
                    if len(line) > 0:
                        name_file_names.add(line)
            names_by_file[name_file.name] = name_file_names
        present_all_files = set.intersection(*names_by_file.values())
        present_any_file = set.union(*names_by_file.values())
        self.printer.confirm(f"Found a total of {len(present_any_file)} names "
                             f"in {len(name_files)} files.")

        reference_names = None
        self.printer.indent()
        for name_file, name_file_names in names_by_file.items():
            if reference_names is None:
                self.printer.inform(f"{name_file}: {len(name_file_names)}")
            else:
                new_students = name_file_names - reference_names
                gone_students = reference_names - name_file_names
                self.printer.inform(f"{name_file}: {len(name_file_names)} "
                                    f"(+{len(new_students)}, "
                                    f"-{len(gone_students)})")
            reference_names = name_file_names
        self.printer.inform(f"{len(present_all_files)} present in all files.")
        self.printer.outdent()

        for name in sorted(present_any_file, key=str.casefold):
            student = select_student_by_name(name, self._storage, self.printer)
            if student is None and name in self._storage.student_name_matches:
                student = self._storage.student_name_matches[name]
                self.printer.inform(f"Loaded '{name}' -> {student} from "
                                    f"previous manual choice.")
            if student is None:
                self.printer.warning("Manual correction needed! Who is "
                                     f"'{name}'?")
                self.printer.inform(f"Please enter a new name or type '-':")
                while True:
                    answer = self.printer.ask("Alternative name: ")
                    if answer == "-":
                        self.printer.warning(f"Ignoring '{name}'.")
                        break
                    student = select_student_by_name(answer, self._storage,
                                                     self.printer)
                    if student is None:
                        self.printer.warning(
                            f"Could not find student '{answer}'. Please "
                            f"try again or type '-'. Who is '{name}'?")
                    else:
                        self.printer.confirm(f"{name} is {student}.")
                        self._storage.add_student_name_match(name, student)
                        break

            if student is not None:
                names[name] = student

        with open(names_file, "w") as fp:
            dump(
                {
                    name: student.muesli_student_id
                    for name, student in names.items()
                }, fp)
        self._storage.save_student_name_matches()
        self.printer.confirm(f"Stored {len(names)} names.")

        yes_students = list(names.values())
        self.printer.inform("Saving to Muesli …")
        with self._muesli:
            self._muesli.updated_presented(present_name, self.printer,
                                           yes_students)
            self.printer.confirm("Saved to Muesli.")

            all_students = self._storage.get_all_students_of_tutorial(
                yes_students[0].tutorial_id)
            no_students = [
                student for student in all_students
                if student not in yes_students
            ]
            if self.printer.yes_no(
                    f"Grade remaining {len(no_students)} students "
                    f"with zero points?"):
                self.printer.inform("Saving to Muesli …")
                self._muesli.updated_presented(present_name,
                                               self.printer,
                                               no_students,
                                               value=0)
                self.printer.confirm("Saved to Muesli.")