Пример #1
0
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]
Пример #2
0
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()
Пример #3
0
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]
Пример #4
0
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)
Пример #5
0
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
Пример #6
0
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]
Пример #7
0
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")
Пример #8
0
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)
Пример #9
0
 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')
Пример #10
0
 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)
Пример #11
0
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)
Пример #12
0
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
Пример #13
0
 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()
     ]
Пример #14
0
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)
Пример #15
0
 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
Пример #16
0
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
Пример #17
0
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')
Пример #18
0
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
Пример #19
0
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'
Пример #20
0
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