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()
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)
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"
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)
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)