Skip to content

Commit fe118d8

Browse files
authored
Grade Correctness for Checkpoint Grading and Bug Fixes (okpy#1210)
* allow autograder correctness grading for checkpoints * minor tweaks in how backups are gathered * fix composition comments not working
1 parent 8a92eee commit fe118d8

File tree

8 files changed

+72
-27
lines changed

8 files changed

+72
-27
lines changed

server/autograder.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,6 @@ def retry_task(task):
235235
message = '{} graded, {} failed'.format(
236236
statuses[GradingStatus.DONE], statuses[GradingStatus.FAILED])
237237
logger.info(message)
238-
return message
239238

240239

241240
@jobs.background_job
@@ -251,5 +250,11 @@ def autograde_assignment(assignment_id):
251250
assignment = Assignment.query.get(assignment_id)
252251
course_submissions = assignment.course_submissions(include_empty=False)
253252
backup_ids = set(fs['backup']['id'] for fs in course_submissions if fs['backup'])
254-
return autograde_backups(assignment, jobs.get_current_job().user_id, backup_ids, logger)
253+
try:
254+
autograde_backups(assignment, current_user.id, backup_ids, logger)
255+
except ValueError:
256+
logger.info('Could not autograde backups - Please add an autograding key.')
257+
return
258+
return '/admin/course/{cid}/assignments/{aid}/scores'.format(
259+
cid=jobs.get_current_job().course_id, aid=assignment.id)
255260

server/controllers/admin.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,7 @@ def autograde(cid, aid):
829829
job = jobs.enqueue_job(
830830
autograder.autograde_assignment,
831831
description='Autograde {}'.format(assign.display_name),
832+
result_kind='link',
832833
timeout=2 * 60 * 60, # 2 hours
833834
course_id=cid,
834835
user_id=current_user.id,
@@ -1151,18 +1152,21 @@ def checkpoint_grading(cid, aid):
11511152

11521153
form = forms.CheckpointCreditForm()
11531154
if form.validate_on_submit():
1155+
timeout = 3600 if form.grade_backups.data else 600
11541156
job = jobs.enqueue_job(
11551157
checkpoint.assign_scores,
11561158
description='Checkpoint Scoring for {}'.format(assign.display_name),
1157-
timeout=600,
1159+
timeout=timeout,
1160+
result_kind='link',
11581161
course_id=cid,
11591162
user_id=current_user.id,
11601163
assign_id=assign.id,
11611164
score=form.score.data,
11621165
kind=form.kind.data,
11631166
message=form.message.data,
11641167
deadline=form.deadline.data,
1165-
include_backups=form.include_backups.data)
1168+
include_backups=form.include_backups.data,
1169+
grade_backups=form.grade_backups.data)
11661170
return redirect(url_for('.course_job', cid=cid, job_id=job.id))
11671171
else:
11681172
if not form.kind.data:

server/forms.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,10 @@ class CheckpointCreditForm(GradeForm):
317317
description="Award points to all submissions before this time")
318318
include_backups = BooleanField('Include Backups', default=True,
319319
description='Include backups (as well as submissions)')
320+
grade_backups = BooleanField('Grade Backups', default=False,
321+
description='Grade backups using the autograder')
322+
kind = SelectField('Kind', choices=[(c, c.title()) for c in SCORE_KINDS if 'checkpoint' in c.lower()],
323+
validators=[validators.required()])
320324

321325
class CreateTaskForm(BaseForm):
322326
kind = SelectField('Kind', choices=[(c, c.title()) for c in SCORE_KINDS],

server/jobs/checkpoint.py

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
from server import jobs
55
from server.models import Assignment, Score, Backup, db
66
from server.utils import server_time_obj
7+
from server.autograder import autograde_backups
78

89
@jobs.background_job
910
def assign_scores(assign_id, score, kind, message, deadline,
10-
include_backups=True):
11+
include_backups=True, grade_backups=False):
1112
logger = jobs.get_job_logger()
1213
current_user = jobs.get_current_job().user
1314

@@ -19,7 +20,7 @@ def assign_scores(assign_id, score, kind, message, deadline,
1920
backups = Backup.query.filter(
2021
Backup.assignment_id == assign_id,
2122
or_(Backup.created <= deadline, Backup.custom_submission_time <= deadline)
22-
).order_by(Backup.created.desc()).group_by(Backup.submitter_id)
23+
).group_by(Backup.submitter_id).order_by(Backup.created.desc())
2324

2425
if not include_backups:
2526
backups = backups.filter(Backup.submit == True)
@@ -31,28 +32,49 @@ def assign_scores(assign_id, score, kind, message, deadline,
3132
.format(deadline))
3233
return "No Scores Created"
3334

34-
total_count = len(all_backups)
35-
logger.info("Found {} eligible submissions...".format(total_count))
36-
3735
score_counter, seen = 0, set()
3836

37+
unique_backups = []
38+
3939
for back in all_backups:
40-
if back.creator in seen:
40+
if back.creator not in seen:
41+
unique_backups.append(back)
42+
seen |= back.owners()
43+
44+
total_count = len(unique_backups)
45+
logger.info("Found {} unique and eligible submissions...".format(total_count))
46+
47+
if grade_backups:
48+
logger.info('\nAutograding {} backups'.format(total_count))
49+
backup_ids = [back.id for back in unique_backups]
50+
try:
51+
autograde_backups(assignment, current_user.id, backup_ids, logger)
52+
except ValueError:
53+
logger.info('Could not autograde backups - Please add an autograding key.')
54+
else:
55+
for back in unique_backups:
56+
new_score = Score(score=score, kind=kind, message=message,
57+
user_id=back.submitter_id,
58+
assignment=assignment, backup=back,
59+
grader=current_user)
60+
61+
db.session.add(new_score)
62+
new_score.archive_duplicates()
63+
4164
score_counter += 1
42-
continue
43-
new_score = Score(score=score, kind=kind, message=message,
44-
user_id=back.submitter_id,
45-
assignment=assignment, backup=back,
46-
grader=current_user)
47-
db.session.add(new_score)
48-
new_score.archive_duplicates()
65+
if score_counter % 100 == 0:
66+
logger.info("Scored {} of {}".format(score_counter, total_count))
67+
68+
# only commit if all scores were successfully added
4969
db.session.commit()
5070

51-
score_counter += 1
52-
if score_counter % 5 == 0:
53-
logger.info("Scored {} of {}".format(score_counter, total_count))
54-
seen |= back.owners()
71+
logger.info("Left {} '{}' scores of {}".format(score_counter, kind.title(), score))
72+
return '/admin/course/{cid}/assignments/{aid}/scores'.format(
73+
cid=jobs.get_current_job().course_id, aid=assignment.id)
74+
75+
76+
77+
78+
79+
5580

56-
result = "Left {} '{}' scores of {}".format(score_counter, kind.title(), score)
57-
logger.info(result)
58-
return result

server/static/css/code.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* Source file and diff rendering */
2-
.source-file {
2+
.source-file-box {
33
position: relative;
44
font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
55
font-size: 12px;

server/static/css/main.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,4 +205,13 @@ img.desaturate{
205205
display: block;
206206
margin: 0px auto;
207207
color: #717171;
208+
}
209+
210+
.checkbox {
211+
display: inline-block;
212+
}
213+
214+
.checkbox + .help-block{
215+
display: inline-block;
216+
margin-left: 8px;
208217
}

server/templates/diff.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ <h6>This file could not be displayed</h6>
137137
{% endmacro %}
138138

139139
{% macro source_file(backup, filename, file, moss_diff) %}
140-
<div class="box source-file">
140+
<div class="box source-file-box">
141141
<div class="box-header source-file-header">
142142
<div class="source-file-name fixed-width-font">
143143
{{ filename }}
@@ -160,7 +160,7 @@ <h6>This file could not be displayed</h6>
160160
</button>
161161
</div>
162162
</div>
163-
<div class="box-body table-responsive"
163+
<div class="box-body source-file table-responsive"
164164
data-backup-id={{ utils.encode_id(backup.id) }}
165165
data-filename={{ filename }}>
166166
<table class="highlight">

server/templates/staff/jobs/checkpoint.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ <h1>
3838
{{ forms.render_field(form.message) }}
3939
{{ forms.render_field(form.deadline) }}
4040
{{ forms.render_checkbox_field(form.include_backups) }}
41+
{{ forms.render_checkbox_field(form.grade_backups) }}
4142
{% endcall %}
4243
</div>
4344
</div>

0 commit comments

Comments
 (0)