Exemplo n.º 1
0
def fork_group(lti=lti):
    ''' Adds a group to a course'''
    # Get arguments
    assignment_group_id = int(request.values.get('assignment_group_id'))
    assignment_group = AssignmentGroup.by_id(assignment_group_id)
    is_embedded = ('embed' == request.values.get('menu', "select"))
    # Verify exists
    check_resource_exists(assignment_group, "Assignment Group",
                          assignment_group_id)
    # Verify permissions
    require_course_instructor(g.user, assignment_group.course_id)
    # Perform action
    new_assignment_group = AssignmentGroup.new(
        owner_id=g.user.id,
        course_id=assignment_group.course_id,
        name=assignment_group.name)
    new_assignment_group.forked_id = assignment_group_id
    new_assignment_group.forked_version = assignment_group.version
    # Result
    select_url = get_select_menu_link(new_assignment_group.id,
                                      new_assignment_group.name, is_embedded,
                                      True)
    return jsonify(success=True,
                   id=new_assignment_group.id,
                   name=new_assignment_group.name,
                   select=select_url)
Exemplo n.º 2
0
def remove_group(lti=lti):
    ''' Removes a group from a course'''
    assignment_group_id = int(request.values.get('assignment_group_id'))
    assignment_group = AssignmentGroup.by_id(assignment_group_id)
    # Verify exists
    check_resource_exists(assignment_group, "Assignment Group",
                          assignment_group_id)
    # Verify permissions
    require_course_instructor(g.user, assignment_group.course_id)
    # Perform action
    AssignmentGroup.remove(assignment_group.id)
    # Result
    return jsonify(success=True)
Exemplo n.º 3
0
def import_bundle(bundle, owner_id, course_id=None, update=True):
    if 'course' in bundle:
        course = Course.decode_json(bundle['course'], owner_id=owner_id)
        db.session.add(course)
        db.session.commit()
    else:
        course = Course.by_id(course_id)
    assignment_remap = {}
    assignments = bundle.get('assignments', [])
    for assignment_data in natsorted(assignments, key=lambda a: a['name']):
        assignment = Assignment.decode_json(assignment_data,
                                            course_id=course.id,
                                            owner_id=owner_id)
        assignment_remap[assignment_data['url']] = assignment.id
    group_remap = {}
    groups = bundle.get('groups', [])
    for group_data in natsorted(groups, key=lambda g: g['name']):
        group = AssignmentGroup.decode_json(group_data,
                                            course_id=course.id,
                                            owner_id=owner_id)
        group_remap[group_data['url']] = group.id
    memberships = bundle.get('memberships', [])
    for member_data in sorted(memberships, key=sorter):
        assignment_id = assignment_remap[member_data['assignment_url']]
        group_id = group_remap[member_data['assignment_group_url']]
        member = AssignmentGroupMembership.decode_json(
            member_data,
            assignment_id=assignment_id,
            assignment_group_id=group_id)
    return True
Exemplo n.º 4
0
def generate_maintable(zip_file, course_id, assignment_group_ids):
    code_states, latest_code_states, scores = {}, {}, {}
    query = Log.query.filter_by(course_id=course_id)
    if assignment_group_ids is not None:
        assignment_ids = [
            assignment.id for group_id in assignment_group_ids for assignment
            in AssignmentGroup.by_id(group_id).get_assignments()
        ]
        query = query.filter(Log.assignment_id.in_(assignment_ids))
    estimated_size = query.count()
    logs = query.order_by(Log.date_created.asc()).yield_per(100)
    tempdir = tempfile.mkdtemp()
    temppath = os.path.join(tempdir, 'MainTable.csv')
    #with io.StringIO() as maintable_file:
    with open(temppath, 'w') as maintable_file:
        writer = csv.writer(maintable_file, **PROGSNAP_CSV_WRITER_OPTIONS)
        writer.writerow(HEADERS)
        order_id = 0
        for log in tqdm(logs, total=estimated_size):
            writer.writerow(
                to_progsnap_event(log, order_id, code_states,
                                  latest_code_states, scores))
            order_id += 1
        #zip_file.writestr("MainTable.csv", maintable_file.getvalue())
    zip_file.write(temppath, "MainTable.csv")
    shutil.rmtree(tempdir)
    return "MainTable.csv", code_states
Exemplo n.º 5
0
def get_groups_submissions(group_id, user_id, course_id):
    group = AssignmentGroup.by_id(group_id)
    check_resource_exists(group, "AssignmentGroup", group_id)
    assignments = group.get_assignments()
    submissions = [
        assignment.load(user_id, course_id=course_id)
        for assignment in assignments
    ]
    return group, assignments, submissions
 def get_existing(cls, data):
     group_url = data['assignment_group_url']
     assignment_url = data['assignment_url']
     assignment = Assignment.by_url(assignment_url)
     group = AssignmentGroup.by_url(group_url)
     if not assignment or not group:
         return None
     return (AssignmentGroupMembership.query.filter_by(
         assignment_group_id=group.id, assignment_id=assignment.id).first())
Exemplo n.º 7
0
    def run(self, **kwargs):
        from models.user import User
        from models.course import Course
        from models.role import Role
        from models.assignment_group import AssignmentGroup
        from models.assignment_group_membership import AssignmentGroupMembership
        from models.assignment import Assignment

        default_course = Course.query.first()

        print("Adding Teacher")
        teacher = User(first_name="Klaus",
                       last_name="Bart",
                       password=hash_password("password"),
                       confirmed_at=datetime.datetime.now(),
                       active=True,
                       email="*****@*****.**")
        db.session.add(teacher)
        db.session.flush()
        db.session.add(
            Role(name='instructor',
                 course_id=default_course.id,
                 user_id=teacher.id))

        print("Adding Student")
        student = User(first_name="Ada",
                       last_name="Bart",
                       password=hash_password("password"),
                       confirmed_at=datetime.datetime.now(),
                       active=True,
                       email="*****@*****.**")
        db.session.add(student)
        db.session.flush()
        db.session.add(
            Role(name='student',
                 course_id=default_course.id,
                 user_id=student.id))

        print("Adding basic assignments")
        basic_group = AssignmentGroup(name="First Group",
                                      course_id=default_course.id,
                                      owner_id=teacher.id)
        db.session.add(basic_group)
        db.session.flush()
        for i in range(5):
            assignment = Assignment(name="Problem {}".format(i),
                                    instructions="Complete this problem",
                                    owner_id=teacher.id,
                                    course_id=default_course.id)
            db.session.add(assignment)
            db.session.flush()
            db.session.add(
                AssignmentGroupMembership(assignment_group_id=basic_group.id,
                                          assignment_id=assignment.id))

        db.session.commit()
        print("Complete")
Exemplo n.º 8
0
def move_membership(lti=None):
    # Get arguments
    assignment_id = int(request.values.get('assignment_id'))
    old_group_id = int(request.values.get('old_group_id'))
    new_group_id = int(request.values.get('new_group_id'))
    assignment = Assignment.by_id(assignment_id)
    # Verify exists
    check_resource_exists(assignment, "Assignment", assignment_id)
    # Verify permissions
    require_course_instructor(g.user, assignment.course_id)

    # Verify permissions
    if new_group_id != -1:
        new_assignment_group = AssignmentGroup.by_id(new_group_id)
        require_course_instructor(g.user, new_assignment_group.course_id)
    if old_group_id != -1:
        old_assignment_group = AssignmentGroup.by_id(old_group_id)
        require_course_instructor(g.user, old_assignment_group.course_id)
    # Perform action
    AssignmentGroupMembership.move_assignment(assignment_id, new_group_id)
    # Result
    return jsonify(success=True)
Exemplo n.º 9
0
def edit_settings(lti=lti):
    # Get arguments
    assignment_group_id = int(request.values.get('assignment_group_id'))
    assignment_group = AssignmentGroup.by_id(assignment_group_id)
    ip_ranges = request.values.get('ip_ranges')
    passcode = request.values.get('passcode')
    # Verify exists
    check_resource_exists(assignment_group, "Assignment Group",
                          assignment_group_id)
    # Verify permissions
    require_course_instructor(g.user, assignment_group.course_id)
    # Perform action
    if request.method == 'POST':
        if ip_ranges is not None:
            for assignment in assignment_group.get_assignments():
                assignment.edit(dict(ip_ranges=ip_ranges))
                assignment.update_setting("passcode", passcode)
        return redirect(request.url)
    # Result
    else:
        assignments = assignment_group.get_assignments()
        passcode = assignments[0].get_setting("passcode", "")
        existing_ip_ranges = [
            assignment.ip_ranges for assignment in assignments
        ]
        merged_duplicates = set(existing_ip_ranges)
        warning = ""
        if len(merged_duplicates) == 1:
            ip_ranges = merged_duplicates.pop()
        elif merged_duplicates:
            ip_ranges = existing_ip_ranges[0]
            warning = "This assignment has multiple IP ranges: <pre>{}</pre>".format(
                "\n".join(existing_ip_ranges))
        return '''
            <!doctype html>
            <title>Edit Assignment Group Settings</title>
            <h1>Edit Assignment Group Settings</h1>
            <p>Assignment: {group_name}</p>
            <p>{warning}</p>
            <form action="" method=post>
              <p>IP Ranges: <input type=text name=ip_ranges value="{ip_ranges}"><br>
                 Passcode: <input type=text name=passcode value="{passcode}"><br>
                 <input type=submit value=Change>
            </form>
            '''.format(group_name=assignment_group.name,
                       ip_ranges=ip_ranges if ip_ranges else "",
                       passcode=passcode if passcode else "",
                       warning=warning)
 def encode_json(self):
     group = AssignmentGroup.by_id(self.assignment_group_id)
     group_url = group.url if group else None
     assignment = Assignment.by_id(self.assignment_id)
     assignment_url = assignment.url if assignment else None
     return {
         '_schema_version': 1,
         'assignment_group_id': self.assignment_group_id,
         'assignment_group_url': group_url,
         'assignment_id': self.assignment_id,
         'assignment_url': assignment_url,
         'position': self.position,
         'id': self.id,
         'date_modified': datetime_to_string(self.date_modified),
         'date_created': datetime_to_string(self.date_created)
     }
Exemplo n.º 11
0
def edit_group(lti=lti):
    # Get arguments
    assignment_group_id = int(request.values.get('assignment_group_id'))
    assignment_group = AssignmentGroup.by_id(assignment_group_id)
    new_name = request.values.get('new_name')
    new_url = request.values.get('new_url')
    # Verify exists
    check_resource_exists(assignment_group, "Assignment Group",
                          assignment_group_id)
    # Verify permissions
    require_course_instructor(g.user, assignment_group.course_id)
    # Perform action
    changed = assignment_group.edit(dict(name=new_name, url=new_url))
    # Result
    return jsonify(success=True,
                   name=assignment_group.name,
                   url=assignment_group.url)
Exemplo n.º 12
0
def export():
    user = load_api_user()
    assignment_url = request.json.get("assignment_url")
    assignment_id = request.json.get("assignment_id")
    if assignment_id or assignment_url:
        if assignment_url:
            assignment = Assignment.by_url(assignment_url)
        else:
            assignment = Assignment.by_id(assignment_id)
        check_resource_exists(assignment, "Assignment", assignment_id
                              or assignment_url)
        if not user.is_instructor(assignment.course_id):
            return abort(400, "Not an instructor in this assignments' course.")
        return json.dumps(export_bundle(assignments=[assignment]))
    group_id = request.json.get("assignment_group_id")
    if group_id:
        assignment_group = AssignmentGroup.by_id(group_id)
        assignments = assignment_group.get_assignments()
        memberships = assignment_group.get_memberships()
        if not user.is_instructor(assignment_group.course_id):
            return abort(
                400, "Not an instructor in this assignment group's course.")
        for assignment in assignments:
            if not user.is_instructor(assignment.course_id):
                return abort(400,
                             "Not an instructor in this assignments' course.")
        bundle = export_bundle(groups=[assignment_group],
                               assignments=assignments,
                               memberships=memberships)
        return json.dumps(bundle)
    course_id = request.json.get("course_id")
    if course_id:
        if not user.is_instructor(course_id):
            return abort(400, "Not an instructor in this course.")
        course = Course.by_id(course_id)
        groups = course.get_assignment_groups()
        assignment_and_memberships = course.get_assignments()
        assignments = [a for a, m in assignment_and_memberships]
        memberships = [m for a, m in assignment_and_memberships]
        bundle = export_bundle(groups=groups,
                               assignments=assignments,
                               memberships=memberships)
        return json.dumps(bundle)
    abort(400, "No assignment_id or assignment_group_id given")
Exemplo n.º 13
0
def export():
    assignment_group_id = int(request.values.get('assignment_group_id'))
    assignment_group = AssignmentGroup.by_id(assignment_group_id)
    course_id = get_course_id(True)
    user, user_id = get_user()
    # Verify exists
    check_resource_exists(assignment_group, "Assignment Group",
                          assignment_group_id)
    # Perform action
    assignments = assignment_group.get_assignments()
    memberships = assignment_group.get_memberships()
    bundle = export_bundle(groups=[assignment_group],
                           assignments=assignments,
                           memberships=memberships)
    filename = assignment_group.get_filename()
    return Response(json.dumps(bundle, indent=2),
                    mimetype='application/json',
                    headers={
                        'Content-Disposition':
                        'attachment;filename={}'.format(filename)
                    })
Exemplo n.º 14
0
def add_group(lti=lti):
    ''' Adds a group to a course'''
    # Get arguments
    course_id = int(request.values.get('course_id'))
    new_name = request.values.get('name')
    new_url = request.values.get('url')
    is_embedded = ('embed' == request.values.get('menu', "select"))
    # Verify permissions
    require_course_instructor(g.user, course_id)
    # Perform action
    assignment_group = AssignmentGroup.new(owner_id=g.user.id,
                                           course_id=course_id,
                                           name=new_name,
                                           url=new_url)
    # Result
    select_url = get_select_menu_link(assignment_group.id,
                                      assignment_group.name, is_embedded, True)
    return jsonify(success=True,
                   id=assignment_group.id,
                   url=assignment_group.url,
                   name=assignment_group.name,
                   select=select_url)
Exemplo n.º 15
0
    def run(self, owner_id, **kwargs):
        from models.user import User
        from models.course import Course
        from models.role import Role
        from models.assignment import Assignment
        from models.assignment_group import AssignmentGroup
        from models.assignment_group_membership import AssignmentGroupMembership

        owner_id = int(owner_id)
        maze_course = Course.new('Maze Course', owner_id, 'public')

        maze_group = AssignmentGroup.new(owner_id, maze_course.id, "Maze Game")

        for level in range(10):
            maze_level = Assignment.new(owner_id,
                                        maze_course.id,
                                        'maze',
                                        level=str(1 + level))
            db.session.add(maze_level)
            db.session.flush()
            membership = AssignmentGroupMembership.move_assignment(
                maze_level.id, maze_group.id)
            db.session.add(membership)
        db.session.commit()
Exemplo n.º 16
0
def generate_link_assignments(zip_file, course_id, assignment_group_ids):
    if assignment_group_ids is None:
        assignments = Log.get_assignments_for_course(course_id)
        all_groups = set()
        assignment_groups = {}
        for assignment in assignments:
            groups = AssignmentGroup.by_assignment(assignment.id)
            all_groups.update(groups)
            assignment_groups[assignment.id] = groups
    else:
        all_groups = [
            AssignmentGroup.by_id(group_id)
            for group_id in assignment_group_ids
        ]
        assignment_groups = {}
        assignments = set()
        for group in all_groups:
            for assignment in group.get_assignments():
                if assignment.id not in assignment_groups:
                    assignment_groups[assignment.id] = set()
                assignment_groups[assignment.id].add(group)
                assignments.add(assignment)

    with io.StringIO() as assignment_file:
        assignment_writer = csv.writer(assignment_file,
                                       **PROGSNAP_CSV_WRITER_OPTIONS)
        assignment_writer.writerow([
            "AssignmentId", "X-Version", "X-Name", "X-URL", "X-Instructions",
            "X-Reviewed", "X-Hidden", "X-Settings", "X-Code.OnRun",
            "X-Code.OnChange", "X-Code.OnEval", "X-Code.Starting",
            "X-Code.ExtraInstructor", "X-Code.ExtraStarting", "X-Forked.Id",
            "X-Forked.Version", "X-Owner.Id", "X-Course.Id",
            "X-AssignmentGroup.Ids"
        ])
        for assignment in natsorted(assignments, key=lambda a: a.name):
            assignment_writer.writerow([
                assignment.id, assignment.version, assignment.name,
                assignment.url, assignment.instructions, assignment.reviewed,
                assignment.hidden, assignment.settings, assignment.on_run,
                assignment.on_change, assignment.on_eval,
                assignment.starting_code, assignment.extra_instructor_files,
                assignment.extra_starting_files, assignment.forked_id,
                assignment.forked_version, assignment.owner_id,
                assignment.course_id, ", ".join(
                    map(str, (g.id for g in assignment_groups[assignment.id])))
            ])

        zip_file.writestr("LinkTables/Assignment.csv",
                          assignment_file.getvalue())
        yield "LinkTables/Assignment.csv"

    with io.StringIO() as group_file:
        group_writer = csv.writer(group_file, **PROGSNAP_CSV_WRITER_OPTIONS)
        group_writer.writerow([
            "AssignmentGroupId", "X-Version", "X-Name", "X-URL", "X-Forked.Id",
            "X-Forked.Version", "X-Owner.Id", "X-Course.Id"
        ])
        for group in natsorted(all_groups, key=lambda g: g.name):
            group_writer.writerow([
                group.id,
                group.version,
                group.name,
                group.url,
                group.forked_id,
                group.forked_version,
                group.owner_id,
                group.course_id,
            ])

        zip_file.writestr("LinkTables/AssignmentGroup.csv",
                          group_file.getvalue())
        yield "LinkTables/AssignmentGroup.csv"
Exemplo n.º 17
0
def parse_assignment_load():
    # Lookup Code
    assignment_group_id = parse_lookup_code()
    # Assignment Group ID
    if assignment_group_id is None:
        assignment_group_id = maybe_int(
            request.args.get('assignment_group_id'))
    # Exact "url" code for group
    if assignment_group_id is None:
        assignment_group_id = AssignmentGroup.id_by_url(
            request.args.get('assignment_group_url'))
    # Assignment ID
    current_assignment_id = maybe_int(request.args.get('assignment_id'))
    # Exact "url" code for assignment
    if current_assignment_id is None:
        current_assignment_id = Assignment.id_by_url(
            request.args.get('assignment_url'))
    # User
    user = g.get('user', None)
    user_id = user.id if user else None
    # Course ID of the user
    course_id = maybe_int(request.args.get('course_id', None))
    if course_id is None:
        course_id = int(g.course.id) if 'course' in g and g.course else None
    # LTI submission URL
    new_submission_url = request.form.get('lis_result_sourcedid', None)
    # Embedded?
    embed = request.values.get('embed', 'false').lower() == 'true'
    # Get group
    assignment_group = AssignmentGroup.by_id(assignment_group_id)
    # Get assignments
    if assignment_group is None:
        assignment = Assignment.by_id(current_assignment_id)
        if assignment:
            assignments = [assignment]
        else:
            assignments = []
    else:
        assignments = assignment_group.get_assignments()
    # Potentially adjust assignment_id
    if current_assignment_id is None and assignments:
        current_assignment_id = assignments[0].id
    # Get submissions
    if user_id is None or course_id is None:
        submissions = []
    else:
        submissions = [
            assignment.load_or_new_submission(user_id, course_id,
                                              new_submission_url,
                                              assignment_group_id)
            for assignment in assignments
        ]
    # Determine the users' role in relation to this information
    role = user.determine_role(assignments,
                               submissions) if user else "anonymous"
    if role in ("student", "anonymous"):
        # Check for any IP locked assignments
        for assignment in assignments:
            if not assignment.is_allowed(request.remote_addr):
                return abort(
                    403,
                    "You cannot access this assignment from your current location: "
                    + request.remote_addr)
    # Check passcode
    passcode_protected = False
    for assignment in assignments:
        if assignment.has_passcode() and not passcode_protected:
            passcode_protected = True
    # Combine the submissions and assignments
    group = list(zip(assignments, submissions))
    # Okay we've got everything
    return dict(group=group,
                assignment_group=assignment_group,
                assignments=assignments,
                submissions=submissions,
                assignment_group_id=assignment_group_id,
                current_assignment_id=current_assignment_id,
                user=user,
                user_id=user_id,
                role=role,
                course_id=course_id,
                embed=embed,
                passcode_protected=passcode_protected)