def test_get_course_id(app): with app.app_context(): identifiers = {'abxce': 1, 'tryui': 2, 'oiuyt': 3, 'ertyu': 4} course_db = CourseDB() for key in identifiers: course_id = course_db.get_course_id(key) assert course_id[0] == identifiers[key]
def validate_all(pre_post, course_name): """Set the time validity for all students of a course to 1.""" course_db = CourseDB() course_id = course_db.get_course_id(course_name)[0] questionnaire_db = QuestionnaireDB() if pre_post not in ["pre", "post"]: print("Unknown pre_post specifier {}, should be 'pre' or 'post'" "".format(pre_post)) return query = """ UPDATE student_{} SET valid_time = 1 WHERE student_id IN ( SELECT student_id FROM student_course WHERE course_id = ? ) """.format(pre_post) questionnaire_db.execute(query, (course_id, )) questionnaire_db.db.commit()
def test_get_similar_course(app): with app.app_context(): similar = {1: [4], 2: [None], 3: [None], 4: [1]} course_db = CourseDB() for key in similar: similar_ids = course_db.get_similar_course_ids(key) for indx, val in enumerate(similar_ids): assert val[0] == similar[key][indx]
def get_unmatched_students(): """Get all valid unmatched responses, sorted by course.""" course_db = CourseDB() course_data = list(course_db.get_all_course_data()) questionnaire_db = QuestionnaireDB() data = pd.DataFrame(columns=["course_id", "pre", "post"]) for course in course_data: course_id = course["id"] def get_unmatched(pre_post, course_id): other = "post" if pre_post == "pre" else "pre" res = questionnaire_db.execute( """ SELECT student.code FROM student, student_{0}, student_course WHERE student_{0}.student_id = student_course.student_id AND student_course.course_id = ? AND student_{0}.valid_control = 1 AND student_{0}.valid_time = 1 AND student.id = student_{0}.student_id AND student_{0}.student_id NOT IN ( SELECT student_id FROM student_{1} ) """.format(pre_post, other), (course_id, )) return res pre = get_unmatched("pre", course_id) for row in pre: data = data.append( { "course_id": course_id, "pre": row[0], "post": "" }, ignore_index=True) post = get_unmatched("post", course_id) for row in post: data = data.append( { "course_id": course_id, "pre": "", "post": row[0] }, ignore_index=True) data.to_csv("/app/instance/unmatched.csv", index=False)
def test_get_course_dates(app, MonkeyDBDates): with app.app_context(): course_db = CourseDB() times = course_db.get_course_questionnaire_dates(1) # dummy values from conftest.py start_date_pre = str( int(time.mktime(datetime.date(2001, 1, 5).timetuple()))) start_date_post = str( int(time.mktime(datetime.date(2002, 1, 20).timetuple()))) assert times["pre"] == start_date_pre assert times["post"] == start_date_post
def test_course_report_info(app): with app.app_context(): results = { 1: ['Bachelor Physiker', 32], 2: ['Master Physiker Projekt', 16], 3: ['Nebenfach Grundpraktikum', 25], 4: ['Bachelor Physiker 2', 25], } course_db = CourseDB() for key in results: info = course_db.get_course_report_info(key) assert info[0] == results[key][0] assert info[1] == results[key][1]
def export(): """Export all matched responses to a csv at /app/instace/export.csv.""" cols = [ "course_id", "experience_id", "program_id", "course_type_id", "traditional_id", *["q_you_pre_" + str(i) for i in range(1, 31)], *["q_you_post_" + str(i) for i in range(1, 31)], *["q_expert_pre_" + str(i) for i in range(1, 31)], *["q_expert_post_" + str(i) for i in range(1, 31)], *["q_mark_" + str(i) for i in range(1, 24)], ] data = {} for col in cols: data[col] = [] course_db = CourseDB() questionnaire_db = QuestionnaireDB() course_data = list(course_db.get_all_course_data()) for course in course_data: course_id = course["id"] metadata_name = ("experience_id", "program_id", "course_type_id", "traditional_id") metadata = [course[name] for name in metadata_name] matched = questionnaire_db.get_matched_responses(course_id, disagreement=True) for i in range(matched.size()): data["course_id"].append(course_id) for indx, col in enumerate(metadata_name): data[col].append(metadata[indx]) for indx in range(1, 31): data["q_you_pre_" + str(indx)].append( matched.q_you_pre.responses[i][indx - 1]) data["q_you_post_" + str(indx)].append( matched.q_you_post.responses[i][indx - 1]) data["q_expert_pre_" + str(indx)].append( matched.q_expert_pre.responses[i][indx - 1]) data["q_expert_post_" + str(indx)].append( matched.q_expert_post.responses[i][indx - 1]) for indx in range(1, 24): data["q_mark_" + str(indx)].append( matched.q_mark.responses[i][indx - 1]) df = pd.DataFrame(data) # shuffle the data df = df.sample(frac=1).reset_index(drop=True) df.to_csv("/app/instance/export.csv")
def overview(): course_db = CourseDB() courses = course_db.get_overview(session['user_id']) past_courses = [] current_courses = [] for course in courses: course_post = datetime.strptime(course[7], '%d.%m.%Y').date() if course_post < date.today(): report_dir = os.path.join(current_app.instance_path, course[0]) if os.path.exists(report_dir): course = list(course) + [course[0]] past_courses.append(course) else: current_courses.append(course) return render_template('course/overview.html', current_courses=current_courses, past_courses=past_courses)
def insert_data(self, df): """Insert new data into the database.""" course_db = CourseDB() for _, row in df.iterrows(): course_id = course_db.get_course_id(row['course_id']) if course_id is not None: student_id = self._add_student(row['personal_code'], course_id[0]) else: student_id = self._add_student(row['personal_code']) self._add_student_unknown_course(student_id, row['course_id']) if row['pre_post'] == 1: questionnaire_id = self._add_pre_questionnaire(row) self._add_student_prepost(row, student_id, questionnaire_id, 'pre') elif row['pre_post'] == 2: questionnaire_id = self._add_post_questionnaire(row) self._add_student_prepost(row, student_id, questionnaire_id, 'post')
def parse(self, form): free_text = form[self.name + '_free'].strip() if not free_text: return super(QuestionDropdownWithText, self).parse(form) db = CourseDB() add_new_value = { 'university': db.add_and_get_id_university, 'equipment': db.add_and_get_id_equipment } new_id = add_new_value[self.name](free_text) return (self.name + '_id', new_id)
def get_unknown_courses(): """Get all course codes that could not be matched.""" course_db = CourseDB() course_data = list(course_db.get_all_course_data()) data = pd.DataFrame(columns=["known_courses", "unknown_courses"]) for course in course_data: data = data.append( { "known_courses": course["identifier"], "unknwon_courses": "" }, ignore_index=True) questionnaire_db = QuestionnaireDB() res = questionnaire_db.execute( "SELECT course_code FROM student_unknown_course", ()) for row in res: if row[0] is not None and row[0].strip() != "": data = data.append({ "known_courses": "", "unknwon_courses": row[0] }, ignore_index=True) data.to_csv("/app/instance/unknown.csv", index=False)
def AddValidity(df): """Check validity of row. valid_control tests for the correct answer of the control question and valid_time tests for if the end date is within 14 days of the begin of the post test. """ df["valid_control"] = df.apply(lambda row: CheckValidityControlRow(row), axis=1) df = df.drop(["qcontrol", "qcontrol2"], axis=1) course_db = CourseDB() df["valid_time"] = df.apply( lambda row: CheckValidityTimeRow(row, course_db), axis=1) return df
def __init__(self): self.db = CourseDB() self.values = {} self.questions = [ StartTab(), QuestionText( 'name', 'Name', 'Wählen Sie einen beliebigen Namen für den Kurs aus.'), QuestionDate( 'start_date_pre', 'Start Prä-Befragung', 'Start der Befragung vor dem Kurs. Die Befragung ist 14 Tage aktiv.' + 'Safari-Nutzer: Bitte in der Form 2019-03-16 angeben.'), QuestionDate( 'start_date_post', 'Start Post-Befragung', 'Start der Befragung nach dem Kurs. Die Befragung ist 14 Tage aktiv.' + 'Safari-Nutzer: Bitte in der Form 2019-03-16 angeben.'), QuestionDropdown( 'university_type', 'Art der Hochschule', 'An welcher Art von Hochschule findet der Kurs statt?', self.db.select_all_entries('university_type')), QuestionDropdownWithText( 'university', 'Hochschule', 'An welcher Hochschule findet der Kurs statt?', self.db.select_all_entries('university'), 'Andere'), QuestionDropdown('program', 'Studiengang', 'Zu welchen Studiengang gehört der Kurs?', self.db.select_all_entries('program')), QuestionDropdown('experience', 'Jahrgang', 'In welchem Jahrgang sind die Studenten?', self.db.select_all_entries('experience')), QuestionDropdown('course_type', 'Art des Kurses', 'Was für eine Art von Kurs ist es?', self.db.select_all_entries('course_type')), QuestionDropdown('traditional', 'Didaktische Methoden', 'Welche didaktischen Methoden benutzt der Kurs?', self.db.select_all_entries('traditional')), QuestionDropdown('focus', 'Schwerpunkt', 'Worauf liegt der Schwerpunkt des Kurses?', self.db.select_all_entries('focus')), QuestionNumber( 'number_students', 'Anzahl an Studenten', ('Wieviele Studenten werden voraussichtlich an dem Kurs ' + 'teilnehmen?'), default=0, value_range=(0, 1000)), QuestionNumber( 'students_per_instructor', 'Verhältnis Studenten/Betreuer', 'Wieviele Studenten kommen in etwa auf einen Betreuer?', default=0, value_range=(0, 100)), QuestionNumber( 'number_experiments', 'Nummer von Experimenten', 'Wieviele Experimente muss jeder Student durchführen?', default=0, value_range=(0, 1000)), QuestionNumber('number_projects', 'Nummer von Projekten', 'Wieviele Projekte muss jeder Student durchführen?', default=0, value_range=(0, 1000)), QuestionNumber( 'lab_per_lecture', 'Verhältnis Praktikum/Vorlesung', 'Wie ist das Verhältnis von Praktikum zu Vorlesung? (Angabe als z.B. 0.5)', default=0, value_range=(0, 100), step=0.1), QuestionNumber('hours_per_lab', 'Länge eines Termins', 'Wieviele Stunden dauert ein Termin?', default=0, value_range=(0, 24), step=0.01), QuestionNumber('number_labs', 'Anzahl Termine', 'Wieviele Termine gibt es?', default=0, value_range=(0, 1000)), QuestionNumber('week_guided', 'Geführte Wochen', 'Wieviel Wochen sind die Experiment geführt?', default=0, value_range=(0, 1000)), QuestionDropdownWithText( 'equipment', 'Geräte', 'Was für eine Art von Geräten wird hauptsächlich verwendet?', self.db.select_all_entries('equipment'), 'Andere'), EndTab(), StartTab(), QuestionFrequency( { 'frequency_phys_principle': 'bekannte physikalische Prinzipien verifizieren?', 'frequency_known_principle': 'bekannte physikalische Prinzipien durch selbstständiges Experimentieren wiederentdecken?', 'frequency_unknown_principle': 'offene Fragen untersuchen, deren Antwort unbekannt ist?' }, 'Wie oft werden Studenten in dem Praktikum ...'), QuestionFrequency( { 'students_questions': 'der eigenen Fragestellung?', 'students_plan': 'der Planung der Messmethode?', 'students_design': 'dem Design des Messaubaus?', 'students_apparatus': 'dem Aufbau der Messapparate?', 'students_analysis': 'der selbstständigen Ausarbeitung der Auswertung?', 'students_troubleshoot': 'dem Troubleshooting des Messapparates?', 'students_groups': 'der Gruppenarbeit?' }, 'Wie oft arbeiten Studenten an ...'), QuestionFrequency( { 'modeling_mathematics': 'die mathematische Modellierung des physikalischen Systems', 'modeling_model': 'die konzeptuelle Modellierung des physikalischen Systems', 'modeling_tools': 'Modellierung des physikalischen Aufbau', 'modeling_measurement': 'Modellierung der Messgeräte', 'modeling_predictions': 'Angabe von Vorhersagen, die durch mathematische oder physikalische Modelle entstehen', 'modeling_uncertainty': 'um das Messsystem order die Messprozedur zu verbessern und die Messunsicherheiten zu reduzieren', 'modeling_calibrate': 'Kalibrierung der Messgeräte' }, 'Studenten modellieren selbstständig durch ...'), QuestionFrequency( { 'analysis_uncertainty': 'der direkten Bestimmung der Messunsicherheiten', 'analysis_calculate': 'Bestimmung der Messunsicherheiten durch Fehlerfortpflanzung', 'analysis_computer': 'Berechnung/Visualisierung am Computer', 'analysis_control': 'Computersteuerung der Messgeräte' }, 'Studenten führen die Auswertung und die Visualisierung der Daten durch mit ...' ), QuestionFrequency( { 'communication_oral': 'die Ergebnisse in einer mündlichen Präsentation', 'communication_written': 'die Ergebnisse in einer schriftlichen Präsentation/Bericht', 'communication_journal': 'die Ergebnisse in Form eines Journalartikels', 'communication_lab': 'den Versuchsablauf in einem Laborbuch', 'communication_test': 'die Vorbereitung mit einem Testat' }, 'Studenten kommunizieren ...'), QuestionNote('notes', 'Notizen', ('Gibt es noch etwas, dass Sie uns sagen wollen? ' + 'Max. 255 Zeichen.')), EndTab() ]
class HandleCourseQuestions: """Handler for the questions about a new course. The member self.question contains all CourseQuestion objects. """ def __init__(self): self.db = CourseDB() self.values = {} self.questions = [ StartTab(), QuestionText( 'name', 'Name', 'Wählen Sie einen beliebigen Namen für den Kurs aus.'), QuestionDate( 'start_date_pre', 'Start Prä-Befragung', 'Start der Befragung vor dem Kurs. Die Befragung ist 14 Tage aktiv.' + 'Safari-Nutzer: Bitte in der Form 2019-03-16 angeben.'), QuestionDate( 'start_date_post', 'Start Post-Befragung', 'Start der Befragung nach dem Kurs. Die Befragung ist 14 Tage aktiv.' + 'Safari-Nutzer: Bitte in der Form 2019-03-16 angeben.'), QuestionDropdown( 'university_type', 'Art der Hochschule', 'An welcher Art von Hochschule findet der Kurs statt?', self.db.select_all_entries('university_type')), QuestionDropdownWithText( 'university', 'Hochschule', 'An welcher Hochschule findet der Kurs statt?', self.db.select_all_entries('university'), 'Andere'), QuestionDropdown('program', 'Studiengang', 'Zu welchen Studiengang gehört der Kurs?', self.db.select_all_entries('program')), QuestionDropdown('experience', 'Jahrgang', 'In welchem Jahrgang sind die Studenten?', self.db.select_all_entries('experience')), QuestionDropdown('course_type', 'Art des Kurses', 'Was für eine Art von Kurs ist es?', self.db.select_all_entries('course_type')), QuestionDropdown('traditional', 'Didaktische Methoden', 'Welche didaktischen Methoden benutzt der Kurs?', self.db.select_all_entries('traditional')), QuestionDropdown('focus', 'Schwerpunkt', 'Worauf liegt der Schwerpunkt des Kurses?', self.db.select_all_entries('focus')), QuestionNumber( 'number_students', 'Anzahl an Studenten', ('Wieviele Studenten werden voraussichtlich an dem Kurs ' + 'teilnehmen?'), default=0, value_range=(0, 1000)), QuestionNumber( 'students_per_instructor', 'Verhältnis Studenten/Betreuer', 'Wieviele Studenten kommen in etwa auf einen Betreuer?', default=0, value_range=(0, 100)), QuestionNumber( 'number_experiments', 'Nummer von Experimenten', 'Wieviele Experimente muss jeder Student durchführen?', default=0, value_range=(0, 1000)), QuestionNumber('number_projects', 'Nummer von Projekten', 'Wieviele Projekte muss jeder Student durchführen?', default=0, value_range=(0, 1000)), QuestionNumber( 'lab_per_lecture', 'Verhältnis Praktikum/Vorlesung', 'Wie ist das Verhältnis von Praktikum zu Vorlesung? (Angabe als z.B. 0.5)', default=0, value_range=(0, 100), step=0.1), QuestionNumber('hours_per_lab', 'Länge eines Termins', 'Wieviele Stunden dauert ein Termin?', default=0, value_range=(0, 24), step=0.01), QuestionNumber('number_labs', 'Anzahl Termine', 'Wieviele Termine gibt es?', default=0, value_range=(0, 1000)), QuestionNumber('week_guided', 'Geführte Wochen', 'Wieviel Wochen sind die Experiment geführt?', default=0, value_range=(0, 1000)), QuestionDropdownWithText( 'equipment', 'Geräte', 'Was für eine Art von Geräten wird hauptsächlich verwendet?', self.db.select_all_entries('equipment'), 'Andere'), EndTab(), StartTab(), QuestionFrequency( { 'frequency_phys_principle': 'bekannte physikalische Prinzipien verifizieren?', 'frequency_known_principle': 'bekannte physikalische Prinzipien durch selbstständiges Experimentieren wiederentdecken?', 'frequency_unknown_principle': 'offene Fragen untersuchen, deren Antwort unbekannt ist?' }, 'Wie oft werden Studenten in dem Praktikum ...'), QuestionFrequency( { 'students_questions': 'der eigenen Fragestellung?', 'students_plan': 'der Planung der Messmethode?', 'students_design': 'dem Design des Messaubaus?', 'students_apparatus': 'dem Aufbau der Messapparate?', 'students_analysis': 'der selbstständigen Ausarbeitung der Auswertung?', 'students_troubleshoot': 'dem Troubleshooting des Messapparates?', 'students_groups': 'der Gruppenarbeit?' }, 'Wie oft arbeiten Studenten an ...'), QuestionFrequency( { 'modeling_mathematics': 'die mathematische Modellierung des physikalischen Systems', 'modeling_model': 'die konzeptuelle Modellierung des physikalischen Systems', 'modeling_tools': 'Modellierung des physikalischen Aufbau', 'modeling_measurement': 'Modellierung der Messgeräte', 'modeling_predictions': 'Angabe von Vorhersagen, die durch mathematische oder physikalische Modelle entstehen', 'modeling_uncertainty': 'um das Messsystem order die Messprozedur zu verbessern und die Messunsicherheiten zu reduzieren', 'modeling_calibrate': 'Kalibrierung der Messgeräte' }, 'Studenten modellieren selbstständig durch ...'), QuestionFrequency( { 'analysis_uncertainty': 'der direkten Bestimmung der Messunsicherheiten', 'analysis_calculate': 'Bestimmung der Messunsicherheiten durch Fehlerfortpflanzung', 'analysis_computer': 'Berechnung/Visualisierung am Computer', 'analysis_control': 'Computersteuerung der Messgeräte' }, 'Studenten führen die Auswertung und die Visualisierung der Daten durch mit ...' ), QuestionFrequency( { 'communication_oral': 'die Ergebnisse in einer mündlichen Präsentation', 'communication_written': 'die Ergebnisse in einer schriftlichen Präsentation/Bericht', 'communication_journal': 'die Ergebnisse in Form eines Journalartikels', 'communication_lab': 'den Versuchsablauf in einem Laborbuch', 'communication_test': 'die Vorbereitung mit einem Testat' }, 'Studenten kommunizieren ...'), QuestionNote('notes', 'Notizen', ('Gibt es noch etwas, dass Sie uns sagen wollen? ' + 'Max. 255 Zeichen.')), EndTab() ] def __iter__(self): for question in self.questions: yield question def parse(self, form): """Parse a given form for the values for the new course. Args: form (dict(str: str)): The form returned from the webpage. Returns: A list of all the errors it encountered while parsing. >>> parse({"name": ""}) ["Name is required."] """ errors = [] for question in self.questions: try: parsed_data = question.parse(form) if parsed_data: if len(parsed_data) >= 2 and len(parsed_data[0]) == 2: for data in parsed_data: self.values[data[0]] = data[1] else: self.values[parsed_data[0]] = parsed_data[1] except Exception as e: errors.append(e) try: errors.extend(self._sanity_check()) except KeyError as e: pass return errors def _sanity_check(self): """Check the sanity of the data. 1. Check if both start-dates are in the future. 2. Post is after Pre Date 3. All frequency questions have int values between 0 and 3 """ errors = [] # all dates in future if not ((date.fromtimestamp(int(self.values['start_date_pre'])) > date.today()) & (date.fromtimestamp( int(self.values['start_date_post'])) > date.today())): errors.append('Das Anfangsdatum muss in der Zukunft liegen.') # post is after pre if not self.values['start_date_pre'] < self.values['start_date_post']: errors.append( 'Start Post-Befragung muss nach der Pre-Befragung sein.') frequency_questions = [ 'frequency_*', 'students_*^(?!_)', 'modeling_*', 'analysis_*', 'communication_*' ] for key in self.values: if any(re.match(expr, key) for expr in frequency_questions): if not (int(self.values[key]) in [0, 1, 2, 3]): errors.append('Flascher Wert im Feld {}'.format(key)) return errors def write(self, user_id): """Write the parsed values to the database. Args: user_id (str): The id of the owner of the new course. """ self.db.add_course(user_id, self.values)
def parse(self, form): if form[self.name]: db = CourseDB() new_id = db.add_and_get_id_note(form[self.name]) return (self.name + '_id', new_id) return None
def test_add_new_course(client, app, auth, MonkeyEmail): # non logged in user redirected to log in response = client.get('/add_course') assert response.headers['Location'] == 'http://localhost/auth/login' auth.login() response = client.post('/add_course', data={ 'name': 'phys_test', 'start_date_pre': '2030-03-16', 'start_date_post': '2031-04-16', 'university_type': '1', 'university': '1', 'program': '1', 'experience': '1', 'course_type': '1', 'traditional': '1', 'focus': '1', 'number_students': '20', 'students_per_instructor': '4', 'number_experiments': '5', 'number_projects': '1', 'lab_per_lecture': '2', 'hours_per_lab': '2.5', 'number_labs': '10', 'week_guided': '1', 'equipment': '1', 'frequency_phys_principle': '3', 'frequency_known_principle': '2', 'frequency_unknown_principle': '0', 'students_questions': '0', 'students_plan': '0', 'students_design': '0', 'students_apparatus': '0', 'students_analysis': '0', 'students_troubleshoot': '0', 'students_groups': '0', 'modeling_mathematics': '0', 'modeling_model': '0', 'modeling_tools': '0', 'modeling_measurement': '0', 'modeling_predictions': '0', 'modeling_uncertainty': '0', 'modeling_calibrate': '0', 'analysis_uncertainty': '0', 'analysis_calculate': '0', 'analysis_computer': '0', 'analysis_control': '0', 'communication_oral': '0', 'communication_written': '0', 'communication_journal': '0', 'communication_lab': '0', 'communication_test': '0', 'university_free': '', 'equipment_free': '', 'notes': '' }) # after successfully adding course reroute to index assert response.headers['Location'] == 'http://localhost/' # check if new course has really been inserted with app.app_context(): course_db = CourseDB() assert 'phys_test' in course_db.get_courses(user_id=2)[2] assert MonkeyEmail.called assert MonkeyEmail.recipient == '*****@*****.**' assert MonkeyEmail.subject == 'Kurs Registrierung GEclass' assert 'phys_test' in MonkeyEmail.content
def create_reports(): """Create the reports for all finished courses.""" course_db = CourseDB() questionnaire_db = QuestionnaireDB() finished_courses = course_db.get_postsurveys_starting_before( datetime.timedelta(days=15)) for (course_id, course_identifier) in finished_courses: report_dir = os.path.join(current_app.instance_path, course_identifier) if os.path.exists(report_dir): continue matched_responses = questionnaire_db.get_matched_responses(course_id) similar_courses = course_db.get_similar_course_ids(course_id) similar_responses = copy.deepcopy(matched_responses) for (similar_id, ) in similar_courses: matched = questionnaire_db.get_matched_responses(similar_id) similar_responses.append(matched) os.mkdir(report_dir) os.chdir(report_dir) if matched_responses.size() == 0: SendEmail( '*****@*****.**', 'Kurs {} hat keine gematched Antworten'.format( course_identifier), 'Der Kurs {} mit id {} hat keine gematched Antworten. ' 'Der Report konnte nicht erzeugt werden.'.format( course_identifier, course_id)) log.warning( 'Course {} with id {} has no matched responses'.format( course_identifier, course_id)) continue generate_plots(matched_responses, similar_responses) count_pre, count_post = questionnaire_db.get_course_numbers(course_id) name, count_students = course_db.get_course_report_info(course_id) with current_app.open_resource('util/report_template.txt', 'r') as f: content = f.read().format( course_name=sanitize_name(name), course_pre=count_pre, course_post=count_post, course_matched=matched_responses.size(), course_reported=count_students, course_ratio=matched_responses.size() / count_students, similar_matched=similar_responses.size(), ) with open(os.path.join(report_dir, 'report.tex'), 'w') as f: f.write(content) latexmk_command = ['latexmk', '-pdf', '-quiet', '-f', 'report.tex'] latexmk_clean = ['latexmk', '-c', 'report.tex'] failure = subprocess.call(latexmk_command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) if failure: SendEmail( '*****@*****.**', 'Fehler bei Report für Kurs {}'.format(course_identifier), 'Der Report für den Kurs {} mit id {} konnte nicht ' 'erzeugt werden.'.format(course_identifier, course_id)) log.error('Error while processing of the tex-file for course ' '{} with id {}'.format(course_identifier, course_id)) continue subprocess.call(latexmk_clean, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) click.echo('Generated Report for {} with {} matched responses'.format( course_identifier, matched_responses.size())) click.echo('Finished Reports')
def test_add_course(app, MonkeyEmail): with app.app_context(): course_db = CourseDB() courses = course_db.get_courses(user_id=2) assert len(courses) == 2 course_name = 'New Course' fields = { 'name': course_name, 'program_id': '1', 'course_type_id': '1', 'focus_id': '1', 'traditional_id': '1', 'equipment_id': '1', 'experience_id': '1', 'university_type_id': '1', 'university_id': '1', 'number_students': '20', 'students_per_instructor': '4', 'lab_per_lecture': '2', 'hours_per_lab': '2.5', 'number_labs': '10', 'number_experiments': '5', 'number_projects': '1', 'week_guided': '1', 'start_date_pre': '1899849600', 'start_date_post': '1934064000', 'frequency_phys_principle': '3', 'frequency_known_principle': '2', 'frequency_unknown_principle': '0', 'students_questions': '0', 'students_plan': '0', 'students_design': '0', 'students_apparatus': '0', 'students_analysis': '0', 'students_troubleshoot': '0', 'students_groups': '0', 'modeling_mathematics': '0', 'modeling_model': '0', 'modeling_tools': '0', 'modeling_measurement': '0', 'modeling_predictions': '0', 'modeling_uncertainty': '0', 'modeling_calibrate': '0', 'analysis_uncertainty': '0', 'analysis_calculate': '0', 'analysis_computer': '0', 'analysis_control': '0', 'communication_oral': '0', 'communication_written': '0', 'communication_lab': '0', 'communication_journal': '0', 'communication_test': '0' } course_db.add_course(user_id=2, fields=fields) courses = course_db.get_courses(user_id=2) assert len(courses) == 3 assert courses[-1]['name'] == course_name assert MonkeyEmail.called assert MonkeyEmail.recipient == '*****@*****.**' assert MonkeyEmail.subject == 'Kurs Registrierung GEclass' assert course_name in MonkeyEmail.content
def test_select_all_courses(app): with app.app_context(): course_db = CourseDB() courses = course_db.get_courses(user_id=2) assert courses[0]['name'] == 'Bachelor Physiker' assert courses[1]['name'] == 'Master Physiker Projekt'
def test_get_surveys_today(app, MonkeyEmail): with app.app_context(): timestamp_today = str(int(time.mktime(date.today().timetuple()))) fields_pre = { 'name': 'test_pre', 'program_id': '1', 'course_type_id': '1', 'focus_id': '1', 'traditional_id': '1', 'equipment_id': '1', 'experience_id': '1', 'university_type_id': '1', 'university_id': '1', 'number_students': '20', 'students_per_instructor': '4', 'lab_per_lecture': '2', 'hours_per_lab': '2.5', 'number_labs': '10', 'number_experiments': '5', 'number_projects': '1', 'week_guided': '1', 'start_date_pre': timestamp_today, 'start_date_post': '1934064000', 'frequency_phys_principle': '3', 'frequency_known_principle': '2', 'frequency_unknown_principle': '0', 'students_questions': '0', 'students_plan': '0', 'students_design': '0', 'students_apparatus': '0', 'students_analysis': '0', 'students_troubleshoot': '0', 'students_groups': '0', 'modeling_mathematics': '0', 'modeling_model': '0', 'modeling_tools': '0', 'modeling_measurement': '0', 'modeling_predictions': '0', 'modeling_uncertainty': '0', 'modeling_calibrate': '0', 'analysis_uncertainty': '0', 'analysis_calculate': '0', 'analysis_computer': '0', 'analysis_control': '0', 'communication_oral': '0', 'communication_written': '0', 'communication_lab': '0', 'communication_journal': '0', 'communication_test': '0' } fields_post_1 = fields_pre.copy() fields_post_1['name'] = 'test_post_1' fields_post_1['start_date_pre'] = 1 fields_post_1['start_date_post'] = timestamp_today fields_post_2 = fields_post_1.copy() fields_post_2['name'] = 'test_post_2' course_db = CourseDB() course_db.generate_identifier = lambda: '12345' course_db.add_course(user_id=1, fields=fields_pre) course_db.add_course(user_id=1, fields=fields_post_1) course_db.add_course(user_id=2, fields=fields_post_2) pre, post = course_db.get_surveys_today() pre_list = [] for row in pre: pre_list.append(list(row)) post_list = [] for row in post: post_list.append(list(row)) assert [1, 'test_pre', '12345'] in pre_list assert [1, 'test_post_1', '12345'] in post_list assert [2, 'test_post_2', '12345'] in post_list