1
1
#!/usr/bin/env python
2
2
# IVLE - Informatics Virtual Learning Environment
3
# Copyright (C) 2007-2009 The University of Melbourne
3
# Copyright (C) 2007-2008 The University of Melbourne
5
5
# This program is free software; you can redistribute it and/or modify
6
6
# it under the terms of the GNU General Public License as published by
20
20
# Author: Matt Giuca
22
23
# Script to calculate the marks for all students for a particular subject.
23
24
# Requires root to run.
31
from xml.dom import minidom
31
33
if os.getuid() != 0:
32
34
print >>sys.stderr, "Must run %s as root." % os.path.basename(sys.argv[0])
36
37
import ivle.database
37
38
import ivle.worksheet.utils
39
41
def get_userdata(user):
56
58
return (userdata_header + [ws.name for ws in worksheets]
57
59
+ ["Total %", "Mark"])
59
def get_marks_user(worksheets, user, as_of=None):
61
def get_marks_user(worksheets, user):
60
62
"""Gets marks for a particular user for a particular set of worksheets.
61
63
@param worksheets: List of Worksheet objects to get marks for.
62
64
@param user: User to get marks for.
63
@param as_of: Optional datetime. If supplied, gets the marks as of as_of.
64
65
@returns: The user's percentage for each worksheet, overall, and
65
66
their final mark, as a list of strings, in a manner which corresponds to
66
67
the headings produced by get_marks_header.
74
75
for worksheet in worksheets:
75
76
# We simply ignore optional exercises here
76
77
mand_done, mand_total, _, _ = (
77
ivle.worksheet.utils.calculate_score(store, user, worksheet,
80
worksheet_pcts.append(float(mand_done) / mand_total)
82
# Avoid Div0, just give everyone 0 marks if there are none
83
worksheet_pcts.append(0.0)
78
ivle.worksheet.utils.calculate_score(store, user, worksheet))
79
worksheet_pcts.append(float(mand_done) / mand_total)
84
80
problems_done += mand_done
85
81
problems_total += mand_total
87
ivle.worksheet.utils.calculate_mark(problems_done, problems_total))
88
return worksheet_pcts + [float(percent)/100, mark]
82
problems_pct = float(problems_done) / problems_total
83
problems_pct_int = (100 * problems_done) / problems_total
84
# XXX Marks calculation (should be abstracted out of here!)
85
# percent / 16, rounded down, with a maximum mark of 5
87
mark = min(problems_pct_int / 16, max_mark)
88
return worksheet_pcts + [problems_pct, mark]
90
def writeuser(worksheets, user, csvfile, cutoff=None):
90
def writeuser(worksheets, user, csvfile):
91
91
userdata = get_userdata(user)
92
marksdata = get_marks_user(worksheets, user, cutoff)
93
data = userdata + marksdata
94
# CSV writer can't handle non-ASCII characters. Encode to UTF-8.
95
data = [unicode(x).encode('utf-8') for x in data]
96
csvfile.writerow(data)
92
marksdata = get_marks_user(worksheets, user)
93
csvfile.writerow(userdata + marksdata)
98
95
def main(argv=None):
109
106
parser.add_option("-s", "--semester",
110
107
action="store", dest="semester", metavar="YEAR/SEMESTER",
111
108
help="Semester of the subject's offering (eg. 2009/1). "
112
"Defaults to the currently active semester.",
114
parser.add_option("-c", "--cutoff",
115
action="store", dest="cutoff", metavar="DATE",
116
help="Cutoff date (calculate the marks as of this date). "
109
"Defaults to the currently active semester.",
119
111
(options, args) = parser.parse_args(argv[1:])
134
126
except ValueError:
135
127
parser.error('Invalid semester (must have form "year/semester")')
137
if options.cutoff is not None:
139
cutoff = datetime.datetime.strptime(options.cutoff,
142
parser.error("Invalid date format: '%s' "
143
"(must be YYYY-MM-DD H:M:S)." % options.cutoff)
147
store = ivle.database.get_store(ivle.config.Config(plugins=False))
129
store = ivle.database.get_store()
149
131
# Get the subject from the DB
150
132
subject = store.find(ivle.database.Subject,
183
165
# Get the list of assessable worksheets
184
worksheets = offering.worksheets.find(assessable=True)
166
worksheets = list(offering.worksheets.find(assessable=True))
186
168
# Start writing the CSV file - header
187
169
csvfile = csv.writer(sys.stdout)
188
170
csvfile.writerow(get_header(worksheets))
190
# Get all users enrolled in this offering
191
users = store.find(ivle.database.User,
192
ivle.database.User.id == ivle.database.Enrolment.user_id,
193
offering.id == ivle.database.Enrolment.offering).order_by(
194
ivle.database.User.login)
172
users = store.find(ivle.database.User).order_by(ivle.database.User.login)
195
173
for user in users:
196
writeuser(worksheets, user, csvfile, cutoff)
174
writeuser(worksheets, user, csvfile)
198
176
if __name__ == "__main__":
199
177
sys.exit(main(sys.argv))