Example #1
0
def gen_materials():
    course_offerings = db.select_columns('course_offerings', ['id', 'course'])

    # currently adds a presentation and report for each thesis
    for course in course_offerings:

        # filtering out any courses not a thesis
        name = db.select_columns(
            'courses', ['name'], ['id'], [course[1]]
        )
        if len(name) == 0:
            continue
        name = name[0][0].lower()
        if 'thesis' not in name:
            continue
        # entering 2 materials for each thesis
        queries = []
        queries.append((
            'materials',
            ['Course Outline', course[0]],
            ['name', 'course_offering']
        ))
        queries.append((
            'materials',
            [f'Sample Report {name.title()}', course[0]],
            ['name', 'course_offering']
        ))
        db.insert_multiple(queries)
Example #2
0
def gen_sessions():
    ret = []

    for year in range(2018, 2019):
        ret.append([year, 1,
                    datetime.datetime(year, 1, 1, 0, 0, 0).timestamp(),
                    datetime.datetime(year, 6, 30, 23, 59, 59).timestamp()
                    ])
        ret.append([year, 2,
                    datetime.datetime(year, 7, 1, 0, 0, 0).timestamp(),
                    datetime.datetime(year, 11, 30, 23, 59, 59).timestamp()
                    ])

    for year in range(2019, 2021):
        ret.append([year, 1,
                    datetime.datetime(year, 2, 18, 0, 0, 0).timestamp(),
                    datetime.datetime(year, 5, 18, 23, 59, 59).timestamp()
                    ])
        ret.append([year, 2,
                    datetime.datetime(year, 6, 3, 0, 0, 0).timestamp(),
                    datetime.datetime(year, 8, 31, 23, 59, 59).timestamp()
                    ])
        ret.append([year, 3,
                    datetime.datetime(year, 9, 16, 0, 0, 0).timestamp(),
                    datetime.datetime(year, 12, 14, 23, 59, 59).timestamp()
                    ])

    query = []
    for sess in ret:
        query.append(('sessions',
                      sess,
                      ['year', 'term', 'start_date', 'end_date']))
    db.insert_multiple(query)
    return ret
Example #3
0
def create_course():
    db.connect()
    curr_year = datetime.now().year
    num_terms = queries.get_terms_per_year(curr_year)
    course = {'offerings': [False for _ in range(num_terms)]}
    try:
        res = get_fields(request.form,
                         ['title', 'code', 'description', 'year'], ['year'])
        for i in range(num_terms):
            if str(i + 1) in request.form:
                course['offerings'][i] = True
    except ValueError as e:
        db.close()
        return e.args[0]

    course['title'] = res[0]
    course['code'] = res[1]
    course['description'] = res[2]

    if not re.match(config.COURSE_CODE_FORMAT, course['code']):
        db.close()
        return error("Invalid course code", 'code')

    course['year'] = int(res[3])
    if curr_year > course['year']:
        db.close()
        return error(f"Year must be at least {curr_year}")

    if True not in course['offerings']:
        db.close()
        return error('You must select at least one term offering')

    sessions = queries.get_course_sessions(course['code'])
    sessions = filter(lambda s: s[0] == course['year'], sessions)
    for year, term in sessions:
        if course['offerings'][term - 1]:
            db.close()
            return error(f"{course['code']} already offered in {year} T{term}")

    db.insert_single('courses',
                     [course['code'], course['title'], course['description']],
                     ['code', 'name', 'description'])
    res = db.select_columns('courses', ['id'], ['code'], [course['code']])
    course['id'] = res[0][0]

    query = []
    for i in range(len(course['offerings'])):
        if not course['offerings'][i]:
            continue
        res = db.select_columns('sessions', ['id'], ['year', 'term'],
                                [course['year'], i + 1])
        session_id = res[0][0]
        query.append(('course_offerings', [course['id'],
                                           session_id], ['course', 'session']))
    db.insert_multiple(query)
    db.close()
    return jsonify({'status': 'ok'})
Example #4
0
def gen_submissions():
    acc_types = get_all_account_types()
    request_types = get_all_request_types()
    students = db.select_columns(
        'users', ['id', 'email'], ['account_type'], [acc_types['student']]
    )

    upload_dir = Path(config.STATIC_PATH) / Path(config.FILE_UPLOAD_DIR)
    upload_dir.mkdir(exist_ok=True)
    sample_submission = Path('db/sample_submission.pdf')
    for student in students:
        tasks = db_queries.get_user_tasks(student[0])
        now = datetime.datetime.now().timestamp()
        queries = []
        zid = student[1].split('@')[0]
        for task in tasks:
            # if task is in the future, don't create a submission
            if task[4] > now:
                deadline_time = datetime.datetime.fromtimestamp(task[4])
                now_time = datetime.datetime.fromtimestamp(now)
                dif = deadline_time - now_time
                if dif.days > 14:
                    continue
                number = random.randrange(10)
                if number > 2:
                    continue
            stem = Path(str(uuid.uuid4()) + 'sample_submission.pdf')
            path = upload_dir / stem
            copyfile(sample_submission, path)
            sub_name = '{zid}-{task_name}'.format(zid=zid,
                                                  task_name=task[1])
            if 'approval' in task[3]:
                queries.append((
                    'submissions',
                    [student[0], task[0], sub_name,
                     None, 'Here is a lengthy essay', now,
                     request_types['approved']]
                ))
            else:
                queries.append((
                    'submissions',
                    [student[0], task[0], sub_name,
                     str(stem), 'Here is a lengthy description', now,
                     request_types['pending mark']]
                ))
        db.insert_multiple(queries)
Example #5
0
def gen_topics():
    with open('db/topics.json') as f:
        topics = json.load(f)
        query = []

        supervisor_type = db.select_columns('account_types',
                                            ['id'],
                                            ['name'],
                                            ['supervisor'])[0][0]

        supervisors = db.select_columns('users',
                                        ['id'],
                                        ['account_type'],
                                        [supervisor_type])

        # remove any topics with empty areas or descriptions
        for i in range(len(topics)-1, -1, -1):
            if len(topics[i]['areas']) == 0:
                topics.pop(i)
            elif len(topics[i]['description']) == 0:
                topics.pop(i)

        topics_per_sup = math.floor(len(topics)/len(supervisors))
        topics_per_sup = min(topics_per_sup, 10)

        course_ids = db.select_columns('courses', ['id'], ['prereq'], [1])
        course_ids = list(map(lambda x: x[0], course_ids))
        base_topic_id = 1
        for sup in supervisors:
            for i in range(0, topics_per_sup):
                t = topics[i+base_topic_id]
                query.append((
                    'topics', [i+base_topic_id, t['name'], sup[0],
                               t['description'], random.randrange(0, 2)],
                    ['id', 'name', 'supervisor', 'description', 'visible']
                ))
                gen_topic_areas(i+base_topic_id, t['areas'])
                gen_topic_prereqs(i+base_topic_id, course_ids)
            base_topic_id += topics_per_sup
        db.insert_multiple(query)
Example #6
0
def gen_task_critera():
    tasks = db.select_columns('tasks', ['id', 'name', 'marking_method'])

    for task in tasks:
        queries = []

        if(task[2] == 1):
            queries.append((
                'task_criteria',
                [task[0], 'Approval', 100],
                ['task', 'name', 'max_mark']
            ))
        else:
            queries.append((
                'task_criteria',
                [task[0], 'Technical Quality and Completeness', 80],
                ['task', 'name', 'max_mark']
            ))
            queries.append((
                'task_criteria',
                [task[0], 'Structure and Presentation', 20],
                ['task', 'name', 'max_mark']
            ))
        db.insert_multiple(queries)
def create():
    course_id = request.args.get('course_offering_id', None, type=int)
    if request.method == 'GET':
        if course_id is None:
            abort(400)
        db.connect()
        res = db.select_columns('course_offerings', ['id'], ['id'],
                                [course_id])
        if not len(res):
            db.close()
            abort(404)
        file_types = db.select_columns('file_types', ['name'])
        file_types = list(map(lambda x: x[0], file_types))
        allowed_file_types = ','.join(file_types)

        heading = 'Create Task'
        default_fields = {
            'task-name': '',
            'deadline': '',
            'task-description': '',
            'submission-type': 'text',
            'word-limit': '',
            'maximum-file-size': '',
            'accepted-file-type': '',
            'marking-method': 'accept',
            'criteria': [],
            'task_attachments': []
        }

        # if updating old task then load old task data
        old_task_id = request.args.get('update', None, type=int)
        if old_task_id is not None:
            res = queries.get_past_task_data(old_task_id)
            if res is not None:
                res = res[0]
                heading = 'Edit Task'

                # basic task details
                default_fields['task-name'] = res[0]
                time_format = '%d/%m/%Y %H:%M'
                due_date = datetime.fromtimestamp(res[1])
                default_fields['deadline'] = due_date.strftime(time_format)
                default_fields['task-description'] = res[2]

                attachments = db.select_columns('task_attachments', ['path'],
                                                ['task'], [old_task_id])
                for r in attachments:
                    file = [FileUpload(filename=r[0])]
                    default_fields['task_attachments'] = file

                # submission method specific
                if res[3] == 'text submission':
                    default_fields['word-limit'] = res[4]
                else:
                    default_fields['submission-type'] = 'file'
                    default_fields['maximum-file-size'] = int(res[5])
                    default_fields['accepted-file-type'] = res[6]

                # marking method specifics
                if res[7] == 'requires mark':
                    default_fields['marking-method'] = 'criteria'
                    crit = db.select_columns('task_criteria',
                                             ['name, max_mark'], ['task'],
                                             [old_task_id])
                    if crit is not None:
                        default_fields['criteria'] = crit

        db.close()
        if default_fields['maximum-file-size'] == '':
            default_fields['maximum-file-size'] = 5
        if default_fields['accepted-file-type'] == '':
            default_fields['accepted-file-type'] = '.pdf'
        return render_template('create_task.html',
                               heading=heading,
                               title=heading,
                               file_types=file_types,
                               course_id=course_id,
                               max_file_size=config.MAX_FILE_SIZE,
                               max_word_limit=config.MAX_WORD_LIMIT,
                               accepted_file_types=allowed_file_types,
                               old_task_id=old_task_id,
                               default_fields=default_fields)

    try:
        fields = [
            'task-name', 'deadline', 'task-description', 'submission-type',
            'word-limit', 'maximum-file-size', 'accepted-file-type',
            'marking-method', 'num-criteria', 'course-id', 'file-name',
            'old_task_id', 'delete_old_attachment'
        ]
        task_name, deadline, task_description, submission_type, \
            word_limit, max_file_size, accepted_ftype, marking_method, \
            num_criteria, course_id, file_name, old_task_id, \
            delete_old_attachment = \
            get_fields(request.form, fields,
                       optional=['word-limit', 'file-name'],
                       ints=['maximum-file-size', 'num-criteria',
                             'word-limit', 'course-id',
                             'delete_old_attachment'])
    except ValueError as e:
        return e.args[0]

    try:
        old_task_id = int(old_task_id)
    except ValueError as e:
        old_task_id = None

    try:
        deadline = datetime.strptime(deadline, '%d/%m/%Y %H:%M').timestamp()
    except ValueError:
        return error('Invalid date format for deadline!')

    if submission_type == 'file':
        max_size = config.MAX_FILE_SIZE
        if not (1 <= max_file_size <= max_size):
            return error(
                f'Maximum file size must be between 1 and {max_size}!')
    elif submission_type == 'text':
        try:
            word_limit = get_fields(request.form, ['word-limit'],
                                    ints=['word-limit'])[0]
        except ValueError as e:
            return e.args[0]
        max_word_limit = config.MAX_WORD_LIMIT
        if not (1 <= word_limit <= max_word_limit):
            return error(f'Word limit must be between 1 and {max_word_limit}!')
    else:
        return error('Unknown submission type!')

    if marking_method == 'criteria':
        if num_criteria < 1:
            return error('At least one marking criterion is required!')
        else:
            criteria = [f'criteria-{i}' for i in range(1, num_criteria + 1)]
            marks = [f'maximum-mark-{i}' for i in range(1, num_criteria + 1)]
            try:
                criteria = get_fields(request.form, criteria)
                marks = get_fields(request.form, marks, ints=marks)
            except ValueError as e:
                return e.args[0]

        if sum([mark for mark in marks]) != 100:
            return error('Marks must add to 100!')
    elif marking_method != 'accept':
        return error('Unknown marking method!')

    db.connect()
    res = db.select_columns('course_offerings', ['id'], ['id'], [course_id])
    if not len(res):
        db.close()
        return error('Cannot create task for unknown course!')
    res = db.select_columns('tasks', ['id', 'name'],
                            ['name', 'course_offering'],
                            [task_name, course_id])
    if len(res) and res[0][0] != old_task_id:
        db.close()
        return error('A task with that name already exists in this course!')

    # retrieve some foreign keys for insertion
    res = db.select_columns('file_types', ['id'], ['name'], [accepted_ftype])
    if not len(res):
        db.close()
        return error('Invalid or unsupported file type!')
    file_type_id = res[0][0]

    # upload file if present
    sent_file = None
    if len(file_name):
        try:
            sent_file = FileUpload(req=request)
        except KeyError:
            db.close()
            return error('Could not find a file to upload')

        res = db.select_columns('file_types', ['name'])
        file_types = list(map(lambda x: x[0], res))
        if sent_file.get_extention() not in file_types:
            db.close()
            accept_files = ', '.join(file_types)
            return error(f'Accepted file types are: {accept_files}')
        if sent_file.get_size() > config.MAX_FILE_SIZE:
            sent_file.remove_file()
            db.close()
            return error(
                f'File exceeds the maximum size of {config.MAX_FILE_SIZE} MB')
        sent_file.commit()

    if (len(file_name) and old_task_id is not None) or delete_old_attachment:
        old = db.select_columns('task_attachments', ['path'], ['task'],
                                [old_task_id])
        if old:
            db.delete_rows('task_attachments', ['task'], [old_task_id])
            try:
                prev_submission = FileUpload(filename=old[0][0])
                prev_submission.remove_file()
            except LookupError:
                # If the file doesn't exists don't worry as we are deleting
                # the attachment anyway
                pass

    res = db.select_columns('submission_methods', ['id'], ['name'],
                            ['{} submission'.format(submission_type)])
    submission_method_id = res[0][0]
    marking_method = 'approval' if marking_method == 'accept' else 'mark'
    res = db.select_columns('marking_methods', ['id'], ['name'],
                            ['requires {}'.format(marking_method)])
    mark_method_id = res[0][0]

    # commit task
    if old_task_id is not None:
        # update an existing task
        db.update_rows('tasks', [
            task_name, course_id, deadline, task_description, max_file_size,
            submission_method_id, mark_method_id, word_limit
        ], [
            'name', 'course_offering', 'deadline', 'description', 'size_limit',
            'submission_method', 'marking_method', 'word_limit'
        ], ['id'], [old_task_id])
    else:
        # add a new task`
        db.insert_single('tasks', [
            task_name, course_id, deadline, task_description, max_file_size, 0,
            submission_method_id, mark_method_id, word_limit
        ], [
            'name', 'course_offering', 'deadline', 'description', 'size_limit',
            'visible', 'submission_method', 'marking_method', 'word_limit'
        ])

    res = db.select_columns('tasks', ['id'], ['name', 'course_offering'],
                            [task_name, course_id])
    task_id = res[0][0]

    if sent_file:
        db.insert_single('task_attachments',
                         [task_id, sent_file.get_name()], ['task', 'path'])

    # delete old entries in other tables
    if old_task_id is not None:
        db.delete_rows('submission_types', ['task'], [old_task_id])

        res = db.select_columns('task_criteria', ['id'], ['task'],
                                [old_task_id])
        for r in res:
            db.delete_rows('marks', ['criteria'], [r[0]])
        db.delete_rows('task_criteria', ['task'], [old_task_id])

    # commit accepted file type
    db.insert_single('submission_types', [file_type_id, task_id],
                     ['file_type', 'task'])

    # commit marking criteria
    marking_criteria = []
    if marking_method == 'approval':
        marking_criteria.append(
            ('task_criteria', [task_id, 'Approval',
                               100], ['task', 'name', 'max_mark']))
    else:
        for i in range(len(criteria)):
            marking_criteria.append(
                ('task_criteria', [task_id, criteria[i],
                                   marks[i]], ['task', 'name', 'max_mark']))
    db.insert_multiple(marking_criteria)

    db.close()
    return jsonify({'status': 'ok'})
Example #8
0
def gen_marks():
    acc_types = get_all_account_types()
    students = db.select_columns(
        'users', ['id'], ['account_type'], [acc_types['student']]
    )
    request_types = get_all_request_types()

    for student in students:
        markers = db_queries.get_user_ass_sup(student[0])
        if len(markers) == 0:
            continue
        markers = markers[0]
        if None in markers:
            continue
        tasks = db_queries.get_user_tasks(student[0])
        for task in tasks:
            if 'approval' in task[3]:
                continue
            now = datetime.datetime.now().timestamp()
            deadline = task[4]
            if deadline > now:
                continue
            criteria_ids = db.select_columns(
                'task_criteria', ['id', 'max_mark'], ['task'], [task[0]]
            )
            queries = []

            # create the marks
            for criteria in criteria_ids:
                mark = random.randrange(criteria[1])
                if(mark/criteria[1] < .5):
                    feedback = "Not of a high enough quality, there's"\
                               + " a lot of room for improvement."
                elif(mark/criteria[1] < .7):
                    feedback = "Some parts are of poor quality, and there's"\
                               + " room for some improvement, but overall a"\
                               + " decent attempt."
                else:
                    feedback = "Amazing quality, a few parts could use some"\
                               + " polishing but great job!"
                queries.append((
                    'marks',
                    [criteria[0], mark, student[0],
                     markers[0], feedback, None]
                ))

                mark = random.randrange(criteria[1])
                if(mark/criteria[1] < .5):
                    feedback = "Not of a high enough quality, there's"\
                               + " a lot of room for improvement."
                elif(mark/criteria[1] < .7):
                    feedback = "Some parts are of poor quality, and there's"\
                               + " room for some improvement, but overall a"\
                               + " decent attempt."
                else:
                    feedback = "Amazing quality, a few parts could use some"\
                               + " polishing but great job!"
                queries.append((
                    'marks',
                    [criteria[0], mark, student[0],
                     markers[1], feedback, None]
                ))

            db.insert_multiple(queries)
            db.update_rows(
                'submissions',
                [request_types['marked']], ['status'],
                ['student', 'task'], [student[0], task[0]]
            )
Example #9
0
def gen_users():
    with open('db/names.json') as f:
        names = json.load(f)
        types = get_all_account_types()
        password = bcrypt.hashpw('password1'.encode('utf-8'), bcrypt.gensalt())
        query = []
        timestamp = 946645140

        # student users
        students = []
        for i in range(100):
            zid = 'z{}'.format(str(1000001 + i))
            students.append(zid)
            name = names[i]['name']
            query.append(('users',
                          [name, f'{zid}@unsw.edu.au',
                           password, types['student'], '', '', timestamp],
                          ['name', 'email', 'password',
                           'account_type', 'confirm_code',
                           'reset_code', 'date_created']))

        # public users
        public = []
        for i in range(20):
            zid = 'z{}'.format(str(4000001 + i))
            public.append(zid)
            name = names[100+i]['name']
            query.append(('users',
                          [name, f'{zid}@unsw.edu.au',
                           password, types['public'], '', '', timestamp],
                          ['name', 'email', 'password',
                           'account_type', 'confirm_code',
                           'reset_code', 'date_created']))

        # supervisor/assessor users
        supervisors = []
        for i in range(10):
            zid = 'z{}'.format(str(8000001 + i))
            supervisors.append(zid)
            name = names[200+i]['name']
            query.append(('users',
                          [name, f'{zid}@unsw.edu.au',
                           password, types['supervisor'], '', '', timestamp],
                          ['name', 'email', 'password',
                           'account_type', 'confirm_code',
                           'reset_code', 'date_created']))

        # course admin users
        course_admin = []
        for i in range(5):
            zid = 'z{}'.format(str(9000001 + i))
            course_admin.append(zid)
            name = names[300+i]['name']
            query.append(('users',
                          [name, f'{zid}@unsw.edu.au',
                           password, types['course_admin'], '', '', timestamp],
                          ['name', 'email', 'password',
                           'account_type', 'confirm_code',
                           'reset_code', 'date_created']))

        db.insert_multiple(query)