2
# IVLE - Informatics Virtual Learning Environment
3
# Copyright (C) 2007-2009 The University of Melbourne
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
# Script to calculate the marks for all students for a particular subject.
23
# Requires root to run.
30
from xml.dom import minidom
33
print >>sys.stderr, "Must run %s as root." % os.path.basename(sys.argv[0])
37
import ivle.worksheet.utils
40
def get_userdata(user):
42
Given a User object, returns a list of strings for the user data which
43
will be part of the output for this user.
44
(This is not marks, it's other user data).
46
last_login = (None if user.last_login is None else
47
user.last_login.strftime("%d/%m/%y"))
48
return [user.studentid, user.login, user.fullname, last_login]
50
userdata_header = ["Student ID", "Login", "Full name", "Last login"]
51
def get_header(worksheets):
53
Given a list of Worksheet objects (the assessable worksheets), returns a
54
list of strings -- the column headings for the marks section of the CSV
57
return (userdata_header + [ws.name for ws in worksheets]
58
+ ["Total %", "Mark"])
60
def get_marks_user(worksheets, user):
61
"""Gets marks for a particular user for a particular set of worksheets.
62
@param worksheets: List of Worksheet objects to get marks for.
63
@param user: User to get marks for.
64
@returns: The user's percentage for each worksheet, overall, and
65
their final mark, as a list of strings, in a manner which corresponds to
66
the headings produced by get_marks_header.
69
# As we go, calculate the total score for this subject
70
# (Assessable worksheets only, mandatory problems only)
74
for worksheet in worksheets:
75
# We simply ignore optional exercises here
76
mand_done, mand_total, _, _ = (
77
ivle.worksheet.utils.calculate_score(store, user, worksheet))
79
worksheet_pcts.append(float(mand_done) / mand_total)
81
# Avoid Div0, just give everyone 0 marks if there are none
82
worksheet_pcts.append(0.0)
83
problems_done += mand_done
84
problems_total += mand_total
86
ivle.worksheet.utils.calculate_mark(problems_done, problems_total))
87
return worksheet_pcts + [float(percent)/100, mark]
89
def writeuser(worksheets, user, csvfile):
90
userdata = get_userdata(user)
91
marksdata = get_marks_user(worksheets, user)
92
data = userdata + marksdata
93
# CSV writer can't handle non-ASCII characters. Encode to UTF-8.
94
data = [unicode(x).encode('utf-8') for x in data]
95
csvfile.writerow(data)
102
usage = """usage: %prog [options] subject
104
Reports each student's marks for a given subject offering."""
107
parser = optparse.OptionParser(usage)
108
parser.add_option("-s", "--semester",
109
action="store", dest="semester", metavar="YEAR/SEMESTER",
110
help="Semester of the subject's offering (eg. 2009/1). "
111
"Defaults to the currently active semester.",
113
(options, args) = parser.parse_args(argv[1:])
119
subject_name = unicode(args[0])
121
if options.semester is None:
122
year, semester = None, None
125
year, semester = options.semester.split('/')
126
if len(year) == 0 or len(semester) == 0:
129
parser.error('Invalid semester (must have form "year/semester")')
131
store = ivle.database.get_store()
133
# Get the subject from the DB
134
subject = store.find(ivle.database.Subject,
135
ivle.database.Subject.short_name == subject_name).one()
137
print >>sys.stderr, "No subject with short name '%s'" % subject_name
140
# Get the offering from the DB
142
# None specified - get the current offering from the DB
143
offerings = list(subject.active_offerings())
144
if len(offerings) == 0:
145
print >>sys.stderr, ("No active offering for subject '%s'"
148
elif len(offerings) > 1:
149
print >>sys.stderr, ("Multiple active offerings for subject '%s':"
151
print >>sys.stderr, "Please use one of:"
152
for offering in offerings:
153
print >>sys.stderr, (" --semester=%s/%s"
154
% (offering.semester.year, offering.semester.semester))
157
offering = offerings[0]
159
# Get the offering for the specified semester
160
offering = subject.offering_for_semester(year, semester)
162
print >>sys.stderr, (
163
"No offering for subject '%s' in semester %s/%s"
164
% (subject_name, year, semester))
167
# Get the list of assessable worksheets
168
worksheets = offering.worksheets.find(assessable=True)
170
# Start writing the CSV file - header
171
csvfile = csv.writer(sys.stdout)
172
csvfile.writerow(get_header(worksheets))
174
# Get all users enrolled in this offering
175
users = store.find(ivle.database.User,
176
ivle.database.User.id == ivle.database.Enrolment.user_id,
177
offering.id == ivle.database.Enrolment.offering).order_by(
178
ivle.database.User.login)
180
writeuser(worksheets, user, csvfile)
182
if __name__ == "__main__":
183
sys.exit(main(sys.argv))