Beispiel #1
0
def student_assignment_show_deadline(ctx, course, assignment_id, utc):
    assignment = course.get_assignment(assignment_id)
    if assignment is None:
        print("Assignment %s does not exist" % assignment_id)
        ctx.exit(CHISUBMIT_FAIL)

    now_utc = get_datetime_now_utc()
    now_local = convert_datetime_to_local(now_utc)

    deadline_utc = assignment.deadline
    deadline_local = convert_datetime_to_local(deadline_utc)

    print(assignment.name)
    print()
    if utc:
        print("      Now (Local): %s" % now_local.isoformat(" "))
        print(" Deadline (Local): %s" % deadline_local.isoformat(" "))
        print()
        print("        Now (UTC): %s" % now_utc.isoformat(" "))
        print("   Deadline (UTC): %s" % deadline_utc.isoformat(" "))
    else:
        print("      Now: %s" % now_local.isoformat(" "))
        print(" Deadline: %s" % deadline_local.isoformat(" "))

    print()

    extensions = compute_extensions_needed(now_utc, deadline_utc)

    if extensions == 0:
        diff = deadline_utc - now_utc
    else:
        diff = now_utc - deadline_utc

    days = diff.days
    hours = diff.seconds // 3600
    minutes = (diff.seconds // 60) % 60
    seconds = diff.seconds % 60

    if extensions == 0:
        print("The deadline has not yet passed")
        print("You have %i days, %i hours, %i minutes, %i seconds left" %
              (days, hours, minutes, seconds))
    else:
        print(
            "The deadline passed %i days, %i hours, %i minutes, %i seconds ago"
            % (days, hours, minutes, seconds))
        print(
            "If you submit your assignment now, you will need to use %i extensions"
            % extensions)

    return CHISUBMIT_SUCCESS
Beispiel #2
0
def student_assignment_show_deadline(ctx, course, assignment_id, utc):
    assignment = course.get_assignment(assignment_id)
    if assignment is None:
        print("Assignment %s does not exist" % assignment_id)
        ctx.exit(CHISUBMIT_FAIL)

    now_utc = get_datetime_now_utc()
    now_local = convert_datetime_to_local(now_utc)

    deadline_utc = assignment.deadline
    deadline_local = convert_datetime_to_local(deadline_utc)

    print(assignment.name)
    print()
    if utc:
        print("      Now (Local): %s" % now_local.isoformat(" "))
        print(" Deadline (Local): %s" % deadline_local.isoformat(" "))
        print()
        print("        Now (UTC): %s" % now_utc.isoformat(" "))
        print("   Deadline (UTC): %s" % deadline_utc.isoformat(" "))
    else:
        print("      Now: %s" % now_local.isoformat(" "))
        print(" Deadline: %s" % deadline_local.isoformat(" "))

    print()

    extensions = compute_extensions_needed(now_utc, deadline_utc)

    if extensions == 0:
        diff = deadline_utc - now_utc
    else:
        diff = now_utc - deadline_utc

    days = diff.days
    hours = diff.seconds // 3600
    minutes = (diff.seconds//60)%60
    seconds = diff.seconds%60

    if extensions == 0:
        print("The deadline has not yet passed")
        print("You have %i days, %i hours, %i minutes, %i seconds left" % (days, hours, minutes, seconds))
    else:
        print("The deadline passed %i days, %i hours, %i minutes, %i seconds ago" % (days, hours, minutes, seconds))
        print("If you submit your assignment now, you will need to use %i extensions" % extensions)

    return CHISUBMIT_SUCCESS
Beispiel #3
0
def assignment_submit(course_id, assignment_id):
    now = get_datetime_now_utc()
    
    course = Course.query.filter_by(id=course_id).first()
    
    if course is None:
        abort(404)
        
    check_course_access_or_abort(g.user, course, 404, roles=["student"])    
    
    assignment = Assignment.query.filter_by(id=assignment_id, course_id=course_id).first()
    # TODO 12DEC14: check permissions *before* 404
    if assignment is None:
        abort(404)

    if not g.user.is_student_in(course):
        error_msg = "You are not a student in course '%s'" % (course_id)
        return jsonify(errors={"register": error_msg}), 400

    if request.method == 'POST':       
        input_data = request.get_json(force=True)
        if not isinstance(input_data, dict):
            return jsonify(error='Request data must be a JSON Object'), 400
        form = SubmitAssignmentInput.from_json(input_data)
        if not form.validate():
            return jsonify(errors=form.errors), 400
        
        team_id = form.team_id.data
        commit_sha = form.commit_sha.data
        extensions_requested = form.extensions.data
        dry_run = form.dry_run.data
        
        team = Team.query.filter_by(id=team_id).first()
        if team is None:
            abort(404)

        check_team_access_or_abort(g.user, team, 404)
        
        team_assignment = AssignmentsTeams.from_id(course.id,team.id,assignment.id)
        if team_assignment is None:
            msg = "Team '%s' is not registered for assignment '%s'" % (team.id, assignment.id)
            return jsonify(errors={"team":msg}), 400
        
        if team_assignment.is_ready_for_grading():
            msg = "You cannot re-submit assignment %s." % (assignment.id)
            msg = " You made a submission before the deadline, and the deadline has passed."
            return jsonify(errors={"submit":msg}), 400
        
        response = {}

        response["dry_run"] = dry_run
        
        response["prior_submission"] = {}
        response["prior_submission"]["submitted_at"] = team_assignment.submitted_at
        response["prior_submission"]["commit_sha"] = team_assignment.commit_sha
        response["prior_submission"]["extensions_used"] = team_assignment.extensions_used
        
        response["submission"] = {}
        response["submission"]["course_id"] = course.id
        response["submission"]["assignment_id"] = assignment.id
        response["submission"]["submitted_at"] = now
        response["submission"]["deadline"] = assignment.deadline
        
        extensions_needed = compute_extensions_needed(submission_time = now, deadline = assignment.deadline)
                
        extension_policy = course.options.get("extension-policy", None)
        extensions_available = team.get_extensions_available(extension_policy)
                
        if extensions_available < 0:
            error_msg = "The number of available extensions is negative"
            return jsonify(errors={"fatal": error_msg}), 500            

        response["submission"]["extensions_requested"] = extensions_requested
        response["submission"]["extensions_needed"] = extensions_needed

        response["team"] = {}
        response["team"]["id"] = team.id
        response["team"]["extensions_available_before"] = extensions_available
        
        if extensions_available + team_assignment.extensions_used >= extensions_needed and extensions_requested == extensions_needed: 
            response["success"] = True
            
            # If the team has already used extensions for a previous submission,
            # they don't count towards the number of extensions needed
            # They are 'credited' to the available extensions
            extensions_available += team_assignment.extensions_used
            
            extensions_available -= extensions_needed
            if not dry_run:
                team_assignment.extensions_used = extensions_needed
                team_assignment.commit_sha = commit_sha
                team_assignment.submitted_at = now
                
                db.session.add(team_assignment)
                db.session.commit()
        else:
            response["success"] = False
                
        response["team"]["extensions_available"] = extensions_available
        
        return jsonify(response)
Beispiel #4
0
def assignment_submit(course_id, assignment_id):
    now = get_datetime_now_utc()

    course = Course.query.filter_by(id=course_id).first()

    if course is None:
        abort(404)

    check_course_access_or_abort(g.user, course, 404, roles=["student"])

    assignment = Assignment.query.filter_by(id=assignment_id,
                                            course_id=course_id).first()
    # TODO 12DEC14: check permissions *before* 404
    if assignment is None:
        abort(404)

    if not g.user.is_student_in(course):
        error_msg = "You are not a student in course '%s'" % (course_id)
        return jsonify(errors={"register": error_msg}), 400

    if request.method == 'POST':
        input_data = request.get_json(force=True)
        if not isinstance(input_data, dict):
            return jsonify(error='Request data must be a JSON Object'), 400
        form = SubmitAssignmentInput.from_json(input_data)
        if not form.validate():
            return jsonify(errors=form.errors), 400

        team_id = form.team_id.data
        commit_sha = form.commit_sha.data
        extensions_requested = form.extensions.data
        dry_run = form.dry_run.data

        team = Team.query.filter_by(id=team_id).first()
        if team is None:
            abort(404)

        check_team_access_or_abort(g.user, team, 404)

        team_assignment = AssignmentsTeams.from_id(course.id, team.id,
                                                   assignment.id)
        if team_assignment is None:
            msg = "Team '%s' is not registered for assignment '%s'" % (
                team.id, assignment.id)
            return jsonify(errors={"team": msg}), 400

        if team_assignment.is_ready_for_grading():
            msg = "You cannot re-submit assignment %s." % (assignment.id)
            msg = " You made a submission before the deadline, and the deadline has passed."
            return jsonify(errors={"submit": msg}), 400

        response = {}

        response["dry_run"] = dry_run

        response["prior_submission"] = {}
        response["prior_submission"][
            "submitted_at"] = team_assignment.submitted_at
        response["prior_submission"]["commit_sha"] = team_assignment.commit_sha
        response["prior_submission"][
            "extensions_used"] = team_assignment.extensions_used

        response["submission"] = {}
        response["submission"]["course_id"] = course.id
        response["submission"]["assignment_id"] = assignment.id
        response["submission"]["submitted_at"] = now
        response["submission"]["deadline"] = assignment.deadline

        extensions_needed = compute_extensions_needed(
            submission_time=now, deadline=assignment.deadline)

        extension_policy = course.options.get("extension-policy", None)
        extensions_available = team.get_extensions_available(extension_policy)

        if extensions_available < 0:
            error_msg = "The number of available extensions is negative"
            return jsonify(errors={"fatal": error_msg}), 500

        response["submission"]["extensions_requested"] = extensions_requested
        response["submission"]["extensions_needed"] = extensions_needed

        response["team"] = {}
        response["team"]["id"] = team.id
        response["team"]["extensions_available_before"] = extensions_available

        if extensions_available + team_assignment.extensions_used >= extensions_needed and extensions_requested == extensions_needed:
            response["success"] = True

            # If the team has already used extensions for a previous submission,
            # they don't count towards the number of extensions needed
            # They are 'credited' to the available extensions
            extensions_available += team_assignment.extensions_used

            extensions_available -= extensions_needed
            if not dry_run:
                team_assignment.extensions_used = extensions_needed
                team_assignment.commit_sha = commit_sha
                team_assignment.submitted_at = now

                db.session.add(team_assignment)
                db.session.commit()
        else:
            response["success"] = False

        response["team"]["extensions_available"] = extensions_available

        return jsonify(response)
Beispiel #5
0
    def create(cls, registration, commit_sha, submitted_at, extensions_override):
        deadline = registration.assignment.deadline
        grace_period = registration.assignment.grace_period
        effective_deadline = deadline + grace_period
        
        extensions_needed = compute_extensions_needed(submission_time = submitted_at, 
                                                      deadline = effective_deadline)
        extensions_needed_without_grace_period = compute_extensions_needed(submission_time = submitted_at, 
                                                      deadline = deadline)
        
        if extensions_override is None and extensions_needed_without_grace_period == extensions_needed + 1:
            in_grace_period = True
        else:
            in_grace_period = False
        
        extensions_available = registration.team.get_extensions_available()
                
        if extensions_available < 0:
            msg = "The number of available extensions is negative"
            return False, Response({"fatal": [msg]}, status=status.HTTP_500_INTERNAL_SERVER_ERROR), None           

        if registration.final_submission is not None:
            extensions_used_in_existing_submission = registration.final_submission.extensions_used
        else:
            extensions_used_in_existing_submission = 0 
        
        error_data = {"extensions_available": extensions_available,
                      "extensions_needed": extensions_needed,
                      "submitted_at": submitted_at.isoformat(sep=" "),
                      "deadline": registration.assignment.deadline.isoformat(sep=" ")}
        
        if extensions_override is None and extensions_available + extensions_used_in_existing_submission < extensions_needed:
            msg = "You do not have enough extensions to make this submission."
            response_data = {"errors": [msg]}
            response_data.update(error_data)
            response = Response(response_data, status=status.HTTP_400_BAD_REQUEST)
            raise SubmissionValidationException(response)
        if extensions_override is not None and extensions_available + extensions_used_in_existing_submission - extensions_override < 0:
            msg = "The extensions override you have specified would leave the team with a negative number of extensions."
            error_data["extensions_override"] = extensions_override
            response_data = {"errors": [msg]}
            response_data.update(error_data)
            response = Response(response_data, status=status.HTTP_400_BAD_REQUEST)
            raise SubmissionValidationException(response)
        else:     
            extensions = {}
            extensions["extensions_available_before"] = extensions_available
            
            # If the team has already used extensions for a previous submission,
            # they don't count towards the number of extensions needed
            # They are 'credited' to the available extensions
            extensions_available += extensions_used_in_existing_submission
            
            if extensions_override is not None:
                extensions["extensions_override"] = extensions_override
                extensions_used = extensions_override
            else:
                extensions_used = extensions_needed

            extensions_available -= extensions_used 

            extensions["extensions_available_after"] = extensions_available
            extensions["extensions_needed"] = extensions_needed            
            
            submission = cls(registration = registration,
                             extensions_used = extensions_used,
                             commit_sha = commit_sha,
                             submitted_at = submitted_at,
                             in_grace_period = in_grace_period)
            
            return submission, extensions                    
Beispiel #6
0
    def create(cls, registration, commit_sha, submitted_at, submitted_by, extensions_override):
        deadline = registration.assignment.deadline
        grace_period = registration.assignment.grace_period
        effective_deadline = deadline + grace_period
        
        extensions_needed = compute_extensions_needed(submission_time = submitted_at, 
                                                      deadline = effective_deadline)
        extensions_needed_without_grace_period = compute_extensions_needed(submission_time = submitted_at, 
                                                      deadline = deadline)
        
        if extensions_override is None and extensions_needed_without_grace_period == extensions_needed + 1:
            in_grace_period = True
        else:
            in_grace_period = False
        
        extensions_available = registration.team.get_extensions_available()
                
        if extensions_available < 0:
            msg = "The number of available extensions is negative"
            return False, Response({"fatal": [msg]}, status=status.HTTP_500_INTERNAL_SERVER_ERROR), None           

        if registration.final_submission is not None:
            extensions_used_in_existing_submission = registration.final_submission.extensions_used
        else:
            extensions_used_in_existing_submission = 0 
        
        error_data = {"extensions_available": extensions_available,
                      "extensions_needed": extensions_needed,
                      "submitted_at": submitted_at.isoformat(sep=" "),
                      "deadline": registration.assignment.deadline.isoformat(sep=" ")}
        
        if extensions_override is None and extensions_available + extensions_used_in_existing_submission < extensions_needed:
            msg = "You do not have enough extensions to make this submission."
            response_data = {"errors": [msg]}
            response_data.update(error_data)
            response = Response(response_data, status=status.HTTP_400_BAD_REQUEST)
            raise SubmissionValidationException(response)
        if extensions_override is not None and extensions_available + extensions_used_in_existing_submission - extensions_override < 0:
            msg = "The extensions override you have specified would leave the team with a negative number of extensions."
            error_data["extensions_override"] = extensions_override
            response_data = {"errors": [msg]}
            response_data.update(error_data)
            response = Response(response_data, status=status.HTTP_400_BAD_REQUEST)
            raise SubmissionValidationException(response)
        else:     
            extensions = {}
            extensions["extensions_available_before"] = extensions_available
            
            # If the team has already used extensions for a previous submission,
            # they don't count towards the number of extensions needed
            # They are 'credited' to the available extensions
            extensions_available += extensions_used_in_existing_submission
            
            if extensions_override is not None:
                extensions["extensions_override"] = extensions_override
                extensions_used = extensions_override
            else:
                extensions_used = extensions_needed

            extensions_available -= extensions_used 

            extensions["extensions_available_after"] = extensions_available
            extensions["extensions_needed"] = extensions_needed            
            
            submission = cls(registration = registration,
                             extensions_used = extensions_used,
                             commit_sha = commit_sha,
                             submitted_at = submitted_at,
                             submitted_by = submitted_by,
                             in_grace_period = in_grace_period)
            
            return submission, extensions