Example #1
0
    def update_table(self):
        """update table widget - signal"""
        try:
            horizontal_header_labels = ["Student ID"]
            horizontal_header_labels += get_all_test_items(
                self.comboBox_moduleCode.currentText(),
                self.comboBox_week.currentText())
            horizontal_header_labels += ["Attempts Left", "Total Marks"]
            self.tableWidget.setColumnCount(len(horizontal_header_labels))
            student_ids = get_all_student_ids(
                self.comboBox_moduleCode.currentText())
            self.tableWidget.setRowCount(len(student_ids))
            self.tableWidget.setHorizontalHeaderLabels(
                horizontal_header_labels)

            # write student ids
            col = 0
            for _id in student_ids:
                self.tableWidget.setItem(col, 0, QTableWidgetItem(_id))
                col += 1
            # write attendance, compilation, test1, test2 ....
            try:
                for row in range(self.tableWidget.rowCount()):
                    student_id = self.tableWidget.item(row, 0).text().strip()
                    vars_filepath = const.get_vars_file_path(
                        self.comboBox_moduleCode.currentText(),
                        self.comboBox_week.currentText(), student_id)
                    with open(vars_filepath, 'r') as stream:
                        data: dict = yaml.safe_load(stream)
                    for label in horizontal_header_labels[1:-2]:
                        if label in data.keys():
                            self.tableWidget.setItem(
                                row, self.columnFromLabel(label),
                                QTableWidgetItem(str(data[label])))
            except Exception as e:
                print(e)
            # write attempts left and total marks
            try:
                for row in range(self.tableWidget.rowCount()):
                    student_id = self.tableWidget.item(row, 0).text().strip()
                    vars_filepath = const.get_vars_file_path(
                        self.comboBox_moduleCode.currentText(),
                        self.comboBox_week.currentText(), student_id)
                    with open(vars_filepath, 'r') as stream:
                        data: dict = yaml.safe_load(stream)
                    if "attemptsLeft" in data.keys():
                        self.tableWidget.setItem(
                            row, self.columnFromLabel("Attempts Left"),
                            QTableWidgetItem(str(data["attemptsLeft"])))
                    if "marks" in data.keys():
                        self.tableWidget.setItem(
                            row, self.columnFromLabel("Total Marks"),
                            QTableWidgetItem(str(data["marks"])))
            except Exception as e:
                print(e)
        except Exception as e:
            print(e)
            self.tableWidget.clear()
Example #2
0
def createVarsFile(name, sock):
    """Create vars file for a specific student"""
    send_message("OK", sock)
    module_code = recv_message(sock)
    student_id = recv_message(sock)
    assignment_name = recv_message(sock)
    vars_filepath = const.get_vars_file_path(module_code, assignment_name,
                                             student_id)
    vars_directory = os.path.dirname(vars_filepath)
    if not os.path.isdir(vars_directory):
        os.makedirs(vars_directory)

    submissions_archive.archive(student_id, module_code, const.whatAY(),
                                assignment_name)

    date_file = vars_directory + "/submission-date.txt"
    current_date = datetime.now()
    current_date = current_date.strftime(SUBMISSION_DATE_FORMAT)

    with open(date_file, 'w+') as file:
        file.write(current_date)

    if not os.path.exists(vars_filepath):
        with open(vars_filepath, 'w'):
            pass
        send_message("Success", sock)
    elif os.path.isfile(vars_directory + "/reinit.attempts"):
        send_message("Reinit", sock)
    else:
        send_message("Failed", sock)
    RetrCommand(name, sock)
def initVarsFile(name, sock):
    """init vars.yaml file"""
    sock.sendall(b"OK")
    module_code = sock.recv(1024).decode()
    student_id = sock.recv(1024).decode()
    week_number = sock.recv(1024).decode()
    vars_filepath = const.get_vars_file_path(module_code, week_number, student_id)
    data = {
        "attemptsLeft": get_total_attempts(module_code, week_number),
        "marks": 0,
    }
    with open(vars_filepath, 'w') as f:
        yaml.dump(data, f, default_flow_style=False)
    RetrCommand(name, sock)
def createVarsFile(name, sock):
    """Create vars file for a specific student"""
    sock.sendall(b"OK")
    module_code = sock.recv(1024).decode()
    student_id = sock.recv(1024).decode()
    week_number = sock.recv(1024).decode()
    vars_filepath = const.get_vars_file_path(module_code, week_number, student_id)
    if not os.path.exists(vars_filepath):
        with open(vars_filepath, 'w'):
            pass
        sock.sendall(b"Success")
        RetrCommand(name, sock)
        return
    sock.sendall(b"Failed")
    RetrCommand(name, sock)
def checkAttemptsLeft(name, sock):
    """check number of attempts left"""
    sock.sendall(b"OK")
    module_code = sock.recv(1024).decode()
    student_id = sock.recv(1024).decode()
    week_number = sock.recv(1024).decode()
    # read vars.yaml file to get attemptsLeft value
    vars_filepath = const.get_vars_file_path(module_code, week_number, student_id)
    with open(vars_filepath, 'r') as stream:
        data: dict = yaml.safe_load(stream)
    if data.get("attemptsLeft"):
        sock.sendall(str(data.get("attemptsLeft")).encode('utf-8'))
    else:
        sock.sendall(b"False")
        print("ERROR: attemptsLeft doesn't exist!!!")
    RetrCommand(name, sock)
Example #6
0
def _checkAttemptsLeft(module_code, assignment_name, student_id):
    exceptions = getStudentExceptions(module_code, assignment_name, student_id)

    if exceptions is None:
        # read vars.yaml file to get attemptsLeft value
        vars_filepath = const.get_vars_file_path(module_code, assignment_name,
                                                 student_id)
        with open(vars_filepath, 'r') as stream:
            data: dict = yaml.safe_load(stream)
        if data.get("attemptsLeft"):
            return str(data.get("attemptsLeft"))
        else:
            print("ERROR: attemptsLeft doesn't exist!!!")
            return "False"
    else:
        if 'totalAttempts' in exceptions:
            return str(exceptions['totalAttempts'])
        else:
            print("ERROR: attemptsLeft doesn't exist!!!")
            return "False"
Example #7
0
def initVarsFile(name, sock):
    """init vars.yaml file"""
    send_message("OK", sock)
    module_code = recv_message(sock)
    student_id = recv_message(sock)
    assignment_name = recv_message(sock)
    vars_filepath = const.get_vars_file_path(module_code, assignment_name,
                                             student_id)
    params_filepath = const.get_params_file_path(module_code, assignment_name)
    vars_directory = os.path.dirname(vars_filepath)

    if os.path.isfile(vars_directory + "/reinit.attempts"):
        print("Re-initialising attempts to excepted attempts")
        os.remove(vars_directory + "/reinit.attempts")
        re_initialise_attempts(vars_filepath, module_code, assignment_name,
                               student_id)
    else:
        with open(params_filepath, 'r') as stream:
            params: dict = yaml.safe_load(stream)

        data = {
            "attemptsLeft":
            get_total_attempts(module_code, assignment_name, student_id),
            "marks":
            0,
        }

        if 'attendance' in params:
            data['attendance'] = 0

        if 'compilation' in params:
            data['compilation'] = 0

        with open(vars_filepath, 'w') as f:
            yaml.dump(data, f, default_flow_style=False)

    RetrCommand(name, sock)
Example #8
0
def getExecResult(name, sock):
    """Exec the program and get exec result"""
    send_message("OK", sock)
    module_code = recv_message(sock)
    assignment_name = recv_message(sock)
    student_id = recv_message(sock)
    file_suffix = recv_message(sock)
    penalty = recv_message(sock)
    curr_marks: int = 0
    result_msg: str = ""

    required_code_filename = get_required_code_filename(
        module_code, assignment_name)
    code_filepath = const.get_program_file_path(module_code, assignment_name,
                                                student_id,
                                                required_code_filename)
    params_filepath = const.get_params_file_path(module_code, assignment_name)
    vars_filepath = const.get_vars_file_path(module_code, assignment_name,
                                             student_id)
    vars_directory = os.path.dirname(vars_filepath)
    with open(params_filepath, 'r') as stream:
        data: dict = yaml.safe_load(stream)
    with open(vars_filepath, 'r') as stream:
        vars_data: dict = yaml.safe_load(stream)

    attempts_left = _checkAttemptsLeft(module_code, assignment_name,
                                       student_id)

    # check if attempts left
    if attempts_left != "False" and int(attempts_left) > 0:
        if "tests" in data and data["tests"]:
            tests = data["tests"]
            # if attendance exists, check attendance, assign marks
            if "attendance" in tests:
                attendance = tests["attendance"]
                attendance_marks = int(attendance["marks"])
                attendance_tag = attendance["tag"]
                curr_marks = curr_marks + attendance_marks
                result_msg += "%s: %d/%d\n" % (
                    attendance_tag, attendance_marks, attendance_marks)
                vars_data["attendance"] = attendance_marks
            """Execute the program specified by test"""
            # if compilation exists, check compilation, assign marks

            with handinexecutor.start() as executor:
                compilation_successful = True
                if "compilation" in tests:
                    compilation = tests["compilation"]
                    compilation_marks = int(compilation["marks"])
                    compilation_tag = compilation["tag"]
                    compilation_command = compilation["command"]

                    compile_proc = executor.compile(
                        path_to_file=code_filepath,
                        compile_command=compilation_command,
                        language=None)
                    compilation_successful = compile_proc.exit_code == 0

                    if compilation_successful:
                        vars_data["compilation"] = compilation_marks
                        result_msg += "%s: %d/%d\n" % (compilation_tag,
                                                       compilation_marks,
                                                       compilation_marks)
                        curr_marks += compilation_marks
                    else:
                        # compilation failed
                        result_msg += "%s: %d/%d\n" % (compilation_tag, 0,
                                                       compilation_marks)
                        vars_data["compilation"] = 0
                        test_output(vars_directory, "compilation",
                                    compile_proc.stderr, False)
                        with open(vars_filepath, 'w') as f:
                            yaml.dump(vars_data, f)

                if compilation_successful:
                    for key in tests.keys():
                        if key.startswith("test"):
                            test_marks = int(tests[key]["marks"])
                            test_tag = tests[key]["tag"]
                            test_command = tests[key]["command"]
                            input_data_file_path, answer_file_path, filter_file_path = get_file_paths(
                                tests[key])
                            filter_command = tests[key]["filterCommand"]

                            stdin_input = None
                            if input_data_file_path is not None and input_data_file_path != '':
                                input_data_file = open(input_data_file_path,
                                                       'r')
                                stdin_input = input_data_file.read()
                                input_data_file.close()

                            # change working directory
                            os.chdir(os.path.dirname(code_filepath))
                            exec1 = executor.run(path_to_file=code_filepath,
                                                 run_command=test_command,
                                                 language=None,
                                                 stdin=stdin_input)

                            if exec1.exit_code != 0:
                                # custom test failed
                                result_msg += "%s: %d/%d</br> " % (test_tag, 0,
                                                                   test_marks)
                                test_marks = 0
                                test_output(vars_directory, key,
                                            "Stderr: " + exec1.stderr, False)
                            else:
                                if exec1.timeout:
                                    # custom test failed
                                    result_msg += "%s: %d/%d</br> " % (
                                        test_tag, 0, test_marks)
                                    test_marks = 0
                                    test_output(vars_directory, key,
                                                "Test execution timed out",
                                                False)
                                else:
                                    if const.PROGRAM_SYSCALL_MONITORING and not executor.copy_syscall_log(
                                            vars_directory, key):
                                        print(
                                            "Warning: failed to copy syscall_monitor log"
                                        )

                                    output = exec1.stdout
                                    if answer_file_path is not None and answer_file_path != '':
                                        answer_file = open(
                                            answer_file_path, 'rb')
                                        answer = answer_file.read()

                                        # use stdout and answer as two argv of filter file, then perform filtering
                                        # TODO: may need to be changed ...
                                        if (filter_file_path is not None and filter_file_path != '') and \
                                                (filter_command is not None and filter_command != ''):
                                            try:
                                                # copy filter file to student dir
                                                filter_filename = os.path.basename(
                                                    filter_file_path)
                                                filter_file_path_dst = os.path.join(
                                                    os.path.dirname(
                                                        code_filepath),
                                                    filter_filename)
                                                with open(
                                                        filter_file_path_dst,
                                                        'w'):
                                                    pass
                                                shutil.copyfile(
                                                    filter_file_path,
                                                    filter_file_path_dst)

                                                os.chdir(
                                                    os.path.dirname(
                                                        filter_file_path_dst))
                                                output = replace_whitespace_with_underscore(
                                                    output.decode('utf-8')
                                                ).encode('utf-8')
                                                answer = replace_whitespace_with_underscore(
                                                    answer.decode('utf-8')
                                                ).encode('utf-8')
                                                command: str = (
                                                    filter_command + " %s %s"
                                                ) % (output.decode('utf-8'),
                                                     answer.decode('utf-8'))
                                                filter_proc = Popen(
                                                    command,
                                                    stdin=PIPE,
                                                    stdout=PIPE,
                                                    stderr=PIPE,
                                                    shell=True)
                                                stdout, stderr = filter_proc.communicate(
                                                )
                                                output, answer = stdout.decode(
                                                    'utf-8').split(' ')
                                            except Exception as e:
                                                print(e)
                                        else:
                                            answer = answer.decode()

                                        if compare_output_with_answer(
                                                output, answer):
                                            # custom test success
                                            curr_marks = curr_marks + test_marks
                                            result_msg += "%s: %d/%d</br> " % (
                                                test_tag, test_marks,
                                                test_marks)
                                            test_output(
                                                vars_directory, key, output,
                                                True)
                                        else:
                                            # custom test failed
                                            result_msg += "%s: %d/%d</br> " % (
                                                test_tag, 0, test_marks)
                                            test_marks = 0
                                            test_output(
                                                vars_directory, key, output,
                                                False)
                                            test_output(
                                                vars_directory, key, answer,
                                                None, "Answer File")
                                    else:
                                        # custom test success
                                        curr_marks = curr_marks + test_marks
                                        result_msg += "%s: %d/%d</br> " % (
                                            test_tag, test_marks, test_marks)
                                        test_output(vars_directory, key,
                                                    output, True)

                            vars_data[key] = test_marks

        # check assignment attempts left and update attempts left
        if "attemptsLeft" in vars_data and vars_data["attemptsLeft"]:
            attemptsLeft = vars_data["attemptsLeft"]
            vars_data["attemptsLeft"] = attemptsLeft - 1
            attemptsLeft -= 1
            if attemptsLeft <= 0:
                vars_data["attemptsLeft"] = 0
                attemptsLeft = 0
            with open(vars_filepath, 'w') as f:
                yaml.dump(vars_data, f)
            result_msg += "</br>You have %s attempts left</br> " % str(
                attemptsLeft)

            # apply penalty
            curr_marks = int(
                round(curr_marks - (curr_marks * (int(penalty) / 100))))
            result_msg += f"</br>Penalty: {penalty}%</br> "

            if curr_marks < 0:
                curr_marks = 0

            # update student marks
            with open(vars_filepath, 'r') as stream:
                vars_data2: dict = yaml.safe_load(stream)
            if "marks" in vars_data2.keys():
                vars_data2["marks"] = curr_marks
            with open(vars_filepath, 'w') as f:
                yaml.dump(vars_data2, f)
            result_msg += f"</br>Total marks: {curr_marks}</br> "
            submissions_archive.cull_old_archives(
            )  # this is a successful submission so, you are free to remove old ones
    else:
        result_msg = "Sorry, you have no attempts left for this assignment!"
        submissions_archive.undo_archive(
        )  # unsuccessful submission, remove newest archive and don't remove any old ones

    send_message(result_msg, sock)
    RetrCommand(name, sock)
def getExecResult(name, sock):
    """Exec the program and get exec result"""
    sock.sendall(b"OK")
    module_code = sock.recv(1024).decode()
    week_number = sock.recv(1024).decode()
    student_id = sock.recv(1024).decode()
    file_suffix = sock.recv(1024).decode()
    penalty = sock.recv(1024).decode()

    if file_suffix == "cc" or file_suffix == "cpp":
        lang = "c++"
    elif file_suffix == "java":
        lang = "java"

    curr_marks: int = 0
    result_msg: str = ""
    required_code_filename = get_required_code_filename(module_code, week_number)
    code_filepath = const.get_program_file_path(module_code, week_number, student_id, required_code_filename)
    params_filepath = const.get_params_file_path(module_code, week_number)
    vars_filepath = const.get_vars_file_path(module_code, week_number, student_id)
    with open(params_filepath, 'r') as stream:
        data: dict = yaml.safe_load(stream)
    with open(vars_filepath, 'r') as stream:
        vars_data: dict = yaml.safe_load(stream)

    # check if attempts left
    if vars_data["attemptsLeft"] and vars_data["attemptsLeft"] > 0:
        if data["tests"]:
            # if attendance exists, check attendance, assign marks
            if data["tests"]["attendance"]:
                attendance_marks = int(data["tests"]["attendance"]["marks"])
                attendance_tag = data["tests"]["attendance"]["tag"]
                curr_marks = curr_marks + attendance_marks
                result_msg += "%s: %d/%d\n" % (attendance_tag, attendance_marks, attendance_marks)
                vars_data["attendance"] = attendance_marks

            # if compilation exists, check compilation, assign marks
            if data["tests"]["compilation"]:
                compilation_marks = int(data["tests"]["compilation"]["marks"])
                compilation_tag = data["tests"]["compilation"]["tag"]
                compilation_command = data["tests"]["compilation"]["command"]

                # change working directory
                os.chdir(os.path.dirname(code_filepath))

                p = Popen(compilation_command, stdout=PIPE, shell=True)
                return_code = p.wait()
                if return_code == 0:
                    # compilation successful
                    curr_marks = curr_marks + compilation_marks
                    result_msg += "%s: %d/%d\n" % (compilation_tag, compilation_marks, compilation_marks)
                    vars_data["compilation"] = compilation_marks

                    # execute the rest of custom tests when compilation success
                    for key in data["tests"].keys():
                        if key.startswith("test"):
                            test_marks = int(data["tests"][key]["marks"])
                            test_tag = data["tests"][key]["tag"]
                            test_command = data["tests"][key]["command"]
                            input_data_file_path = data["tests"][key]["inputDataFile"]
                            answer_file_path = data["tests"][key]["answerFile"]
                            filter_file_path = data["tests"][key]["filterFile"]
                            filter_command = data["tests"][key]["filterCommand"]
                            if input_data_file_path is not None and input_data_file_path != '':
                                input_data_file = open(input_data_file_path, 'r')

                                # change working directory
                                os.chdir(os.path.dirname(code_filepath))
                                proc = Popen(test_command, stdin=input_data_file, stdout=PIPE, stderr=PIPE, shell=False)
                                output, stderr = proc.communicate()  # bytes

                                # compare stdout with the answer file
                                if answer_file_path is not None and answer_file_path != '':
                                    answer_file = open(answer_file_path, 'rb')
                                    answer: bytes = answer_file.read()

                                    # use stdout and answer as two argv of filter file, then perform filtering
                                    # TODO: may need to be changed ...
                                    if (filter_file_path is not None and filter_file_path != '') and \
                                            (filter_command is not None and filter_command != ''):
                                        try:
                                            # copy filter file to student dir
                                            filter_filename = os.path.basename(filter_file_path)
                                            filter_file_path_dst = os.path.join(os.path.dirname(code_filepath), filter_filename)
                                            with open(filter_file_path_dst, 'w'):
                                                pass
                                            shutil.copyfile(filter_file_path, filter_file_path_dst)

                                            os.chdir(os.path.dirname(filter_file_path_dst))
                                            output = replace_whitespace_with_underscore(output.decode('utf-8')).encode('utf-8')
                                            answer = replace_whitespace_with_underscore(answer.decode('utf-8')).encode('utf-8')
                                            command: str = (filter_command + " %s %s") % (output.decode('utf-8'), answer.decode('utf-8'))
                                            filter_proc = Popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True)
                                            stdout, stderr = filter_proc.communicate()
                                            output, answer = stdout.decode('utf-8').split(' ')
                                        except Exception as e:
                                            print(e)

                                    if compare_output_with_answer(str(output), str(answer)):
                                        # custom test success
                                        curr_marks = curr_marks + test_marks
                                        result_msg += "%s: %d/%d</br>" % (test_tag, test_marks, test_marks)
                                        vars_data[key] = test_marks
                                    else:
                                        # custom test failed
                                        result_msg += "%s: %d/%d</br>" % (test_tag, 0, test_marks)
                                        vars_data[key] = 0

                else:
                    # compilation failed
                    result_msg += "%s: %d/%d\n" % (compilation_tag, 0, compilation_marks)
                    vars_data["compilation"] = 0

                with open(vars_filepath, 'w') as f:
                    yaml.dump(vars_data, f)

            # check assignment attempts left and update attempts left
            vars_filepath = const.get_vars_file_path(module_code, week_number, student_id)
            with open(vars_filepath, 'r') as stream:
                vars_data: dict = yaml.safe_load(stream)
            if vars_data["attemptsLeft"]:
                vars_data["attemptsLeft"] = vars_data["attemptsLeft"] - 1
                if vars_data["attemptsLeft"] <= 0:
                    vars_data["attemptsLeft"] = 0
            with open(vars_filepath, 'w') as f:
                yaml.dump(vars_data, f)
            result_msg += "\n\nYou have %s attempts left\n\n" % str(vars_data["attemptsLeft"])

            # apply penalty
            curr_marks = curr_marks - int(penalty)
            result_msg += "\n\nPenalty: %s\n\n" % str(penalty)

            # update student marks
            with open(vars_filepath, 'r') as stream:
                vars_data2: dict = yaml.safe_load(stream)
            if "marks" in vars_data2.keys():
                vars_data2["marks"] = curr_marks
            with open(vars_filepath, 'w') as f:
                yaml.dump(vars_data2, f)
            result_msg += "\n\nTotal marks: %s\n\n" % str(curr_marks)
    else:
        result_msg = "Sorry, you have no attempts left for this assignment!"

    sock.sendall(result_msg.encode())
    RetrCommand(name, sock)