Merge pull request #634 from MITx/feature/victor/per-run-info
Feature/victor/per run info
This commit is contained in:
@@ -208,7 +208,8 @@ __IMPORTANT__: A student's state for a particular content element is tied to the
|
||||
* Note: We will be expanding our understanding and format for metadata in the not-too-distant future, but for now it is simply a set of key-value pairs.
|
||||
|
||||
### Policy file location
|
||||
* The policy for a course run `some_url_name` lives in `policies/some_url_name.json`
|
||||
* The policy for a course run `some_url_name` should live in `policies/some_url_name/policy.json` (NOTE: the old format of putting it in `policies/some_url_name.json` will also work, but we suggest using the subdirectory to have all the per-course policy files in one place)
|
||||
* Grading policy files go in `policies/some_url_name/grading_policy.json` (if there's only one course run, can also put it directly in the course root: `/grading_policy.json`)
|
||||
|
||||
### Policy file contents
|
||||
* The file format is "json", and is best shown by example, as in the tutorial above (though also feel free to google :)
|
||||
@@ -218,6 +219,45 @@ Values are dictionaries of the form {"metadata-key" : "metadata-value"}.
|
||||
* The order in which things appear does not matter, though it may be helpful to organize the file in the same order as things appear in the content.
|
||||
* NOTE: json is picky about commas. If you have trailing commas before closing braces, it will complain and refuse to parse the file. This can be irritating at first.
|
||||
|
||||
### Grading policy file contents
|
||||
|
||||
TODO: This needs to be improved, but for now here's a sketch of how grading works:
|
||||
|
||||
|
||||
* First we grade on individual problems. Correct and total are methods on CapaProblem.
|
||||
|
||||
`problem_score = (correct , total)`
|
||||
|
||||
* If a problem weight is in the xml, then re-weight the problem to be worth that many points
|
||||
|
||||
`if problem_weight:`
|
||||
`problem_score = (correct * weight / total, weight)`
|
||||
|
||||
* Now sum up all of problems in a section to get the percent for that section
|
||||
|
||||
`section_percent = \sum_problems_correct / \sum_problems_total`
|
||||
|
||||
* Now we have all of the percents for all of the graded sections. This is the gradesheet that we pass to to a subclass of CourseGrader.
|
||||
|
||||
* A WeightedSubsectionsGrader contains several SingleSectionGraders and AssignmentFormatGraders. Each of those graders is run first before WeightedSubsectionsGrader computes the final grade.
|
||||
|
||||
- SingleSectionGrader (within a WeightedSubsectionsGrader) contains one section
|
||||
|
||||
`grader_percent = section_percent`
|
||||
|
||||
- AssignmentFormatGrader (within a WegithedSubsectionsGrader) contains multiple sections matching a certain format
|
||||
drop the lowest X sections
|
||||
|
||||
`grader_percent = \sum_section_percent / \count_section`
|
||||
|
||||
- WeightedSubsectionsGrader
|
||||
|
||||
`final_grade_percent = \sum_(grader_percent * grader_weight)`
|
||||
|
||||
* Round the final grade up to the nearest percentage point
|
||||
|
||||
`final_grade_percent = round(final_grade_percent * 100 + 0.05) / 100`
|
||||
|
||||
### Available metadata
|
||||
|
||||
__Not inherited:__
|
||||
@@ -316,6 +356,22 @@ before the week 1 material to make it easy to find in the file.
|
||||
|
||||
* Prefer the most "semantic" name for containers: e.g., use problemset rather than vertical for a problem set. That way, if we decide to display problem sets differently, we don't have to change the xml.
|
||||
|
||||
# Other file locations (info and about)
|
||||
|
||||
With different course runs, we may want different course info and about materials. This is now supported by putting files in as follows:
|
||||
|
||||
/
|
||||
about/
|
||||
foo.html -- shared default for all runs
|
||||
url_name1/
|
||||
foo.html -- version used for url_name1
|
||||
bar.html -- bar for url_name1
|
||||
url_name2/
|
||||
bar.html -- bar for url_name2
|
||||
-- url_name2 will use default foo.html
|
||||
|
||||
and the same works for the `info` directory.
|
||||
|
||||
----
|
||||
|
||||
(Dev note: This file is generated from the mitx repo, in `doc/xml-format.md`. Please make edits there.)
|
||||
|
||||
@@ -64,6 +64,22 @@ def course_image_url(course):
|
||||
path = course.metadata['data_dir'] + "/images/course_image.jpg"
|
||||
return try_staticfiles_lookup(path)
|
||||
|
||||
def find_file(fs, dirs, filename):
|
||||
"""
|
||||
Looks for a filename in a list of dirs on a filesystem, in the specified order.
|
||||
|
||||
fs: an OSFS filesystem
|
||||
dirs: a list of path objects
|
||||
filename: a string
|
||||
|
||||
Returns d / filename if found in dir d, else raises ResourceNotFoundError.
|
||||
"""
|
||||
for d in dirs:
|
||||
filepath = path(d) / filename
|
||||
if fs.exists(filepath):
|
||||
return filepath
|
||||
raise ResourceNotFoundError("Could not find {0}".format(filename))
|
||||
|
||||
def get_course_about_section(course, section_key):
|
||||
"""
|
||||
This returns the snippet of html to be rendered on the course about page,
|
||||
@@ -97,8 +113,13 @@ def get_course_about_section(course, section_key):
|
||||
'requirements', 'syllabus', 'textbook', 'faq', 'more_info',
|
||||
'number', 'instructors', 'overview',
|
||||
'effort', 'end_date', 'prerequisites']:
|
||||
|
||||
try:
|
||||
with course.system.resources_fs.open(path("about") / section_key + ".html") as htmlFile:
|
||||
fs = course.system.resources_fs
|
||||
# first look for a run-specific version
|
||||
dirs = [path("about") / course.url_name, path("about")]
|
||||
filepath = find_file(fs, dirs, section_key + ".html")
|
||||
with fs.open(filepath) as htmlFile:
|
||||
return replace_urls(htmlFile.read().decode('utf-8'),
|
||||
course.metadata['data_dir'])
|
||||
except ResourceNotFoundError:
|
||||
@@ -133,7 +154,12 @@ def get_course_info_section(course, section_key):
|
||||
|
||||
if section_key in ['handouts', 'guest_handouts', 'updates', 'guest_updates']:
|
||||
try:
|
||||
with course.system.resources_fs.open(path("info") / section_key + ".html") as htmlFile:
|
||||
fs = course.system.resources_fs
|
||||
# first look for a run-specific version
|
||||
dirs = [path("info") / course.url_name, path("info")]
|
||||
filepath = find_file(fs, dirs, section_key + ".html")
|
||||
|
||||
with fs.open(filepath) as htmlFile:
|
||||
# Replace '/static/' urls
|
||||
info_html = replace_urls(htmlFile.read().decode('utf-8'), course.metadata['data_dir'])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user