106 lines
3.6 KiB
Python
Executable File
106 lines
3.6 KiB
Python
Executable File
from urllib.parse import urlencode
|
|
from urllib.request import urlopen
|
|
import pickle
|
|
import json
|
|
from collections import OrderedDict
|
|
import numpy as np
|
|
import os
|
|
|
|
|
|
class SubmissionBase:
|
|
|
|
submit_url = 'https://www-origin.coursera.org/api/' \
|
|
'onDemandProgrammingImmediateFormSubmissions.v1'
|
|
save_file = 'token.pkl'
|
|
|
|
def __init__(self, assignment_slug, part_names):
|
|
self.assignment_slug = assignment_slug
|
|
self.part_names = part_names
|
|
self.login = None
|
|
self.token = None
|
|
self.functions = OrderedDict()
|
|
self.args = dict()
|
|
|
|
def grade(self):
|
|
print('\nSubmitting Solutions | Programming Exercise %s\n' % self.assignment_slug)
|
|
self.login_prompt()
|
|
|
|
# Evaluate the different parts of exercise
|
|
parts = OrderedDict()
|
|
for part_id, result in self:
|
|
parts[str(part_id)] = {'output': sprintf('%0.5f ', result)}
|
|
result, response = self.request(parts)
|
|
response = json.loads(response.decode("utf-8"))
|
|
|
|
# if an error was returned, print it and stop
|
|
if 'errorMessage' in response:
|
|
print(response['errorMessage'])
|
|
return
|
|
|
|
# Print the grading table
|
|
print('%43s | %9s | %-s' % ('Part Name', 'Score', 'Feedback'))
|
|
print('%43s | %9s | %-s' % ('---------', '-----', '--------'))
|
|
for part in parts:
|
|
part_feedback = response['partFeedbacks'][part]
|
|
part_evaluation = response['partEvaluations'][part]
|
|
score = '%d / %3d' % (part_evaluation['score'], part_evaluation['maxScore'])
|
|
print('%43s | %9s | %-s' % (self.part_names[int(part) - 1], score, part_feedback))
|
|
evaluation = response['evaluation']
|
|
total_score = '%d / %d' % (evaluation['score'], evaluation['maxScore'])
|
|
print(' --------------------------------')
|
|
print('%43s | %9s | %-s\n' % (' ', total_score, ' '))
|
|
|
|
def login_prompt(self):
|
|
if os.path.isfile(self.save_file):
|
|
with open(self.save_file, 'rb') as f:
|
|
login, token = pickle.load(f)
|
|
reenter = input('Use token from last successful submission (%s)? (Y/n): ' % login)
|
|
|
|
if reenter == '' or reenter[0] == 'Y' or reenter[0] == 'y':
|
|
self.login, self.token = login, token
|
|
return
|
|
else:
|
|
os.remove(self.save_file)
|
|
|
|
self.login = input('Login (email address): ')
|
|
self.token = input('Token: ')
|
|
|
|
# Save the entered credentials
|
|
if not os.path.isfile(self.save_file):
|
|
with open(self.save_file, 'wb') as f:
|
|
pickle.dump((self.login, self.token), f)
|
|
|
|
def request(self, parts):
|
|
params = {
|
|
'assignmentSlug': self.assignment_slug,
|
|
'secret': self.token,
|
|
'parts': parts,
|
|
'submitterEmail': self.login}
|
|
|
|
params = urlencode({'jsonBody': json.dumps(params)}).encode("utf-8")
|
|
f = urlopen(self.submit_url, params)
|
|
try:
|
|
return 0, f.read()
|
|
finally:
|
|
f.close()
|
|
|
|
def __iter__(self):
|
|
for part_id in self.functions:
|
|
yield part_id
|
|
|
|
def __setitem__(self, key, value):
|
|
self.functions[key] = value
|
|
|
|
|
|
def sprintf(fmt, arg):
|
|
""" Emulates (part of) Octave sprintf function. """
|
|
if isinstance(arg, tuple):
|
|
# for multiple return values, only use the first one
|
|
arg = arg[0]
|
|
|
|
if isinstance(arg, (np.ndarray, list)):
|
|
# concatenates all elements, column by column
|
|
return ' '.join(fmt % e for e in np.asarray(arg).ravel('F'))
|
|
else:
|
|
return fmt % arg
|