Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
ef8a211b
Commit
ef8a211b
authored
Aug 01, 2012
by
Calen Pennington
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #329 from MITx/MITx/feature/bridger/fast_course_grading
Got profile page working again.
parents
a2e1409d
ae3da772
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
106 additions
and
107 deletions
+106
-107
common/lib/xmodule/xmodule/course_module.py
+33
-1
common/lib/xmodule/xmodule/graders.py
+64
-0
lms/djangoapps/courseware/course_settings.py
+0
-91
lms/djangoapps/courseware/grades.py
+1
-3
lms/djangoapps/courseware/views.py
+3
-7
lms/templates/profile.html
+5
-5
No files found.
common/lib/xmodule/xmodule/course_module.py
View file @
ef8a211b
from
fs.errors
import
ResourceNotFoundError
import
time
import
dateutil.parser
import
logging
from
xmodule.graders
import
load_grading_policy
from
xmodule.modulestore
import
Location
from
xmodule.seq_module
import
SequenceDescriptor
,
SequenceModule
...
...
@@ -14,6 +16,9 @@ class CourseDescriptor(SequenceDescriptor):
def
__init__
(
self
,
system
,
definition
=
None
,
**
kwargs
):
super
(
CourseDescriptor
,
self
)
.
__init__
(
system
,
definition
,
**
kwargs
)
self
.
_grader
=
None
self
.
_grade_cutoffs
=
None
try
:
self
.
start
=
time
.
strptime
(
self
.
metadata
[
"start"
],
"
%
Y-
%
m-
%
dT
%
H:
%
M"
)
...
...
@@ -27,7 +32,34 @@ class CourseDescriptor(SequenceDescriptor):
def
has_started
(
self
):
return
time
.
gmtime
()
>
self
.
start
@property
def
grader
(
self
):
self
.
__load_grading_policy
()
return
self
.
_grader
@property
def
grade_cutoffs
(
self
):
self
.
__load_grading_policy
()
return
self
.
_grade_cutoffs
def
__load_grading_policy
(
self
):
if
not
self
.
_grader
or
not
self
.
_grade_cutoffs
:
policy_string
=
""
try
:
with
self
.
system
.
resources_fs
.
open
(
"grading_policy.json"
)
as
grading_policy_file
:
policy_string
=
grading_policy_file
.
read
()
except
(
IOError
,
ResourceNotFoundError
):
log
.
warning
(
"Unable to load course settings file from grading_policy.json in course "
+
self
.
id
)
grading_policy
=
load_grading_policy
(
policy_string
)
self
.
_grader
=
grading_policy
[
'GRADER'
]
self
.
_grade_cutoffs
=
grading_policy
[
'GRADE_CUTOFFS'
]
@staticmethod
def
id_to_location
(
course_id
):
'''Convert the given course_id (org/course/name) to a location object.
...
...
common/lib/xmodule/xmodule/graders.py
View file @
ef8a211b
import
abc
import
json
import
logging
from
collections
import
namedtuple
...
...
@@ -9,6 +10,69 @@ log = logging.getLogger("mitx.courseware")
# Section either indicates the name of the problem or the name of the section
Score
=
namedtuple
(
"Score"
,
"earned possible graded section"
)
def
load_grading_policy
(
course_policy_string
):
"""
This loads a grading policy from a string (usually read from a file),
which can be a JSON object or an empty string.
The JSON object can have the keys GRADER and GRADE_CUTOFFS. If either is
missing, it reverts to the default.
"""
default_policy_string
=
"""
{
"GRADER" : [
{
"type" : "Homework",
"min_count" : 12,
"drop_count" : 2,
"short_label" : "HW",
"weight" : 0.15
},
{
"type" : "Lab",
"min_count" : 12,
"drop_count" : 2,
"category" : "Labs",
"weight" : 0.15
},
{
"type" : "Midterm",
"name" : "Midterm Exam",
"short_label" : "Midterm",
"weight" : 0.3
},
{
"type" : "Final",
"name" : "Final Exam",
"short_label" : "Final",
"weight" : 0.4
}
],
"GRADE_CUTOFFS" : {
"A" : 0.87,
"B" : 0.7,
"C" : 0.6
}
}
"""
# Load the global settings as a dictionary
grading_policy
=
json
.
loads
(
default_policy_string
)
# Load the course policies as a dictionary
course_policy
=
{}
if
course_policy_string
:
course_policy
=
json
.
loads
(
course_policy_string
)
# Override any global settings with the course settings
grading_policy
.
update
(
course_policy
)
# Here is where we should parse any configurations, so that we can fail early
grading_policy
[
'GRADER'
]
=
grader_from_conf
(
grading_policy
[
'GRADER'
])
return
grading_policy
def
aggregate_scores
(
scores
,
section_name
=
"summary"
):
"""
...
...
lms/djangoapps/courseware/course_settings.py
deleted
100644 → 0
View file @
a2e1409d
"""
Course settings module. All settings in the global_settings are
first applied, and then any settings in the settings.DATA_DIR/course_settings.json
are applied. A setting must be in ALL_CAPS.
Settings are used by calling
from courseware.course_settings import course_settings
Note that courseware.course_settings.course_settings is not a module -- it's an object. So
importing individual settings is not possible:
from courseware.course_settings.course_settings import GRADER # This won't work.
"""
import
json
import
logging
from
django.conf
import
settings
from
xmodule
import
graders
log
=
logging
.
getLogger
(
"mitx.courseware"
)
global_settings_json
=
"""
{
"GRADER" : [
{
"type" : "Homework",
"min_count" : 12,
"drop_count" : 2,
"short_label" : "HW",
"weight" : 0.15
},
{
"type" : "Lab",
"min_count" : 12,
"drop_count" : 2,
"category" : "Labs",
"weight" : 0.15
},
{
"type" : "Midterm",
"name" : "Midterm Exam",
"short_label" : "Midterm",
"weight" : 0.3
},
{
"type" : "Final",
"name" : "Final Exam",
"short_label" : "Final",
"weight" : 0.4
}
],
"GRADE_CUTOFFS" : {
"A" : 0.87,
"B" : 0.7,
"C" : 0.6
}
}
"""
class
Settings
(
object
):
def
__init__
(
self
):
# Load the global settings as a dictionary
global_settings
=
json
.
loads
(
global_settings_json
)
# Load the course settings as a dictionary
course_settings
=
{}
try
:
# TODO: this doesn't work with multicourse
with
open
(
settings
.
DATA_DIR
+
"/course_settings.json"
)
as
course_settings_file
:
course_settings_string
=
course_settings_file
.
read
()
course_settings
=
json
.
loads
(
course_settings_string
)
except
IOError
:
log
.
warning
(
"Unable to load course settings file from "
+
str
(
settings
.
DATA_DIR
)
+
"/course_settings.json"
)
# Override any global settings with the course settings
global_settings
.
update
(
course_settings
)
# Now, set the properties from the course settings on ourselves
for
setting
in
global_settings
:
setting_value
=
global_settings
[
setting
]
setattr
(
self
,
setting
,
setting_value
)
# Here is where we should parse any configurations, so that we can fail early
self
.
GRADER
=
graders
.
grader_from_conf
(
self
.
GRADER
)
course_settings
=
Settings
()
lms/djangoapps/courseware/grades.py
View file @
ef8a211b
...
...
@@ -3,7 +3,6 @@ import logging
from
django.conf
import
settings
from
courseware.course_settings
import
course_settings
from
xmodule
import
graders
from
xmodule.graders
import
Score
from
models
import
StudentModule
...
...
@@ -11,7 +10,7 @@ from models import StudentModule
_log
=
logging
.
getLogger
(
"mitx.courseware"
)
def
grade_sheet
(
student
,
course
,
student_module_cache
):
def
grade_sheet
(
student
,
course
,
grader
,
student_module_cache
):
"""
This pulls a summary of all problems in the course. It returns a dictionary with two datastructures:
...
...
@@ -78,7 +77,6 @@ def grade_sheet(student, course, student_module_cache):
'chapter'
:
c
.
metadata
.
get
(
'display_name'
),
'sections'
:
sections
})
grader
=
course_settings
.
GRADER
grade_summary
=
grader
.
grade
(
totaled_scores
)
return
{
'courseware_summary'
:
chapters
,
...
...
lms/djangoapps/courseware/views.py
View file @
ef8a211b
...
...
@@ -19,7 +19,6 @@ from django.views.decorators.cache import cache_control
from
module_render
import
toc_for_course
,
get_module
,
get_section
from
models
import
StudentModuleCache
from
student.models
import
UserProfile
from
multicourse
import
multicourse_settings
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.exceptions
import
InvalidLocationError
,
ItemNotFoundError
,
NoPathToItem
from
xmodule.modulestore.django
import
modulestore
...
...
@@ -110,8 +109,8 @@ def profile(request, course_id, student_id=None):
user_info
=
UserProfile
.
objects
.
get
(
user
=
student
)
student_module_cache
=
StudentModuleCache
(
request
.
user
,
course
)
course
,
_
,
_
,
_
=
get_module
(
request
.
user
,
request
,
course
.
location
,
student_module_cache
)
course
_module
,
_
,
_
,
_
=
get_module
(
request
.
user
,
request
,
course
.
location
,
student_module_cache
)
context
=
{
'name'
:
user_info
.
name
,
'username'
:
student
.
username
,
'location'
:
user_info
.
location
,
...
...
@@ -121,7 +120,7 @@ def profile(request, course_id, student_id=None):
'format_url_params'
:
format_url_params
,
'csrf'
:
csrf
(
request
)[
'csrf_token'
]
}
context
.
update
(
grades
.
grade_sheet
(
student
,
course
,
student_module_cache
))
context
.
update
(
grades
.
grade_sheet
(
student
,
course
_module
,
course
.
grader
,
student_module_cache
))
return
render_to_response
(
'profile.html'
,
context
)
...
...
@@ -184,9 +183,6 @@ def index(request, course_id, chapter=None, section=None,
chapter
=
clean
(
chapter
)
section
=
clean
(
section
)
if
settings
.
ENABLE_MULTICOURSE
:
settings
.
MODULESTORE
[
'default'
][
'OPTIONS'
][
'data_dir'
]
=
settings
.
DATA_DIR
+
multicourse_settings
.
get_course_xmlpath
(
course
)
context
=
{
'csrf'
:
csrf
(
request
)[
'csrf_token'
],
'accordion'
:
render_accordion
(
request
,
course
,
chapter
,
section
),
...
...
lms/templates/profile.html
View file @
ef8a211b
...
...
@@ -4,6 +4,7 @@
<
%
block
name=
"headextra"
>
<
%
static:css
group=
'course'
/>
</
%
block>
<
%
namespace
name=
"profile_graphs"
file=
"profile_graphs.js"
/>
<
%
block
name=
"title"
><title>
Profile - edX 6.002x
</title></
%
block>
...
...
@@ -110,9 +111,9 @@ $(function() {
</
%
block>
<
%
include
file=
"navigation.html"
args=
"active_page='profile'"
/>
<
%
include
file=
"
course_
navigation.html"
args=
"active_page='profile'"
/>
<section
class=
"
main-content
"
>
<section
class=
"
container
"
>
<div
class=
"profile-wrapper"
>
<section
class=
"course-info"
>
...
...
@@ -126,8 +127,7 @@ $(function() {
%for chapter in courseware_summary:
%if not chapter['chapter'] == "hidden":
<li>
<h2><a
href=
"${reverse('courseware_chapter', args=format_url_params([chapter['course'], chapter['chapter']])) }"
>
${ chapter['chapter'] }
</a></h2>
<h2>
${ chapter['chapter'] }
</h2>
<ol
class=
"sections"
>
%for section in chapter['sections']:
...
...
@@ -138,7 +138,7 @@ $(function() {
percentageString =
"{0:.0%}"
.
format
(
float
(
earned
)/
total
)
if
earned
>
0 and total > 0 else ""
%>
<h3><a
href=
"${reverse('courseware_section',
args=format_url_params([chapter['course'], chapter['chapter'], section['section']]))
}"
>
<h3><a
href=
"${reverse('courseware_section',
kwargs={'course_id' : course.id, 'chapter' : chapter['chapter'], 'section' : section['section']})
}"
>
${ section['section'] }
</a>
${"({0:.3n}/{1:.3n}) {2}".format( float(earned), float(total), percentageString )}
</h3>
${section['format']}
%if 'due' in section and section['due']!="":
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment