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
be369938
Commit
be369938
authored
Jul 19, 2012
by
Rocky Duan
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of github.com:MITx/mitx
parents
2b89a82a
703c7a95
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
1621 additions
and
79 deletions
+1621
-79
common/lib/capa/capa/capa_problem.py
+37
-9
common/lib/capa/capa/correctmap.py
+9
-1
common/lib/capa/capa/inputtypes.py
+69
-5
common/lib/capa/capa/responsetypes.py
+154
-46
common/lib/capa/capa/templates/choicegroup.html
+6
-3
common/lib/capa/capa/templates/optioninput.html
+1
-1
common/lib/xmodule/tests/__init__.py
+81
-0
common/lib/xmodule/tests/test_files/choiceresponse_checkbox.xml
+59
-0
common/lib/xmodule/tests/test_files/choiceresponse_radio.xml
+40
-0
common/lib/xmodule/tests/test_files/coderesponse.xml
+101
-0
common/lib/xmodule/xmodule/capa_module.py
+23
-3
common/lib/xmodule/xmodule/seq_module.py
+1
-1
lms/djangoapps/courseware/module_render.py
+12
-9
lms/static/sass/marketing-ie.css
+10
-0
lms/static/sass/marketing.css
+1017
-0
lms/urls.py
+1
-1
No files found.
common/lib/capa/capa/capa_problem.py
View file @
be369938
...
...
@@ -39,7 +39,7 @@ import responsetypes
# dict of tagname, Response Class -- this should come from auto-registering
response_tag_dict
=
dict
([(
x
.
response_tag
,
x
)
for
x
in
responsetypes
.
__all__
])
entry_types
=
[
'textline'
,
'schematic'
,
'
choicegroup'
,
'textbox'
,
'imageinput'
,
'optioninput
'
]
entry_types
=
[
'textline'
,
'schematic'
,
'
textbox'
,
'imageinput'
,
'optioninput'
,
'choicegroup'
,
'radiogroup'
,
'checkboxgroup
'
]
solution_types
=
[
'solution'
]
# extra things displayed after "show answers" is pressed
response_properties
=
[
"responseparam"
,
"answer"
]
# these get captured as student responses
...
...
@@ -118,6 +118,9 @@ class LoncapaProblem(object):
# the dict has keys = xml subtree of Response, values = Response instance
self
.
_preprocess_problem
(
self
.
tree
)
if
not
self
.
student_answers
:
# True when student_answers is an empty dict
self
.
set_initial_display
()
def
do_reset
(
self
):
'''
Reset internal state to unfinished, with no answers
...
...
@@ -126,6 +129,14 @@ class LoncapaProblem(object):
self
.
correct_map
=
CorrectMap
()
self
.
done
=
False
def
set_initial_display
(
self
):
initial_answers
=
dict
()
for
responder
in
self
.
responders
.
values
():
if
hasattr
(
responder
,
'get_initial_display'
):
initial_answers
.
update
(
responder
.
get_initial_display
())
self
.
student_answers
=
initial_answers
def
__unicode__
(
self
):
return
u"LoncapaProblem ({0})"
.
format
(
self
.
problem_id
)
...
...
@@ -180,14 +191,31 @@ class LoncapaProblem(object):
return
{
'score'
:
correct
,
'total'
:
self
.
get_max_score
()}
def
update_score
(
self
,
score_msg
):
newcmap
=
CorrectMap
()
def
update_score
(
self
,
score_msg
,
queuekey
):
'''
Deliver grading response (e.g. from async code checking) to
the specific ResponseType that requested grading
Returns an updated CorrectMap
'''
cmap
=
CorrectMap
()
cmap
.
update
(
self
.
correct_map
)
for
responder
in
self
.
responders
.
values
():
if
hasattr
(
responder
,
'update_score'
):
# Is this the best way to implement 'update_score' for CodeResponse?
results
=
responder
.
update_score
(
score_msg
)
newcmap
.
update
(
results
)
self
.
correct_map
=
newcmap
return
newcmap
if
hasattr
(
responder
,
'update_score'
):
# Each LoncapaResponse will update the specific entries of 'cmap' that it's responsible for
cmap
=
responder
.
update_score
(
score_msg
,
cmap
,
queuekey
)
self
.
correct_map
.
set_dict
(
cmap
.
get_dict
())
return
cmap
def
is_queued
(
self
):
'''
Returns True if any part of the problem has been submitted to an external queue
'''
queued
=
False
for
answer_id
in
self
.
correct_map
:
if
self
.
correct_map
.
is_queued
(
answer_id
):
queued
=
True
return
queued
def
grade_answers
(
self
,
answers
):
'''
...
...
@@ -457,7 +485,7 @@ class LoncapaProblem(object):
self
.
responder_answers
=
{}
for
response
in
self
.
responders
.
keys
():
try
:
self
.
responder_answers
[
response
]
=
responder
.
get_answers
()
self
.
responder_answers
[
response
]
=
self
.
responders
[
response
]
.
get_answers
()
except
:
log
.
debug
(
'responder
%
s failed to properly return get_answers()'
%
self
.
responders
[
response
])
# FIXME
raise
...
...
common/lib/capa/capa/correctmap.py
View file @
be369938
...
...
@@ -14,6 +14,7 @@ class CorrectMap(object):
- msg : string (may have HTML) giving extra message response (displayed below textline or textbox)
- hint : string (may have HTML) giving optional hint (displayed below textline or textbox, above msg)
- hintmode : one of (None,'on_request','always') criteria for displaying hint
- queuekey : a random integer for xqueue_callback verification
Behaves as a dict.
'''
...
...
@@ -29,13 +30,14 @@ class CorrectMap(object):
def
__iter__
(
self
):
return
self
.
cmap
.
__iter__
()
def
set
(
self
,
answer_id
=
None
,
correctness
=
None
,
npoints
=
None
,
msg
=
''
,
hint
=
''
,
hintmode
=
None
):
def
set
(
self
,
answer_id
=
None
,
correctness
=
None
,
npoints
=
None
,
msg
=
''
,
hint
=
''
,
hintmode
=
None
,
queuekey
=
None
):
if
answer_id
is
not
None
:
self
.
cmap
[
answer_id
]
=
{
'correctness'
:
correctness
,
'npoints'
:
npoints
,
'msg'
:
msg
,
'hint'
:
hint
,
'hintmode'
:
hintmode
,
'queuekey'
:
queuekey
,
}
def
__repr__
(
self
):
...
...
@@ -63,6 +65,12 @@ class CorrectMap(object):
if
answer_id
in
self
.
cmap
:
return
self
.
cmap
[
answer_id
][
'correctness'
]
==
'correct'
return
None
def
is_queued
(
self
,
answer_id
):
return
answer_id
in
self
.
cmap
and
self
.
cmap
[
answer_id
][
'queuekey'
]
is
not
None
def
is_right_queuekey
(
self
,
answer_id
,
test_key
):
return
answer_id
in
self
.
cmap
and
self
.
cmap
[
answer_id
][
'queuekey'
]
==
test_key
def
get_npoints
(
self
,
answer_id
):
if
self
.
is_correct
(
answer_id
):
npoints
=
self
.
cmap
[
answer_id
]
.
get
(
'npoints'
,
1
)
# default to 1 point if correct
...
...
common/lib/capa/capa/inputtypes.py
View file @
be369938
...
...
@@ -8,7 +8,9 @@ Module containing the problem elements which render into input objects
- textline
- textbox (change this to textarea?)
- schemmatic
- choicegroup (for multiplechoice: checkbox, radio, or select option)
- choicegroup
- radiogroup
- checkboxgroup
- imageinput (for clickable image)
- optioninput (for option list)
...
...
@@ -132,7 +134,8 @@ def optioninput(element, value, status, render_template, msg=''):
oset
=
[
x
[
1
:
-
1
]
for
x
in
list
(
oset
)]
# osetdict = dict([('option_%s_%s' % (eid,x),oset[x]) for x in range(len(oset)) ]) # make dict with IDs
osetdict
=
dict
([(
oset
[
x
],
oset
[
x
])
for
x
in
range
(
len
(
oset
))
])
# make dict with key,value same
osetdict
=
[(
oset
[
x
],
oset
[
x
])
for
x
in
range
(
len
(
oset
))
]
# make ordered list with (key,value) same
# TODO: allow ordering to be randomized
context
=
{
'id'
:
eid
,
'value'
:
value
,
...
...
@@ -145,6 +148,9 @@ def optioninput(element, value, status, render_template, msg=''):
return
etree
.
XML
(
html
)
#-----------------------------------------------------------------------------
# TODO: consolidate choicegroup, radiogroup, checkboxgroup after discussion of
# desired semantics.
@register_render_function
def
choicegroup
(
element
,
value
,
status
,
render_template
,
msg
=
''
):
'''
...
...
@@ -160,7 +166,7 @@ def choicegroup(element, value, status, render_template, msg=''):
type
=
"checkbox"
else
:
type
=
"radio"
choices
=
{}
choices
=
[]
for
choice
in
element
:
if
not
choice
.
tag
==
'choice'
:
raise
Exception
(
"[courseware.capa.inputtypes.choicegroup] Error only <choice> tags should be immediate children of a <choicegroup>, found
%
s instead"
%
choice
.
tag
)
...
...
@@ -168,8 +174,66 @@ def choicegroup(element, value, status, render_template, msg=''):
ctext
+=
''
.
join
([
etree
.
tostring
(
x
)
for
x
in
choice
])
# TODO: what if choice[0] has math tags in it?
if
choice
.
text
is
not
None
:
ctext
+=
choice
.
text
# TODO: fix order?
choices
[
choice
.
get
(
"name"
)]
=
ctext
context
=
{
'id'
:
eid
,
'value'
:
value
,
'state'
:
status
,
'type'
:
type
,
'choices'
:
choices
}
choices
.
append
((
choice
.
get
(
"name"
),
ctext
))
context
=
{
'id'
:
eid
,
'value'
:
value
,
'state'
:
status
,
'input_type'
:
type
,
'choices'
:
choices
,
'inline'
:
True
,
'name_array_suffix'
:
''
}
html
=
render_template
(
"choicegroup.html"
,
context
)
return
etree
.
XML
(
html
)
#-----------------------------------------------------------------------------
def
extract_choices
(
element
):
'''
Extracts choices for a few input types, such as radiogroup and
checkboxgroup.
TODO: allow order of choices to be randomized, following lon-capa spec. Use "location" attribute,
ie random, top, bottom.
'''
choices
=
[]
for
choice
in
element
:
if
not
choice
.
tag
==
'choice'
:
raise
Exception
(
"[courseware.capa.inputtypes.extract_choices]
\
Expected a <choice> tag; got
%
s instead"
%
choice
.
tag
)
choice_text
=
''
.
join
([
etree
.
tostring
(
x
)
for
x
in
choice
])
choices
.
append
((
choice
.
get
(
"name"
),
choice_text
))
return
choices
# TODO: consolidate choicegroup, radiogroup, checkboxgroup after discussion of
# desired semantics.
@register_render_function
def
radiogroup
(
element
,
value
,
status
,
render_template
,
msg
=
''
):
'''
Radio button inputs: (multiple choice)
'''
eid
=
element
.
get
(
'id'
)
choices
=
extract_choices
(
element
)
context
=
{
'id'
:
eid
,
'value'
:
value
,
'state'
:
status
,
'input_type'
:
'radio'
,
'choices'
:
choices
,
'inline'
:
False
,
'name_array_suffix'
:
'[]'
}
html
=
render_template
(
"choicegroup.html"
,
context
)
return
etree
.
XML
(
html
)
# TODO: consolidate choicegroup, radiogroup, checkboxgroup after discussion of
# desired semantics.
@register_render_function
def
checkboxgroup
(
element
,
value
,
status
,
render_template
,
msg
=
''
):
'''
Checkbox inputs: (select one or more choices)
'''
eid
=
element
.
get
(
'id'
)
choices
=
extract_choices
(
element
)
context
=
{
'id'
:
eid
,
'value'
:
value
,
'state'
:
status
,
'input_type'
:
'checkbox'
,
'choices'
:
choices
,
'inline'
:
False
,
'name_array_suffix'
:
'[]'
}
html
=
render_template
(
"choicegroup.html"
,
context
)
return
etree
.
XML
(
html
)
...
...
common/lib/capa/capa/responsetypes.py
View file @
be369938
...
...
@@ -8,6 +8,7 @@ Used by capa_problem.py
'''
# standard library imports
import
hashlib
import
inspect
import
json
import
logging
...
...
@@ -16,9 +17,9 @@ import numpy
import
random
import
re
import
requests
import
time
import
traceback
import
abc
import
time
# specific library imports
from
calc
import
evaluator
,
UndefinedVariable
...
...
@@ -266,6 +267,94 @@ class LoncapaResponse(object):
return
u'LoncapaProblem Response
%
s'
%
self
.
xml
.
tag
#-----------------------------------------------------------------------------
class
ChoiceResponse
(
LoncapaResponse
):
'''
This Response type is used when the student chooses from a discrete set of
choices. Currently, to be marked correct, all "correct" choices must be
supplied by the student, and no extraneous choices may be included.
This response type allows for two inputtypes: radiogroups and checkbox
groups. radiogroups are used when the student should select a single answer,
and checkbox groups are used when the student may supply 0+ answers.
Note: it is suggested to include a "None of the above" choice when no
answer is correct for a checkboxgroup inputtype; this ensures that a student
must actively mark something to get credit.
If two choices are marked as correct with a radiogroup, the student will
have no way to get the answer right.
TODO: Allow for marking choices as 'optional' and 'required', which would
not penalize a student for including optional answers and would also allow
for questions in which the student can supply one out of a set of correct
answers.This would also allow for survey-style questions in which all
answers are correct.
Example:
<choiceresponse>
<radiogroup>
<choice correct="false">
<text>This is a wrong answer.</text>
</choice>
<choice correct="true">
<text>This is the right answer.</text>
</choice>
<choice correct="false">
<text>This is another wrong answer.</text>
</choice>
</radiogroup>
</choiceresponse>
In the above example, radiogroup can be replaced with checkboxgroup to allow
the student to select more than one choice.
'''
response_tag
=
'choiceresponse'
max_inputfields
=
1
allowed_inputfields
=
[
'checkboxgroup'
,
'radiogroup'
]
def
setup_response
(
self
):
self
.
assign_choice_names
()
correct_xml
=
self
.
xml
.
xpath
(
'//*[@id=$id]//choice[@correct="true"]'
,
id
=
self
.
xml
.
get
(
'id'
))
self
.
correct_choices
=
set
([
choice
.
get
(
'name'
)
for
choice
in
correct_xml
])
def
assign_choice_names
(
self
):
'''
Initialize name attributes in <choice> tags for this response.
'''
for
index
,
choice
in
enumerate
(
self
.
xml
.
xpath
(
'//*[@id=$id]//choice'
,
id
=
self
.
xml
.
get
(
'id'
))):
choice
.
set
(
"name"
,
"choice_"
+
str
(
index
))
def
get_score
(
self
,
student_answers
):
student_answer
=
student_answers
.
get
(
self
.
answer_id
,
[])
if
not
isinstance
(
student_answer
,
list
):
student_answer
=
[
student_answer
]
student_answer
=
set
(
student_answer
)
required_selected
=
len
(
self
.
correct_choices
-
student_answer
)
==
0
no_extra_selected
=
len
(
student_answer
-
self
.
correct_choices
)
==
0
correct
=
required_selected
&
no_extra_selected
if
correct
:
return
CorrectMap
(
self
.
answer_id
,
'correct'
)
else
:
return
CorrectMap
(
self
.
answer_id
,
'incorrect'
)
def
get_answers
(
self
):
return
{
self
.
answer_id
:
self
.
correct_choices
}
#-----------------------------------------------------------------------------
class
MultipleChoiceResponse
(
LoncapaResponse
):
# TODO: handle direction and randomize
...
...
@@ -469,13 +558,13 @@ class CustomResponse(LoncapaResponse):
or in a <script>...</script>
'''
snippets
=
[{
'snippet'
:
'''<customresponse>
<
startouttext/
>
<
text
>
<br/>
Suppose that
\
(I(t)
\
) rises from
\
(0
\
) to
\
(I_S
\
) at a time
\
(t_0
\n
eq 0
\
)
In the space provided below write an algebraic expression for
\
(I(t)
\
).
<br/>
<textline size="5" correct_answer="IS*u(t-t0)" />
<
endouttext/
>
<
/text
>
<answer type="loncapa/python">
correct=['correct']
try:
...
...
@@ -696,15 +785,19 @@ class SymbolicResponse(CustomResponse):
class
CodeResponse
(
LoncapaResponse
):
'''
Grade student code using an external server
Grade student code using an external server, called 'xqueue'
In contrast to ExternalResponse, CodeResponse has following behavior:
1) Goes through a queueing system
2) Does not do external request for 'get_answers'
'''
response_tag
=
'coderesponse'
allowed_inputfields
=
[
'textline'
,
'textbox'
]
max_inputfields
=
1
def
setup_response
(
self
):
xml
=
self
.
xml
self
.
url
=
xml
.
get
(
'url'
)
or
"http://ec2-50-16-59-149.compute-1.amazonaws.com/xqueue/submit/"
# FIXME -- hardcoded url
self
.
url
=
xml
.
get
(
'url'
,
"http://ec2-50-16-59-149.compute-1.amazonaws.com/xqueue/submit/"
)
# FIXME -- hardcoded url
answer
=
xml
.
find
(
'answer'
)
if
answer
is
not
None
:
...
...
@@ -713,33 +806,52 @@ class CodeResponse(LoncapaResponse):
self
.
code
=
self
.
system
.
filesystem
.
open
(
'src/'
+
answer_src
)
.
read
()
else
:
self
.
code
=
answer
.
text
else
:
# no <answer> stanza; get code from <script>
else
:
# no <answer> stanza; get code from <script>
self
.
code
=
self
.
context
[
'script_code'
]
if
not
self
.
code
:
msg
=
'
%
s: Missing answer script code for
external
response'
%
unicode
(
self
)
msg
=
'
%
s: Missing answer script code for
code
response'
%
unicode
(
self
)
msg
+=
"
\n
See XML source line
%
s"
%
getattr
(
self
.
xml
,
'sourceline'
,
'<unavailable>'
)
raise
LoncapaProblemError
(
msg
)
self
.
tests
=
xml
.
get
(
'tests'
)
# Extract 'answer' and 'initial_display' from XML. Note that the code to be exec'ed here is:
# (1) Internal edX code, i.e. NOT student submissions, and
# (2) The code should only define the strings 'initial_display', 'answer', 'preamble', 'test_program'
# following the 6.01 problem definition convention
penv
=
{}
penv
[
'__builtins__'
]
=
globals
()[
'__builtins__'
]
try
:
exec
(
self
.
code
,
penv
,
penv
)
except
Exception
as
err
:
log
.
error
(
'Error in CodeResponse
%
s: Error in problem reference code'
%
err
)
raise
Exception
(
err
)
try
:
self
.
answer
=
penv
[
'answer'
]
self
.
initial_display
=
penv
[
'initial_display'
]
except
Exception
as
err
:
log
.
error
(
"Error in CodeResponse
%
s: Problem reference code does not define 'answer' and/or 'initial_display' in <answer>...</answer>"
%
err
)
raise
Exception
(
err
)
def
get_score
(
self
,
student_answers
):
idset
=
sorted
(
self
.
answer_ids
)
try
:
submission
=
[
student_answers
[
k
]
for
k
in
idset
]
submission
=
[
student_answers
[
self
.
answer_id
]
]
except
Exception
as
err
:
log
.
error
(
'Error in CodeResponse
%
s: cannot get student answer for
%
s; student_answers=
%
s'
%
(
err
,
self
.
answer_id
s
,
student_answers
))
log
.
error
(
'Error in CodeResponse
%
s: cannot get student answer for
%
s; student_answers=
%
s'
%
(
err
,
self
.
answer_id
,
student_answers
))
raise
Exception
(
err
)
self
.
context
.
update
({
'submission'
:
submission
})
extra_payload
=
{
'edX_student_response'
:
json
.
dumps
(
submission
)}
# Should do something -- like update the problem state -- based on the queue response
r
=
self
.
_send_to_queue
(
extra_payload
)
return
CorrectMap
()
r
,
queuekey
=
self
.
_send_to_queue
(
extra_payload
)
# TODO: Perform checks on the xqueue response
def
update_score
(
self
,
score_msg
):
# Non-null CorrectMap['queuekey'] indicates that the problem has been submitted
cmap
=
CorrectMap
()
cmap
.
set
(
self
.
answer_id
,
queuekey
=
queuekey
,
msg
=
'Submitted to queue'
)
return
cmap
def
update_score
(
self
,
score_msg
,
oldcmap
,
queuekey
):
# Parse 'score_msg' as XML
try
:
rxml
=
etree
.
fromstring
(
score_msg
)
...
...
@@ -748,51 +860,47 @@ class CodeResponse(LoncapaResponse):
raise
Exception
(
err
)
# The following process is lifted directly from ExternalResponse
idset
=
sorted
(
self
.
answer_ids
)
cmap
=
CorrectMap
()
ad
=
rxml
.
find
(
'awarddetail'
)
.
text
admap
=
{
'EXACT_ANS'
:
'correct'
,
# TODO: handle other loncapa responses
admap
=
{
'EXACT_ANS'
:
'correct'
,
# TODO: handle other loncapa responses
'WRONG_FORMAT'
:
'incorrect'
,
}
self
.
context
[
'correct'
]
=
[
'correct'
]
if
ad
in
admap
:
self
.
context
[
'correct'
][
0
]
=
admap
[
ad
]
# create CorrectMap
for
key
in
idset
:
idx
=
idset
.
index
(
key
)
msg
=
rxml
.
find
(
'message'
)
.
text
.
replace
(
' '
,
' '
)
if
idx
==
0
else
None
cmap
.
set
(
key
,
self
.
context
[
'correct'
][
idx
],
msg
=
msg
)
return
cmap
# Replace 'oldcmap' with new grading results if queuekey matches.
# If queuekey does not match, we keep waiting for the score_msg that will match
if
oldcmap
.
is_right_queuekey
(
self
.
answer_id
,
queuekey
):
msg
=
rxml
.
find
(
'message'
)
.
text
.
replace
(
' '
,
' '
)
oldcmap
.
set
(
self
.
answer_id
,
correctness
=
self
.
context
[
'correct'
][
0
],
msg
=
msg
,
queuekey
=
None
)
# Queuekey is consumed
else
:
log
.
debug
(
'CodeResponse: queuekey
%
d does not match for answer_id=
%
s.'
%
(
queuekey
,
self
.
answer_id
))
return
oldcmap
# CodeResponse differentiates from ExternalResponse in the behavior of 'get_answers'. CodeResponse.get_answers
# does NOT require a queue submission, and the answer is computed (extracted from problem XML) locally.
def
get_answers
(
self
):
# Extract the CodeResponse answer from XML
penv
=
{}
penv
[
'__builtins__'
]
=
globals
()[
'__builtins__'
]
try
:
exec
(
self
.
code
,
penv
,
penv
)
except
Exception
as
err
:
log
.
error
(
'Error in CodeResponse
%
s: Error in problem reference code'
%
err
)
raise
Exception
(
err
)
try
:
ans
=
penv
[
'answer'
]
except
Exception
as
err
:
log
.
error
(
'Error in CodeResponse
%
s: Problem reference code does not define answer in <answer>...</answer>'
%
err
)
raise
Exception
(
err
)
anshtml
=
'<font color="blue"><span class="code-answer"><br/><pre>
%
s</pre><br/></span></font>'
%
ans
return
dict
(
zip
(
self
.
answer_ids
,[
anshtml
]))
anshtml
=
'<font color="blue"><span class="code-answer"><br/><pre>
%
s</pre><br/></span></font>'
%
self
.
answer
return
{
self
.
answer_id
:
anshtml
}
def
get_initial_display
(
self
):
return
{
self
.
answer_id
:
self
.
initial_display
}
# CodeResponse._send_to_queue implements the same interface as defined for ExternalResponse's 'get_score'
def
_send_to_queue
(
self
,
extra_payload
):
# Prepare payload
xmlstr
=
etree
.
tostring
(
self
.
xml
,
pretty_print
=
True
)
header
=
{
'return_url'
:
self
.
system
.
xqueue_callback_url
}
header
.
update
({
'timestamp'
:
time
.
time
()})
payload
=
{
'xqueue_header'
:
json
.
dumps
(
header
),
# 'xqueue_header' should eventually be derived from xqueue.queue_common.HEADER_TAG or something similar
# Queuekey generation
h
=
hashlib
.
md5
()
h
.
update
(
str
(
self
.
system
.
seed
))
h
.
update
(
str
(
time
.
time
()))
queuekey
=
int
(
h
.
hexdigest
(),
16
)
header
.
update
({
'queuekey'
:
queuekey
})
payload
=
{
'xqueue_header'
:
json
.
dumps
(
header
),
# TODO: 'xqueue_header' should eventually be derived from a config file
'xml'
:
xmlstr
,
'edX_cmd'
:
'get_score'
,
'edX_tests'
:
self
.
tests
,
...
...
@@ -808,7 +916,7 @@ class CodeResponse(LoncapaResponse):
log
.
error
(
msg
)
raise
Exception
(
msg
)
return
r
return
r
,
queuekey
#-----------------------------------------------------------------------------
...
...
@@ -1191,5 +1299,5 @@ class ImageResponse(LoncapaResponse):
# TEMPORARY: List of all response subclasses
# FIXME: To be replaced by auto-registration
__all__
=
[
CodeResponse
,
NumericalResponse
,
FormulaResponse
,
CustomResponse
,
SchematicResponse
,
MultipleChoiceResponse
,
TrueFalseResponse
,
ExternalResponse
,
ImageResponse
,
OptionResponse
,
SymbolicResponse
,
String
Response
]
__all__
=
[
CodeResponse
,
NumericalResponse
,
FormulaResponse
,
CustomResponse
,
SchematicResponse
,
ExternalResponse
,
ImageResponse
,
OptionResponse
,
SymbolicResponse
,
StringResponse
,
ChoiceResponse
,
MultipleChoiceResponse
,
TrueFalse
Response
]
common/lib/capa/capa/templates/choicegroup.html
View file @
be369938
<form
class=
"
multiple-choice
"
>
<form
class=
"
choicegroup
"
>
% for choice_id, choice_description in choices
.items()
:
<label
for=
"input_${id}_${choice_id}"
>
<input
type=
"${
type}"
name=
"input_${id
}"
id=
"input_${id}_${choice_id}"
value=
"${choice_id}"
% for choice_id, choice_description in choices:
<label
for=
"input_${id}_${choice_id}"
>
<input
type=
"${
input_type}"
name=
"input_${id}${name_array_suffix
}"
id=
"input_${id}_${choice_id}"
value=
"${choice_id}"
%
if
choice_id
in
value:
checked=
"true"
%
endif
/>
${choice_description}
</label>
% if not inline:
<br/>
% endif
% endfor
<span
id=
"answer_${id}"
></span>
...
...
lms
/templates/optioninput.html
→
common/lib/capa/capa
/templates/optioninput.html
View file @
be369938
...
...
@@ -2,7 +2,7 @@
<select
name=
"input_${id}"
id=
"input_${id}"
>
<option
value=
"option_${id}_dummy_default"
>
</option>
% for option_id, option_description in options
.items()
:
% for option_id, option_description in options:
<option
value=
"${option_id}"
%
if
(
option_id=
=value):
selected=
"true"
...
...
common/lib/xmodule/tests/__init__.py
View file @
be369938
...
...
@@ -13,6 +13,7 @@ import numpy
import
xmodule
import
capa.calc
as
calc
import
capa.capa_problem
as
lcp
from
capa.correctmap
import
CorrectMap
from
xmodule
import
graders
,
x_module
from
xmodule.graders
import
Score
,
aggregate_scores
from
xmodule.progress
import
Progress
...
...
@@ -271,6 +272,86 @@ class StringResponseWithHintTest(unittest.TestCase):
self
.
assertEquals
(
cmap
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
self
.
assertTrue
(
'St. Paul'
in
cmap
.
get_hint
(
'1_2_1'
))
class
CodeResponseTest
(
unittest
.
TestCase
):
'''
Test CodeResponse
'''
def
test_update_score
(
self
):
problem_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/coderesponse.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
problem_file
)
.
read
(),
'1'
,
system
=
i4xs
)
# CodeResponse requires internal CorrectMap state. Build it now in the 'queued' state
old_cmap
=
CorrectMap
()
answer_ids
=
sorted
(
test_lcp
.
get_question_answers
()
.
keys
())
numAnswers
=
len
(
answer_ids
)
for
i
in
range
(
numAnswers
):
old_cmap
.
update
(
CorrectMap
(
answer_id
=
answer_ids
[
i
],
queuekey
=
1000
+
i
))
# Message format inherited from ExternalResponse
correct_score_msg
=
"<edxgrade><awarddetail>EXACT_ANS</awarddetail><message>MESSAGE</message></edxgrade>"
incorrect_score_msg
=
"<edxgrade><awarddetail>WRONG_FORMAT</awarddetail><message>MESSAGE</message></edxgrade>"
xserver_msgs
=
{
'correct'
:
correct_score_msg
,
'incorrect'
:
incorrect_score_msg
,
}
# Incorrect queuekey, state should not be updated
for
correctness
in
[
'correct'
,
'incorrect'
]:
test_lcp
.
correct_map
=
CorrectMap
()
test_lcp
.
correct_map
.
update
(
old_cmap
)
# Deep copy
test_lcp
.
update_score
(
xserver_msgs
[
correctness
],
queuekey
=
0
)
self
.
assertEquals
(
test_lcp
.
correct_map
.
get_dict
(),
old_cmap
.
get_dict
())
# Deep comparison
for
i
in
range
(
numAnswers
):
self
.
assertTrue
(
test_lcp
.
correct_map
.
is_queued
(
answer_ids
[
i
]))
# Should be still queued, since message undelivered
# Correct queuekey, state should be updated
for
correctness
in
[
'correct'
,
'incorrect'
]:
for
i
in
range
(
numAnswers
):
# Target specific answer_id's
test_lcp
.
correct_map
=
CorrectMap
()
test_lcp
.
correct_map
.
update
(
old_cmap
)
new_cmap
=
CorrectMap
()
new_cmap
.
update
(
old_cmap
)
new_cmap
.
set
(
answer_id
=
answer_ids
[
i
],
correctness
=
correctness
,
msg
=
'MESSAGE'
,
queuekey
=
None
)
test_lcp
.
update_score
(
xserver_msgs
[
correctness
],
queuekey
=
1000
+
i
)
self
.
assertEquals
(
test_lcp
.
correct_map
.
get_dict
(),
new_cmap
.
get_dict
())
for
j
in
range
(
numAnswers
):
if
j
==
i
:
self
.
assertFalse
(
test_lcp
.
correct_map
.
is_queued
(
answer_ids
[
j
]))
# Should be dequeued, message delivered
else
:
self
.
assertTrue
(
test_lcp
.
correct_map
.
is_queued
(
answer_ids
[
j
]))
# Should be queued, message undelivered
class
ChoiceResponseTest
(
unittest
.
TestCase
):
def
test_cr_rb_grade
(
self
):
problem_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/choiceresponse_radio.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
problem_file
)
.
read
(),
'1'
,
system
=
i4xs
)
correct_answers
=
{
'1_2_1'
:
'choice_2'
,
'1_3_1'
:[
'choice_2'
,
'choice_3'
]}
test_answers
=
{
'1_2_1'
:
'choice_2'
,
'1_3_1'
:
'choice_2'
,
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_3_1'
),
'incorrect'
)
def
test_cr_cb_grade
(
self
):
problem_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/choiceresponse_checkbox.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
problem_file
)
.
read
(),
'1'
,
system
=
i4xs
)
correct_answers
=
{
'1_2_1'
:
'choice_2'
,
'1_3_1'
:[
'choice_2'
,
'choice_3'
],
'1_4_1'
:[
'choice_2'
,
'choice_3'
]}
test_answers
=
{
'1_2_1'
:
'choice_2'
,
'1_3_1'
:
'choice_2'
,
'1_4_1'
:[
'choice_2'
,
'choice_3'
],
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_3_1'
),
'incorrect'
)
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_4_1'
),
'correct'
)
#-----------------------------------------------------------------------------
# Grading tests
...
...
common/lib/xmodule/tests/test_files/choiceresponse_checkbox.xml
0 → 100644
View file @
be369938
<problem>
<choiceresponse>
<checkboxgroup>
<choice
correct=
"false"
>
<startouttext
/>
This is foil One.
<endouttext
/>
</choice>
<choice
correct=
"false"
>
<startouttext
/>
This is foil Two.
<endouttext
/>
</choice>
<choice
correct=
"true"
>
<startouttext
/>
This is foil Three.
<endouttext
/>
</choice>
<choice
correct=
"false"
>
<startouttext
/>
This is foil Four.
<endouttext
/>
</choice>
<choice
correct=
"false"
>
<startouttext
/>
This is foil Five.
<endouttext
/>
</choice>
</checkboxgroup>
</choiceresponse>
<choiceresponse>
<checkboxgroup>
<choice
correct=
"false"
>
<startouttext
/>
This is foil One.
<endouttext
/>
</choice>
<choice
correct=
"false"
>
<startouttext
/>
This is foil Two.
<endouttext
/>
</choice>
<choice
correct=
"true"
>
<startouttext
/>
This is foil Three.
<endouttext
/>
</choice>
<choice
correct=
"true"
>
<startouttext
/>
This is foil Four.
<endouttext
/>
</choice>
<choice
correct=
"false"
>
<startouttext
/>
This is foil Five.
<endouttext
/>
</choice>
</checkboxgroup>
</choiceresponse>
<choiceresponse>
<checkboxgroup>
<choice
correct=
"false"
>
<startouttext
/>
This is foil One.
<endouttext
/>
</choice>
<choice
correct=
"false"
>
<startouttext
/>
This is foil Two.
<endouttext
/>
</choice>
<choice
correct=
"true"
>
<startouttext
/>
This is foil Three.
<endouttext
/>
</choice>
<choice
correct=
"true"
>
<startouttext
/>
This is foil Four.
<endouttext
/>
</choice>
<choice
correct=
"false"
>
<startouttext
/>
This is foil Five.
<endouttext
/>
</choice>
</checkboxgroup>
</choiceresponse>
</problem>
common/lib/xmodule/tests/test_files/choiceresponse_radio.xml
0 → 100644
View file @
be369938
<problem>
<choiceresponse>
<radiogroup>
<choice
correct=
"false"
>
<startouttext
/>
This is foil One.
<endouttext
/>
</choice>
<choice
correct=
"false"
>
<startouttext
/>
This is foil Two.
<endouttext
/>
</choice>
<choice
correct=
"true"
>
<startouttext
/>
This is foil Three.
<endouttext
/>
</choice>
<choice
correct=
"false"
>
<startouttext
/>
This is foil Four.
<endouttext
/>
</choice>
<choice
correct=
"false"
>
<startouttext
/>
This is foil Five.
<endouttext
/>
</choice>
</radiogroup>
</choiceresponse>
<choiceresponse>
<radiogroup>
<choice
correct=
"false"
>
<startouttext
/>
This is foil One.
<endouttext
/>
</choice>
<choice
correct=
"false"
>
<startouttext
/>
This is foil Two.
<endouttext
/>
</choice>
<choice
correct=
"true"
>
<startouttext
/>
This is foil Three.
<endouttext
/>
</choice>
<choice
correct=
"true"
>
<startouttext
/>
This is foil Four.
<endouttext
/>
</choice>
<choice
correct=
"false"
>
<startouttext
/>
This is foil Five.
<endouttext
/>
</choice>
</radiogroup>
</choiceresponse>
</problem>
common/lib/xmodule/tests/test_files/coderesponse.xml
0 → 100644
View file @
be369938
<problem>
<text>
<h2>
Code response
</h2>
<p>
</p>
<text>
Write a program to compute the square of a number
<coderesponse
tests=
"repeat:2,generate"
>
<textbox
rows=
"10"
cols=
"70"
mode=
"python"
/>
<answer>
<![CDATA[
initial_display = """
def square(n):
"""
answer = """
def square(n):
return n**2
"""
preamble = """
import sys, time
"""
test_program = """
import random
import operator
def testSquare(n = None):
if n is None:
n = random.randint(2, 20)
print 'Test is: square(%d)'%n
return str(square(n))
def main():
f = os.fdopen(3,'w')
test = int(sys.argv[1])
rndlist = map(int,os.getenv('rndlist').split(','))
random.seed(rndlist[0])
if test == 1: f.write(testSquare(0))
elif test == 2: f.write(testSquare(1))
else: f.write(testSquare())
f.close()
main()
sys.exit(0)
"""
]]>
</answer>
</coderesponse>
</text>
<text>
Write a program to compute the cube of a number
<coderesponse
tests=
"repeat:2,generate"
>
<textbox
rows=
"10"
cols=
"70"
mode=
"python"
/>
<answer>
<![CDATA[
initial_display = """
def cube(n):
"""
answer = """
def cube(n):
return n**3
"""
preamble = """
import sys, time
"""
test_program = """
import random
import operator
def testCube(n = None):
if n is None:
n = random.randint(2, 20)
print 'Test is: cube(%d)'%n
return str(cube(n))
def main():
f = os.fdopen(3,'w')
test = int(sys.argv[1])
rndlist = map(int,os.getenv('rndlist').split(','))
random.seed(rndlist[0])
if test == 1: f.write(testCube(0))
elif test == 2: f.write(testCube(1))
else: f.write(testCube())
f.close()
main()
sys.exit(0)
"""
]]>
</answer>
</coderesponse>
</text>
</text>
</problem>
common/lib/xmodule/xmodule/capa_module.py
View file @
be369938
...
...
@@ -323,8 +323,18 @@ class CapaModule(XModule):
raise
self
.
system
.
exception404
def
update_score
(
self
,
get
):
"""
Delivers grading response (e.g. from asynchronous code checking) to
the capa problem, so its score can be updated
'get' must have a field 'response' which is a string that contains the
grader's response
No ajax return is needed. Return empty dict.
"""
queuekey
=
get
[
'queuekey'
]
score_msg
=
get
[
'response'
]
self
.
lcp
.
update_score
(
score_msg
)
self
.
lcp
.
update_score
(
score_msg
,
queuekey
)
return
dict
()
# No AJAX return is needed
...
...
@@ -361,7 +371,16 @@ class CapaModule(XModule):
for
key
in
get
:
# e.g. input_resistor_1 ==> resistor_1
_
,
_
,
name
=
key
.
partition
(
'_'
)
answers
[
name
]
=
get
[
key
]
# This allows for answers which require more than one value for
# the same form input (e.g. checkbox inputs). The convention is that
# if the name ends with '[]' (which looks like an array), then the
# answer will be an array.
if
not
name
.
endswith
(
'[]'
):
answers
[
name
]
=
get
[
key
]
else
:
name
=
name
[:
-
2
]
answers
[
name
]
=
get
.
getlist
(
key
)
return
answers
...
...
@@ -424,7 +443,8 @@ class CapaModule(XModule):
if
not
correct_map
.
is_correct
(
answer_id
):
success
=
'incorrect'
# log this in the track_function
# NOTE: We are logging both full grading and queued-grading submissions. In the latter,
# 'success' will always be incorrect
event_info
[
'correct_map'
]
=
correct_map
.
get_dict
()
event_info
[
'success'
]
=
success
self
.
system
.
track_function
(
'save_problem_check'
,
event_info
)
...
...
common/lib/xmodule/xmodule/seq_module.py
View file @
be369938
...
...
@@ -81,7 +81,7 @@ class SequenceModule(XModule):
# of script, even if it occurs mid-string. Do this after json.dumps()ing
# so that we can be sure of the quotations being used
import
re
params
=
{
'items'
:
re
.
sub
(
r'
</(script)'
,
r'\u003c/\1'
,
json
.
dumps
(
contents
),
flags
=
re
.
IGNORECASE
),
params
=
{
'items'
:
re
.
sub
(
r'
(?i)</(script)'
,
r'\u003c/\1'
,
json
.
dumps
(
contents
)),
# ?i = re.IGNORECASE for py2.6 compatability
'element_id'
:
self
.
location
.
html_id
(),
'item_id'
:
self
.
id
,
'position'
:
self
.
position
,
...
...
lms/djangoapps/courseware/module_render.py
View file @
be369938
...
...
@@ -4,8 +4,10 @@ import logging
from
django.conf
import
settings
from
django.http
import
Http404
from
django.http
import
HttpResponse
from
django.views.decorators.csrf
import
csrf_exempt
from
functools
import
wraps
from
django.contrib.auth.models
import
User
from
xmodule.modulestore.django
import
modulestore
from
mitxmako.shortcuts
import
render_to_string
from
models
import
StudentModule
,
StudentModuleCache
...
...
@@ -33,6 +35,8 @@ class I4xSystem(object):
Create a closure around the system environment.
ajax_url - the url where ajax calls to the encapsulating module go.
xqueue_callback_url - the url where external queueing system (e.g. for grading)
returns its response
track_function - function of (event_type, event), intended for logging
or otherwise tracking the event.
TODO: Not used, and has inconsistent args in different
...
...
@@ -208,7 +212,7 @@ def get_module(user, request, location, student_module_cache, position=None):
# Setup system context for module instance
ajax_url
=
settings
.
MITX_ROOT_URL
+
'/modx/'
+
descriptor
.
location
.
url
()
+
'/'
xqueue_callback_url
=
settings
.
MITX_ROOT_URL
+
'/xqueue/'
+
user
.
username
+
'/'
+
descriptor
.
location
.
url
()
+
'/'
xqueue_callback_url
=
settings
.
MITX_ROOT_URL
+
'/xqueue/'
+
str
(
user
.
id
)
+
'/'
+
descriptor
.
location
.
url
()
+
'/'
def
_get_module
(
location
):
(
module
,
_
,
_
,
_
)
=
get_module
(
user
,
request
,
location
,
student_module_cache
,
position
)
...
...
@@ -324,11 +328,9 @@ def add_histogram(module):
module
.
get_html
=
get_html
return
module
# THK: TEMPORARY BYPASS OF AUTH!
from
django.views.decorators.csrf
import
csrf_exempt
from
django.contrib.auth.models
import
User
# TODO: TEMPORARY BYPASS OF AUTH!
@csrf_exempt
def
xqueue_callback
(
request
,
user
name
,
id
,
dispatch
):
def
xqueue_callback
(
request
,
user
id
,
id
,
dispatch
):
# Parse xqueue response
get
=
request
.
POST
.
copy
()
try
:
...
...
@@ -336,12 +338,9 @@ def xqueue_callback(request, username, id, dispatch):
except
Exception
as
err
:
msg
=
"Error in xqueue_callback
%
s: Invalid return format"
%
err
raise
Exception
(
msg
)
# Should proceed only when the request timestamp is more recent than problem timestamp
timestamp
=
header
[
'timestamp'
]
# Retrieve target StudentModule
user
=
User
.
objects
.
get
(
username
=
username
)
user
=
User
.
objects
.
get
(
id
=
userid
)
student_module_cache
=
StudentModuleCache
(
user
,
modulestore
()
.
get_item
(
id
))
instance
,
instance_module
,
shared_module
,
module_type
=
get_module
(
request
.
user
,
request
,
id
,
student_module_cache
)
...
...
@@ -354,6 +353,10 @@ def xqueue_callback(request, username, id, dispatch):
oldgrade
=
instance_module
.
grade
old_instance_state
=
instance_module
.
state
# Transfer 'queuekey' from xqueue response header to 'get'. This is required to
# use the interface defined by 'handle_ajax'
get
.
update
({
'queuekey'
:
header
[
'queuekey'
]})
# We go through the "AJAX" path
# So far, the only dispatch from xqueue will be 'score_update'
try
:
...
...
lms/static/sass/marketing-ie.css
0 → 100755
View file @
be369938
body
{
margin
:
0
;
padding
:
0
;
}
.wrapper
,
.subpage
,
section
.copyright
,
section
.tos
,
section
.privacy-policy
,
section
.honor-code
,
header
.announcement
div
,
section
.index-content
,
footer
{
margin
:
0
;
overflow
:
hidden
;
}
div
#enroll
form
{
display
:
none
;
}
lms/static/sass/marketing.css
0 → 100755
View file @
be369938
/*
html5doctor.com Reset Stylesheet
v1.6.1
Last Updated: 2010-09-17
Author: Richard Clark - http://richclarkdesign.com
Twitter: @rich_clark
*/
html
,
body
,
div
,
span
,
object
,
iframe
,
h1
,
h2
,
h3
,
h4
,
h5
,
h6
,
p
,
blockquote
,
pre
,
abbr
,
address
,
cite
,
code
,
del
,
dfn
,
em
,
img
,
ins
,
kbd
,
q
,
samp
,
small
,
strong
,
var
,
b
,
i
,
dl
,
dt
,
dd
,
ol
,
ul
,
li
,
fieldset
,
form
,
label
,
legend
,
table
,
caption
,
tbody
,
tfoot
,
thead
,
tr
,
th
,
td
,
article
,
aside
,
canvas
,
details
,
figcaption
,
figure
,
footer
,
header
,
hgroup
,
menu
,
nav
,
section
,
summary
,
time
,
mark
,
audio
,
video
{
margin
:
0
;
padding
:
0
;
border
:
0
;
outline
:
0
;
font-size
:
100%
;
vertical-align
:
baseline
;
background
:
transparent
;
}
body
{
line-height
:
1
;
}
article
,
aside
,
details
,
figcaption
,
figure
,
footer
,
header
,
hgroup
,
menu
,
nav
,
section
{
display
:
block
;
}
nav
ul
{
list-style
:
none
;
}
blockquote
,
q
{
quotes
:
none
;
}
blockquote
:before
,
blockquote
:after
,
q
:before
,
q
:after
{
content
:
''
;
content
:
none
;
}
a
{
margin
:
0
;
padding
:
0
;
font-size
:
100%
;
vertical-align
:
baseline
;
background
:
transparent
;
}
/* change colours to suit your needs */
ins
{
background-color
:
#ff9
;
color
:
#000
;
text-decoration
:
none
;
}
/* change colours to suit your needs */
mark
{
background-color
:
#ff9
;
color
:
#000
;
font-style
:
italic
;
font-weight
:
bold
;
}
del
{
text-decoration
:
line-through
;
}
abbr
[
title
],
dfn
[
title
]
{
border-bottom
:
1px
dotted
;
cursor
:
help
;
}
table
{
border-collapse
:
collapse
;
border-spacing
:
0
;
}
/* change border colour to suit your needs */
hr
{
display
:
block
;
height
:
1px
;
border
:
0
;
border-top
:
1px
solid
#cccccc
;
margin
:
1em
0
;
padding
:
0
;
}
input
,
select
{
vertical-align
:
middle
;
}
/* Generated by Font Squirrel (http://www.fontsquirrel.com) on January 25, 2012 05:06:34 PM America/New_York */
@font-face
{
font-family
:
'Open Sans'
;
src
:
url("../fonts/OpenSans-Regular-webfont.eot")
;
src
:
url("../fonts/OpenSans-Regular-webfont.eot?#iefix")
format
(
"embedded-opentype"
),
url("../fonts/OpenSans-Regular-webfont.woff")
format
(
"woff"
),
url("../fonts/OpenSans-Regular-webfont.ttf")
format
(
"truetype"
),
url("../fonts/OpenSans-Regular-webfont.svg#OpenSansRegular")
format
(
"svg"
);
font-weight
:
600
;
font-style
:
normal
;
}
@font-face
{
font-family
:
'Open Sans'
;
src
:
url("../fonts/OpenSans-Italic-webfont.eot")
;
src
:
url("../fonts/OpenSans-Italic-webfont.eot?#iefix")
format
(
"embedded-opentype"
),
url("../fonts/OpenSans-Italic-webfont.woff")
format
(
"woff"
),
url("../fonts/OpenSans-Italic-webfont.ttf")
format
(
"truetype"
),
url("../fonts/OpenSans-Italic-webfont.svg#OpenSansItalic")
format
(
"svg"
);
font-weight
:
400
;
font-style
:
italic
;
}
@font-face
{
font-family
:
'Open Sans'
;
src
:
url("../fonts/OpenSans-Bold-webfont.eot")
;
src
:
url("../fonts/OpenSans-Bold-webfont.eot?#iefix")
format
(
"embedded-opentype"
),
url("../fonts/OpenSans-Bold-webfont.woff")
format
(
"woff"
),
url("../fonts/OpenSans-Bold-webfont.ttf")
format
(
"truetype"
),
url("../fonts/OpenSans-Bold-webfont.svg#OpenSansBold")
format
(
"svg"
);
font-weight
:
700
;
font-style
:
normal
;
}
@font-face
{
font-family
:
'Open Sans'
;
src
:
url("../fonts/OpenSans-BoldItalic-webfont.eot")
;
src
:
url("../fonts/OpenSans-BoldItalic-webfont.eot?#iefix")
format
(
"embedded-opentype"
),
url("../fonts/OpenSans-BoldItalic-webfont.woff")
format
(
"woff"
),
url("../fonts/OpenSans-BoldItalic-webfont.ttf")
format
(
"truetype"
),
url("../fonts/OpenSans-BoldItalic-webfont.svg#OpenSansBoldItalic")
format
(
"svg"
);
font-weight
:
700
;
font-style
:
italic
;
}
@font-face
{
font-family
:
'Open Sans'
;
src
:
url("../fonts/OpenSans-ExtraBold-webfont.eot")
;
src
:
url("../fonts/OpenSans-ExtraBold-webfont.eot?#iefix")
format
(
"embedded-opentype"
),
url("../fonts/OpenSans-ExtraBold-webfont.woff")
format
(
"woff"
),
url("../fonts/OpenSans-ExtraBold-webfont.ttf")
format
(
"truetype"
),
url("../fonts/OpenSans-ExtraBold-webfont.svg#OpenSansExtrabold")
format
(
"svg"
);
font-weight
:
800
;
font-style
:
normal
;
}
@font-face
{
font-family
:
'Open Sans'
;
src
:
url("../fonts/OpenSans-ExtraBoldItalic-webfont.eot")
;
src
:
url("../fonts/OpenSans-ExtraBoldItalic-webfont.eot?#iefix")
format
(
"embedded-opentype"
),
url("../fonts/OpenSans-ExtraBoldItalic-webfont.woff")
format
(
"woff"
),
url("../fonts/OpenSans-ExtraBoldItalic-webfont.ttf")
format
(
"truetype"
),
url("../fonts/OpenSans-ExtraBoldItalic-webfont.svg#OpenSansExtraboldItalic")
format
(
"svg"
);
font-weight
:
800
;
font-style
:
italic
;
}
.wrapper
,
.subpage
,
section
.copyright
,
section
.tos
,
section
.privacy-policy
,
section
.honor-code
,
header
.announcement
div
,
footer
,
section
.index-content
{
-webkit-box-sizing
:
border-box
;
-moz-box-sizing
:
border-box
;
box-sizing
:
border-box
;
margin
:
0
auto
;
max-width
:
1400px
;
padding
:
25.888px
;
width
:
100%
;
}
.subpage
>
div
,
section
.copyright
>
div
,
section
.tos
>
div
,
section
.privacy-policy
>
div
,
section
.honor-code
>
div
{
padding-left
:
34.171%
;
}
@media
screen
and
(
max-width
:
940px
)
{
.subpage
>
div
,
section
.copyright
>
div
,
section
.tos
>
div
,
section
.privacy-policy
>
div
,
section
.honor-code
>
div
{
padding-left
:
0
;
}
}
.subpage
>
div
p
,
section
.copyright
>
div
p
,
section
.tos
>
div
p
,
section
.privacy-policy
>
div
p
,
section
.honor-code
>
div
p
{
margin-bottom
:
25.888px
;
line-height
:
25.888px
;
}
.subpage
>
div
h1
,
section
.copyright
>
div
h1
,
section
.tos
>
div
h1
,
section
.privacy-policy
>
div
h1
,
section
.honor-code
>
div
h1
{
margin-bottom
:
12.944px
;
}
.subpage
>
div
h2
,
section
.copyright
>
div
h2
,
section
.tos
>
div
h2
,
section
.privacy-policy
>
div
h2
,
section
.honor-code
>
div
h2
{
font
:
18px
"Open Sans"
,
Helvetica
,
Arial
,
sans-serif
;
color
:
#000
;
margin-bottom
:
12.944px
;
}
.subpage
>
div
ul
,
section
.copyright
>
div
ul
,
section
.tos
>
div
ul
,
section
.privacy-policy
>
div
ul
,
section
.honor-code
>
div
ul
{
list-style
:
disc
outside
none
;
}
.subpage
>
div
ul
li
,
section
.copyright
>
div
ul
li
,
section
.tos
>
div
ul
li
,
section
.privacy-policy
>
div
ul
li
,
section
.honor-code
>
div
ul
li
{
list-style
:
disc
outside
none
;
line-height
:
25.888px
;
}
.subpage
>
div
dl
,
section
.copyright
>
div
dl
,
section
.tos
>
div
dl
,
section
.privacy-policy
>
div
dl
,
section
.honor-code
>
div
dl
{
margin-bottom
:
25.888px
;
}
.subpage
>
div
dl
dd
,
section
.copyright
>
div
dl
dd
,
section
.tos
>
div
dl
dd
,
section
.privacy-policy
>
div
dl
dd
,
section
.honor-code
>
div
dl
dd
{
margin-bottom
:
12.944px
;
}
.clearfix
:after
,
.subpage
:after
,
section
.copyright
:after
,
section
.tos
:after
,
section
.privacy-policy
:after
,
section
.honor-code
:after
,
header
.announcement
div
section
:after
,
footer
:after
,
section
.index-content
:after
,
section
.index-content
section
:after
,
section
.index-content
section
.about
section
:after
,
div
.leanModal_box
#enroll
ol
:after
{
content
:
"."
;
display
:
block
;
height
:
0
;
clear
:
both
;
visibility
:
hidden
;
}
.button
,
header
.announcement
div
section
.course
section
a
,
section
.index-content
section
.course
a
,
section
.index-content
section
.staff
a
,
section
.index-content
section
.about-course
section
.cta
a
.enroll
{
-webkit-border-radius
:
3px
;
-moz-border-radius
:
3px
;
-ms-border-radius
:
3px
;
-o-border-radius
:
3px
;
border-radius
:
3px
;
display
:
-moz-inline-box
;
-moz-box-orient
:
vertical
;
display
:
inline-block
;
vertical-align
:
baseline
;
zoom
:
1
;
*
display
:
inline
;
*
vertical-align
:
auto
;
-webkit-transition-property
:
all
;
-moz-transition-property
:
all
;
-ms-transition-property
:
all
;
-o-transition-property
:
all
;
transition-property
:
all
;
-webkit-transition-duration
:
0.15s
;
-moz-transition-duration
:
0.15s
;
-ms-transition-duration
:
0.15s
;
-o-transition-duration
:
0.15s
;
transition-duration
:
0.15s
;
-webkit-transition-timing-function
:
ease-out
;
-moz-transition-timing-function
:
ease-out
;
-ms-transition-timing-function
:
ease-out
;
-o-transition-timing-function
:
ease-out
;
transition-timing-function
:
ease-out
;
-webkit-transition-delay
:
0
;
-moz-transition-delay
:
0
;
-ms-transition-delay
:
0
;
-o-transition-delay
:
0
;
transition-delay
:
0
;
background-color
:
#993333
;
border
:
1px
solid
#732626
;
color
:
#fff
;
margin
:
25.888px
0
12.944px
;
padding
:
6.472px
12.944px
;
text-decoration
:
none
;
font-style
:
normal
;
-webkit-box-shadow
:
inset
0
1px
0
#b83d3d
;
-moz-box-shadow
:
inset
0
1px
0
#b83d3d
;
box-shadow
:
inset
0
1px
0
#b83d3d
;
-webkit-font-smoothing
:
antialiased
;
}
.button
:hover
,
header
.announcement
div
section
.course
section
a
:hover
,
section
.index-content
section
.course
a
:hover
,
section
.index-content
section
.staff
a
:hover
,
section
.index-content
section
.about-course
section
.cta
a
.enroll
:hover
{
background-color
:
#732626
;
border-color
:
#4d1919
;
}
.button
span
,
header
.announcement
div
section
.course
section
a
span
,
section
.index-content
section
.course
a
span
,
section
.index-content
section
.staff
a
span
,
section
.index-content
section
.about-course
section
.cta
a
.enroll
span
{
font-family
:
Garamond
,
Baskerville
,
"Baskerville Old Face"
,
"Hoefler Text"
,
"Times New Roman"
,
serif
;
font-style
:
italic
;
}
p
.ie-warning
{
display
:
block
!important
;
line-height
:
1.3em
;
background
:
yellow
;
margin-bottom
:
25.888px
;
padding
:
25.888px
;
}
body
{
background-color
:
#fff
;
color
:
#444
;
font
:
16px
Georgia
,
serif
;
}
body
:focus
{
outline-color
:
#ccc
;
}
body
h1
{
font
:
800
24px
"Open Sans"
,
Helvetica
,
Arial
,
sans-serif
;
}
body
li
{
margin-bottom
:
25.888px
;
}
body
em
{
font-style
:
italic
;
}
body
a
{
color
:
#993333
;
font-style
:
italic
;
text-decoration
:
none
;
}
body
a
:hover
,
body
a
:focus
{
color
:
#732626
;
}
body
input
[
type
=
"email"
],
body
input
[
type
=
"number"
],
body
input
[
type
=
"password"
],
body
input
[
type
=
"search"
],
body
input
[
type
=
"tel"
],
body
input
[
type
=
"text"
],
body
input
[
type
=
"url"
],
body
input
[
type
=
"color"
],
body
input
[
type
=
"date"
],
body
input
[
type
=
"datetime"
],
body
input
[
type
=
"datetime-local"
],
body
input
[
type
=
"month"
],
body
input
[
type
=
"time"
],
body
input
[
type
=
"week"
],
body
textarea
{
-webkit-box-shadow
:
0
-1px
0
white
;
-moz-box-shadow
:
0
-1px
0
white
;
box-shadow
:
0
-1px
0
white
;
background-color
:
#eeeeee
;
background-image
:
-webkit-gradient
(
linear
,
left
top
,
left
bottom
,
color-stop
(
0%
,
#eeeeee
),
color-stop
(
100%
,
white
));
background-image
:
-webkit-linear-gradient
(
top
,
#eeeeee
,
white
);
background-image
:
-moz-linear-gradient
(
top
,
#eeeeee
,
white
);
background-image
:
-ms-linear-gradient
(
top
,
#eeeeee
,
white
);
background-image
:
-o-linear-gradient
(
top
,
#eeeeee
,
white
);
background-image
:
linear-gradient
(
top
,
#eeeeee
,
white
);
border
:
1px
solid
#999
;
font
:
16px
Georgia
,
serif
;
padding
:
4px
;
width
:
100%
;
}
body
input
[
type
=
"email"
]
:focus
,
body
input
[
type
=
"number"
]
:focus
,
body
input
[
type
=
"password"
]
:focus
,
body
input
[
type
=
"search"
]
:focus
,
body
input
[
type
=
"tel"
]
:focus
,
body
input
[
type
=
"text"
]
:focus
,
body
input
[
type
=
"url"
]
:focus
,
body
input
[
type
=
"color"
]
:focus
,
body
input
[
type
=
"date"
]
:focus
,
body
input
[
type
=
"datetime"
]
:focus
,
body
input
[
type
=
"datetime-local"
]
:focus
,
body
input
[
type
=
"month"
]
:focus
,
body
input
[
type
=
"time"
]
:focus
,
body
input
[
type
=
"week"
]
:focus
,
body
textarea
:focus
{
border-color
:
#993333
;
}
header
.announcement
{
-webkit-background-size
:
cover
;
-moz-background-size
:
cover
;
-ms-background-size
:
cover
;
-o-background-size
:
cover
;
background-size
:
cover
;
background
:
#333
;
border-bottom
:
1px
solid
#000
;
color
:
#fff
;
-webkit-font-smoothing
:
antialiased
;
}
header
.announcement.home
{
background
:
#e3e3e3
url("../images/marketing/shot-5-medium.jpg")
;
}
@media
screen
and
(
min-width
:
1200px
)
{
header
.announcement.home
{
background
:
#e3e3e3
url("../images/marketing/shot-5-large.jpg")
;
}
}
header
.announcement.home
div
{
padding
:
258.88px
25.888px
77.664px
;
}
@media
screen
and
(
max-width
:
780px
)
{
header
.announcement.home
div
{
padding
:
64.72px
25.888px
51.776px
;
}
}
header
.announcement.home
div
nav
h1
{
margin-right
:
0
;
}
header
.announcement.home
div
nav
a
.login
{
display
:
none
;
}
header
.announcement.course
{
background
:
#e3e3e3
url("../images/marketing/course-bg-small.jpg")
;
}
@media
screen
and
(
min-width
:
1200px
)
{
header
.announcement.course
{
background
:
#e3e3e3
url("../images/marketing/course-bg-large.jpg")
;
}
}
@media
screen
and
(
max-width
:
1199px
)
and
(
min-width
:
700px
)
{
header
.announcement.course
{
background
:
#e3e3e3
url("../images/marketing/course-bg-medium.jpg")
;
}
}
header
.announcement.course
div
{
padding
:
103.552px
25.888px
51.776px
;
}
@media
screen
and
(
max-width
:
780px
)
{
header
.announcement.course
div
{
padding
:
64.72px
25.888px
51.776px
;
}
}
header
.announcement
div
{
position
:
relative
;
}
header
.announcement
div
nav
{
position
:
absolute
;
top
:
0
;
right
:
25.888px
;
-webkit-border-radius
:
0
0
3px
3px
;
-moz-border-radius
:
0
0
3px
3px
;
-ms-border-radius
:
0
0
3px
3px
;
-o-border-radius
:
0
0
3px
3px
;
border-radius
:
0
0
3px
3px
;
background
:
#333
;
background
:
rgba
(
0
,
0
,
0
,
0.7
);
padding
:
12.944px
25.888px
;
}
header
.announcement
div
nav
h1
{
display
:
-moz-inline-box
;
-moz-box-orient
:
vertical
;
display
:
inline-block
;
vertical-align
:
baseline
;
zoom
:
1
;
*
display
:
inline
;
*
vertical-align
:
auto
;
margin-right
:
12.944px
;
}
header
.announcement
div
nav
h1
a
{
font
:
italic
800
18px
"Open Sans"
,
Helvetica
,
Arial
,
sans-serif
;
color
:
#fff
;
text-decoration
:
none
;
}
header
.announcement
div
nav
h1
a
:hover
,
header
.announcement
div
nav
h1
a
:focus
{
color
:
#999
;
}
header
.announcement
div
nav
a
.login
{
text-decoration
:
none
;
color
:
#fff
;
font-size
:
12px
;
font-style
:
normal
;
font-family
:
"Open Sans"
,
Helvetica
,
Arial
,
sans-serif
;
}
header
.announcement
div
nav
a
.login
:hover
,
header
.announcement
div
nav
a
.login
:focus
{
color
:
#999
;
}
header
.announcement
div
section
{
background
:
#993333
;
display
:
-moz-inline-box
;
-moz-box-orient
:
vertical
;
display
:
inline-block
;
vertical-align
:
baseline
;
zoom
:
1
;
*
display
:
inline
;
*
vertical-align
:
auto
;
margin-left
:
34.171%
;
padding
:
25.888px
38.832px
;
}
@media
screen
and
(
max-width
:
780px
)
{
header
.announcement
div
section
{
margin-left
:
0
;
}
}
header
.announcement
div
section
h1
{
font-family
:
"Open Sans"
;
font-size
:
30px
;
font-weight
:
800
;
display
:
-moz-inline-box
;
-moz-box-orient
:
vertical
;
display
:
inline-block
;
vertical-align
:
baseline
;
zoom
:
1
;
*
display
:
inline
;
*
vertical-align
:
auto
;
line-height
:
1.2em
;
margin
:
0
25.888px
0
0
;
}
header
.announcement
div
section
h2
{
font-family
:
"Open Sans"
;
font-size
:
24px
;
font-weight
:
400
;
display
:
-moz-inline-box
;
-moz-box-orient
:
vertical
;
display
:
inline-block
;
vertical-align
:
baseline
;
zoom
:
1
;
*
display
:
inline
;
*
vertical-align
:
auto
;
line-height
:
1.2em
;
}
header
.announcement
div
section
.course
section
{
float
:
left
;
margin-left
:
0
;
margin-right
:
3.817%
;
padding
:
0
;
width
:
48.092%
;
}
@media
screen
and
(
max-width
:
780px
)
{
header
.announcement
div
section
.course
section
{
float
:
none
;
width
:
100%
;
margin-right
:
0
;
}
}
header
.announcement
div
section
.course
section
a
{
background-color
:
#4d1919
;
border-color
:
#260d0d
;
-webkit-box-shadow
:
inset
0
1px
0
#732626
,
0
1px
0
#ac3939
;
-moz-box-shadow
:
inset
0
1px
0
#732626
,
0
1px
0
#ac3939
;
box-shadow
:
inset
0
1px
0
#732626
,
0
1px
0
#ac3939
;
display
:
block
;
padding
:
12.944px
25.888px
;
text-align
:
center
;
}
header
.announcement
div
section
.course
section
a
:hover
{
background-color
:
#732626
;
border-color
:
#4d1919
;
}
header
.announcement
div
section
.course
p
{
width
:
48.092%
;
line-height
:
25.888px
;
float
:
left
;
}
@media
screen
and
(
max-width
:
780px
)
{
header
.announcement
div
section
.course
p
{
float
:
none
;
width
:
100%
;
}
}
footer
{
padding-top
:
0
;
}
footer
div
.footer-wrapper
{
border-top
:
1px
solid
#e5e5e5
;
padding
:
25.888px
0
;
background
:
url("../images/marketing/mit-logo.png")
right
center
no-repeat
;
}
@media
screen
and
(
max-width
:
780px
)
{
footer
div
.footer-wrapper
{
background-position
:
left
bottom
;
padding-bottom
:
77.664px
;
}
}
footer
div
.footer-wrapper
a
{
color
:
#888
;
text-decoration
:
none
;
-webkit-transition-property
:
all
;
-moz-transition-property
:
all
;
-ms-transition-property
:
all
;
-o-transition-property
:
all
;
transition-property
:
all
;
-webkit-transition-duration
:
0.15s
;
-moz-transition-duration
:
0.15s
;
-ms-transition-duration
:
0.15s
;
-o-transition-duration
:
0.15s
;
transition-duration
:
0.15s
;
-webkit-transition-timing-function
:
ease-out
;
-moz-transition-timing-function
:
ease-out
;
-ms-transition-timing-function
:
ease-out
;
-o-transition-timing-function
:
ease-out
;
transition-timing-function
:
ease-out
;
-webkit-transition-delay
:
0
;
-moz-transition-delay
:
0
;
-ms-transition-delay
:
0
;
-o-transition-delay
:
0
;
transition-delay
:
0
;
}
footer
div
.footer-wrapper
a
:hover
,
footer
div
.footer-wrapper
a
:focus
{
color
:
#666
;
}
footer
div
.footer-wrapper
p
{
display
:
-moz-inline-box
;
-moz-box-orient
:
vertical
;
display
:
inline-block
;
vertical-align
:
baseline
;
zoom
:
1
;
*
display
:
inline
;
*
vertical-align
:
auto
;
margin-right
:
25.888px
;
}
footer
div
.footer-wrapper
ul
{
display
:
-moz-inline-box
;
-moz-box-orient
:
vertical
;
display
:
inline-block
;
vertical-align
:
baseline
;
zoom
:
1
;
*
display
:
inline
;
*
vertical-align
:
auto
;
}
@media
screen
and
(
max-width
:
780px
)
{
footer
div
.footer-wrapper
ul
{
margin-top
:
25.888px
;
}
}
footer
div
.footer-wrapper
ul
li
{
display
:
-moz-inline-box
;
-moz-box-orient
:
vertical
;
display
:
inline-block
;
vertical-align
:
baseline
;
zoom
:
1
;
*
display
:
inline
;
*
vertical-align
:
auto
;
margin-bottom
:
0
;
}
footer
div
.footer-wrapper
ul
li
:after
{
content
:
' |'
;
display
:
inline
;
color
:
#ccc
;
}
footer
div
.footer-wrapper
ul
li
:last-child:after
{
content
:
none
;
}
footer
div
.footer-wrapper
ul
.social
{
float
:
right
;
margin-right
:
60px
;
position
:
relative
;
top
:
-5px
;
}
@media
screen
and
(
max-width
:
780px
)
{
footer
div
.footer-wrapper
ul
.social
{
float
:
none
;
}
}
footer
div
.footer-wrapper
ul
.social
li
{
float
:
left
;
margin-right
:
12.944px
;
}
footer
div
.footer-wrapper
ul
.social
li
:after
{
content
:
none
;
display
:
none
;
}
footer
div
.footer-wrapper
ul
.social
li
a
{
display
:
block
;
height
:
29px
;
width
:
28px
;
text-indent
:
-9999px
;
}
footer
div
.footer-wrapper
ul
.social
li
a
:hover
{
opacity
:
.8
;
}
footer
div
.footer-wrapper
ul
.social
li
.twitter
a
{
background
:
url("../images/marketing/twitter.png")
0
0
no-repeat
;
}
footer
div
.footer-wrapper
ul
.social
li
.facebook
a
{
background
:
url("../images/marketing/facebook.png")
0
0
no-repeat
;
}
footer
div
.footer-wrapper
ul
.social
li
.linkedin
a
{
background
:
url("../images/marketing/linkedin.png")
0
0
no-repeat
;
}
section
.index-content
section
{
float
:
left
;
}
@media
screen
and
(
max-width
:
780px
)
{
section
.index-content
section
{
float
:
none
;
width
:
auto
;
margin-right
:
0
;
}
}
section
.index-content
section
h1
{
font-size
:
800
24px
"Open Sans"
;
margin-bottom
:
25.888px
;
}
section
.index-content
section
p
{
line-height
:
25.888px
;
margin-bottom
:
25.888px
;
}
section
.index-content
section
ul
{
margin
:
0
;
}
section
.index-content
section
.about
{
-webkit-box-sizing
:
border-box
;
-moz-box-sizing
:
border-box
;
box-sizing
:
border-box
;
border-right
:
1px
solid
#e5e5e5
;
margin-right
:
2.513%
;
padding-right
:
1.256%
;
width
:
65.829%
;
}
@media
screen
and
(
max-width
:
780px
)
{
section
.index-content
section
.about
{
width
:
100%
;
border-right
:
0
;
margin-right
:
0
;
padding-right
:
0
;
}
}
section
.index-content
section
.about
section
{
margin-bottom
:
25.888px
;
}
section
.index-content
section
.about
section
p
{
width
:
48.092%
;
float
:
left
;
}
@media
screen
and
(
max-width
:
780px
)
{
section
.index-content
section
.about
section
p
{
float
:
none
;
width
:
auto
;
}
}
section
.index-content
section
.about
section
p
:nth-child
(
odd
)
{
margin-right
:
3.817%
;
}
@media
screen
and
(
max-width
:
780px
)
{
section
.index-content
section
.about
section
p
:nth-child
(
odd
)
{
margin-right
:
0
;
}
}
section
.index-content
section
.about
section
.intro
section
{
margin-bottom
:
0
;
}
section
.index-content
section
.about
section
.intro
section
.intro-text
{
margin-right
:
3.817%
;
width
:
48.092%
;
}
@media
screen
and
(
max-width
:
780px
)
{
section
.index-content
section
.about
section
.intro
section
.intro-text
{
margin-right
:
0
;
width
:
auto
;
}
}
section
.index-content
section
.about
section
.intro
section
.intro-text
p
{
margin-right
:
0
;
width
:
auto
;
float
:
none
;
}
section
.index-content
section
.about
section
.intro
section
.intro-video
{
width
:
48.092%
;
}
@media
screen
and
(
max-width
:
780px
)
{
section
.index-content
section
.about
section
.intro
section
.intro-video
{
width
:
auto
;
}
}
section
.index-content
section
.about
section
.intro
section
.intro-video
a
{
display
:
block
;
width
:
100%
;
}
section
.index-content
section
.about
section
.intro
section
.intro-video
a
img
{
width
:
100%
;
}
section
.index-content
section
.about
section
.intro
section
.intro-video
a
span
{
display
:
none
;
}
section
.index-content
section
.about
section
.features
{
border-top
:
1px
solid
#E5E5E5
;
padding-top
:
25.888px
;
margin-bottom
:
0
;
}
section
.index-content
section
.about
section
.features
h2
{
text-transform
:
uppercase
;
letter-spacing
:
1px
;
color
:
#888
;
margin-bottom
:
25.888px
;
font-weight
:
normal
;
font-size
:
14px
;
}
section
.index-content
section
.about
section
.features
h2
span
{
text-transform
:
none
;
}
section
.index-content
section
.about
section
.features
p
{
width
:
auto
;
clear
:
both
;
}
section
.index-content
section
.about
section
.features
p
strong
{
font-family
:
"Open sans"
;
font-weight
:
800
;
}
section
.index-content
section
.about
section
.features
p
a
{
color
:
#993333
;
text-decoration
:
none
;
-webkit-transition-property
:
all
;
-moz-transition-property
:
all
;
-ms-transition-property
:
all
;
-o-transition-property
:
all
;
transition-property
:
all
;
-webkit-transition-duration
:
0.15s
;
-moz-transition-duration
:
0.15s
;
-ms-transition-duration
:
0.15s
;
-o-transition-duration
:
0.15s
;
transition-duration
:
0.15s
;
-webkit-transition-timing-function
:
ease-out
;
-moz-transition-timing-function
:
ease-out
;
-ms-transition-timing-function
:
ease-out
;
-o-transition-timing-function
:
ease-out
;
transition-timing-function
:
ease-out
;
-webkit-transition-delay
:
0
;
-moz-transition-delay
:
0
;
-ms-transition-delay
:
0
;
-o-transition-delay
:
0
;
transition-delay
:
0
;
}
section
.index-content
section
.about
section
.features
p
a
:hover
,
section
.index-content
section
.about
section
.features
p
a
:focus
{
color
:
#602020
;
}
section
.index-content
section
.about
section
.features
ul
{
margin-bottom
:
0
;
}
section
.index-content
section
.about
section
.features
ul
li
{
line-height
:
25.888px
;
width
:
48.092%
;
float
:
left
;
margin-bottom
:
12.944px
;
}
@media
screen
and
(
max-width
:
780px
)
{
section
.index-content
section
.about
section
.features
ul
li
{
width
:
auto
;
float
:
none
;
}
}
section
.index-content
section
.about
section
.features
ul
li
:nth-child
(
odd
)
{
margin-right
:
3.817%
;
}
@media
screen
and
(
max-width
:
780px
)
{
section
.index-content
section
.about
section
.features
ul
li
:nth-child
(
odd
)
{
margin-right
:
0
;
}
}
section
.index-content
section
.course
,
section
.index-content
section
.staff
{
width
:
31.658%
;
}
@media
screen
and
(
max-width
:
780px
)
{
section
.index-content
section
.course
,
section
.index-content
section
.staff
{
width
:
auto
;
}
}
section
.index-content
section
.course
h1
,
section
.index-content
section
.staff
h1
{
color
:
#888
;
font
:
normal
16px
Georgia
,
serif
;
font-size
:
14px
;
letter-spacing
:
1px
;
margin-bottom
:
25.888px
;
text-transform
:
uppercase
;
}
section
.index-content
section
.course
h2
,
section
.index-content
section
.staff
h2
{
font
:
800
24px
"Open Sans"
,
Helvetica
,
Arial
,
sans-serif
;
}
section
.index-content
section
.course
h3
,
section
.index-content
section
.staff
h3
{
font
:
400
18px
"Open Sans"
,
Helvetica
,
Arial
,
sans-serif
;
}
section
.index-content
section
.course
a
span
.arrow
,
section
.index-content
section
.staff
a
span
.arrow
{
color
:
rgba
(
255
,
255
,
255
,
0.6
);
font-style
:
normal
;
display
:
-moz-inline-box
;
-moz-box-orient
:
vertical
;
display
:
inline-block
;
vertical-align
:
baseline
;
zoom
:
1
;
*
display
:
inline
;
*
vertical-align
:
auto
;
padding-left
:
10px
;
}
section
.index-content
section
.course
ul
,
section
.index-content
section
.staff
ul
{
list-style
:
none
;
}
section
.index-content
section
.course
ul
li
img
,
section
.index-content
section
.staff
ul
li
img
{
float
:
left
;
margin-right
:
12.944px
;
}
section
.index-content
section
.course
h2
{
padding-top
:
129.44px
;
background
:
url("../images/marketing/circuits-bg.jpg")
0
0
no-repeat
;
-webkit-background-size
:
contain
;
-moz-background-size
:
contain
;
-ms-background-size
:
contain
;
-o-background-size
:
contain
;
background-size
:
contain
;
}
@media
screen
and
(
max-width
:
998px
)
and
(
min-width
:
781px
)
{
section
.index-content
section
.course
h2
{
background
:
url("../images/marketing/circuits-medium-bg.jpg")
0
0
no-repeat
;
}
}
@media
screen
and
(
max-width
:
780px
)
{
section
.index-content
section
.course
h2
{
padding-top
:
129.44px
;
background
:
url("../images/marketing/circuits-bg.jpg")
0
0
no-repeat
;
}
}
@media
screen
and
(
min-width
:
500px
)
and
(
max-width
:
781px
)
{
section
.index-content
section
.course
h2
{
padding-top
:
207.104px
;
}
}
section
.index-content
section
.course
div
.announcement
p
.announcement-button
a
{
margin-top
:
0
;
}
section
.index-content
section
.course
div
.announcement
img
{
max-width
:
100%
;
margin-bottom
:
25.888px
;
}
section
.index-content
section
.about-course
{
-webkit-box-sizing
:
border-box
;
-moz-box-sizing
:
border-box
;
box-sizing
:
border-box
;
border-right
:
1px
solid
#e5e5e5
;
margin-right
:
2.513%
;
padding-right
:
1.256%
;
width
:
65.829%
;
}
@media
screen
and
(
max-width
:
780px
)
{
section
.index-content
section
.about-course
{
width
:
auto
;
border-right
:
0
;
margin-right
:
0
;
padding-right
:
0
;
}
}
section
.index-content
section
.about-course
section
{
width
:
48.092%
;
}
@media
screen
and
(
max-width
:
780px
)
{
section
.index-content
section
.about-course
section
{
width
:
auto
;
}
}
section
.index-content
section
.about-course
section
.about-info
{
margin-right
:
3.817%
;
}
@media
screen
and
(
max-width
:
780px
)
{
section
.index-content
section
.about-course
section
.about-info
{
margin-right
:
0
;
}
}
section
.index-content
section
.about-course
section
.requirements
{
clear
:
both
;
width
:
100%
;
border-top
:
1px
solid
#E5E5E5
;
padding-top
:
25.888px
;
margin-bottom
:
0
;
}
section
.index-content
section
.about-course
section
.requirements
p
{
float
:
left
;
width
:
48.092%
;
margin-right
:
3.817%
;
}
@media
screen
and
(
max-width
:
780px
)
{
section
.index-content
section
.about-course
section
.requirements
p
{
margin-right
:
0
;
float
:
none
;
width
:
auto
;
}
}
section
.index-content
section
.about-course
section
.requirements
p
:nth-child
(
odd
)
{
margin-right
:
0
;
}
section
.index-content
section
.about-course
section
.cta
{
width
:
100%
;
text-align
:
center
;
}
section
.index-content
section
.about-course
section
.cta
a
.enroll
{
padding
:
12.944px
51.776px
;
display
:
-moz-inline-box
;
-moz-box-orient
:
vertical
;
display
:
inline-block
;
vertical-align
:
baseline
;
zoom
:
1
;
*
display
:
inline
;
*
vertical-align
:
auto
;
text-align
:
center
;
font
:
800
18px
"Open Sans"
,
Helvetica
,
Arial
,
sans-serif
;
}
section
.index-content
section
.staff
h1
{
margin-top
:
25.888px
;
}
#lean_overlay
{
background
:
#000
;
display
:
none
;
height
:
100%
;
left
:
0px
;
position
:
fixed
;
top
:
0px
;
width
:
100%
;
z-index
:
100
;
}
div
.leanModal_box
{
background
:
#fff
;
border
:
none
;
-webkit-border-radius
:
3px
;
-moz-border-radius
:
3px
;
-ms-border-radius
:
3px
;
-o-border-radius
:
3px
;
border-radius
:
3px
;
-webkit-box-shadow
:
0
0
6px
black
;
-moz-box-shadow
:
0
0
6px
black
;
box-shadow
:
0
0
6px
black
;
-webkit-box-sizing
:
border-box
;
-moz-box-sizing
:
border-box
;
box-sizing
:
border-box
;
display
:
none
;
padding
:
51.776px
;
text-align
:
left
;
}
div
.leanModal_box
a
.modal_close
{
color
:
#aaa
;
display
:
block
;
font-style
:
normal
;
height
:
14px
;
position
:
absolute
;
right
:
12px
;
top
:
12px
;
width
:
14px
;
z-index
:
2
;
}
div
.leanModal_box
a
.modal_close
:hover
{
color
:
#993333
;
text-decoration
:
none
;
}
div
.leanModal_box
h1
{
border-bottom
:
1px
solid
#eee
;
font-size
:
24px
;
margin-bottom
:
25.888px
;
margin-top
:
0
;
padding-bottom
:
25.888px
;
text-align
:
left
;
}
div
.leanModal_box
#enroll
{
max-width
:
600px
;
}
div
.leanModal_box
#enroll
ol
{
padding-top
:
25.888px
;
}
div
.leanModal_box
#enroll
ol
li
.terms
,
div
.leanModal_box
#enroll
ol
li
.honor-code
{
float
:
none
;
width
:
auto
;
}
div
.leanModal_box
#enroll
ol
li
div
.tip
{
display
:
none
;
}
div
.leanModal_box
#enroll
ol
li
:hover
div
.tip
{
background
:
#333
;
color
:
#fff
;
display
:
block
;
font-size
:
16px
;
line-height
:
25.888px
;
margin
:
0
0
0
-10px
;
padding
:
10px
;
position
:
absolute
;
-webkit-font-smoothing
:
antialiased
;
width
:
500px
;
}
div
.leanModal_box
form
{
text-align
:
left
;
}
div
.leanModal_box
form
div
#enroll_error
,
div
.leanModal_box
form
div
#login_error
,
div
.leanModal_box
form
div
#pwd_error
{
background-color
:
#333333
;
border
:
black
;
color
:
#fff
;
font-family
:
"Open sans"
;
font-weight
:
bold
;
letter-spacing
:
1px
;
margin
:
-25.888px
-25.888px
25.888px
;
padding
:
12.944px
;
text-shadow
:
0
1px
0
#1a1a1a
;
-webkit-font-smoothing
:
antialiased
;
}
div
.leanModal_box
form
div
#enroll_error
:empty
,
div
.leanModal_box
form
div
#login_error
:empty
,
div
.leanModal_box
form
div
#pwd_error
:empty
{
padding
:
0
;
}
div
.leanModal_box
form
ol
{
list-style
:
none
;
margin-bottom
:
25.888px
;
}
div
.leanModal_box
form
ol
li
{
margin-bottom
:
12.944px
;
}
div
.leanModal_box
form
ol
li
.terms
,
div
.leanModal_box
form
ol
li
.remember
{
border-top
:
1px
solid
#eee
;
clear
:
both
;
float
:
none
;
padding-top
:
25.888px
;
width
:
auto
;
}
div
.leanModal_box
form
ol
li
.honor-code
{
float
:
none
;
width
:
auto
;
}
div
.leanModal_box
form
ol
li
label
{
display
:
block
;
font-weight
:
bold
;
}
div
.leanModal_box
form
ol
li
input
[
type
=
"email"
],
div
.leanModal_box
form
ol
li
input
[
type
=
"number"
],
div
.leanModal_box
form
ol
li
input
[
type
=
"password"
],
div
.leanModal_box
form
ol
li
input
[
type
=
"search"
],
div
.leanModal_box
form
ol
li
input
[
type
=
"tel"
],
div
.leanModal_box
form
ol
li
input
[
type
=
"text"
],
div
.leanModal_box
form
ol
li
input
[
type
=
"url"
],
div
.leanModal_box
form
ol
li
input
[
type
=
"color"
],
div
.leanModal_box
form
ol
li
input
[
type
=
"date"
],
div
.leanModal_box
form
ol
li
input
[
type
=
"datetime"
],
div
.leanModal_box
form
ol
li
input
[
type
=
"datetime-local"
],
div
.leanModal_box
form
ol
li
input
[
type
=
"month"
],
div
.leanModal_box
form
ol
li
input
[
type
=
"time"
],
div
.leanModal_box
form
ol
li
input
[
type
=
"week"
],
div
.leanModal_box
form
ol
li
textarea
{
-webkit-box-sizing
:
border-box
;
-moz-box-sizing
:
border-box
;
box-sizing
:
border-box
;
width
:
100%
;
}
div
.leanModal_box
form
ol
li
input
[
type
=
"checkbox"
]
{
margin-right
:
10px
;
}
div
.leanModal_box
form
ol
li
ul
{
list-style
:
disc
outside
none
;
margin
:
12.944px
0
25.888px
25.888px
;
}
div
.leanModal_box
form
ol
li
ul
li
{
color
:
#666
;
float
:
none
;
font-size
:
14px
;
list-style
:
disc
outside
none
;
margin-bottom
:
12.944px
;
}
div
.leanModal_box
form
input
[
type
=
"button"
],
div
.leanModal_box
form
input
[
type
=
"submit"
]
{
border
:
1px
solid
#691b1b
;
-webkit-border-radius
:
3px
;
-moz-border-radius
:
3px
;
-ms-border-radius
:
3px
;
-o-border-radius
:
3px
;
border-radius
:
3px
;
-webkit-box-shadow
:
inset
0
1px
0
0
#bc5c5c
;
-moz-box-shadow
:
inset
0
1px
0
0
#bc5c5c
;
box-shadow
:
inset
0
1px
0
0
#bc5c5c
;
color
:
white
;
display
:
inline
;
font-size
:
11px
;
font-weight
:
bold
;
background-color
:
#993333
;
background-image
:
-webkit-gradient
(
linear
,
left
top
,
left
bottom
,
color-stop
(
0%
,
#993333
),
color-stop
(
100%
,
#761e1e
));
background-image
:
-webkit-linear-gradient
(
top
,
#993333
,
#761e1e
);
background-image
:
-moz-linear-gradient
(
top
,
#993333
,
#761e1e
);
background-image
:
-ms-linear-gradient
(
top
,
#993333
,
#761e1e
);
background-image
:
-o-linear-gradient
(
top
,
#993333
,
#761e1e
);
background-image
:
linear-gradient
(
top
,
#993333
,
#761e1e
);
padding
:
6px
18px
7px
;
text-shadow
:
0
1px
0
#5d1414
;
-webkit-background-clip
:
padding-box
;
font-size
:
18px
;
padding
:
12.944px
;
}
div
.leanModal_box
form
input
[
type
=
"button"
]
:hover
,
div
.leanModal_box
form
input
[
type
=
"submit"
]
:hover
{
-webkit-box-shadow
:
inset
0
1px
0
0
#a44141
;
-moz-box-shadow
:
inset
0
1px
0
0
#a44141
;
box-shadow
:
inset
0
1px
0
0
#a44141
;
cursor
:
pointer
;
background-color
:
#823030
;
background-image
:
-webkit-gradient
(
linear
,
left
top
,
left
bottom
,
color-stop
(
0%
,
#823030
),
color-stop
(
100%
,
#691c1c
));
background-image
:
-webkit-linear-gradient
(
top
,
#823030
,
#691c1c
);
background-image
:
-moz-linear-gradient
(
top
,
#823030
,
#691c1c
);
background-image
:
-ms-linear-gradient
(
top
,
#823030
,
#691c1c
);
background-image
:
-o-linear-gradient
(
top
,
#823030
,
#691c1c
);
background-image
:
linear-gradient
(
top
,
#823030
,
#691c1c
);
}
div
.leanModal_box
form
input
[
type
=
"button"
]
:active
,
div
.leanModal_box
form
input
[
type
=
"submit"
]
:active
{
border
:
1px
solid
#691b1b
;
-webkit-box-shadow
:
inset
0
0
8px
4px
#5c1919
,
inset
0
0
8px
4px
#5c1919
,
0
1px
1px
0
#eeeeee
;
-moz-box-shadow
:
inset
0
0
8px
4px
#5c1919
,
inset
0
0
8px
4px
#5c1919
,
0
1px
1px
0
#eeeeee
;
box-shadow
:
inset
0
0
8px
4px
#5c1919
,
inset
0
0
8px
4px
#5c1919
,
0
1px
1px
0
#eeeeee
;
}
div
#login
{
min-width
:
400px
;
}
div
#login
header
{
border-bottom
:
1px
solid
#ddd
;
margin-bottom
:
25.888px
;
padding-bottom
:
25.888px
;
}
div
#login
header
h1
{
border-bottom
:
0
;
padding-bottom
:
0
;
margin-bottom
:
6.472px
;
}
div
#login
ol
li
{
float
:
none
;
width
:
auto
;
}
div
.lost-password
{
margin-top
:
25.888px
;
text-align
:
left
;
}
div
.lost-password
a
{
color
:
#999
;
}
div
.lost-password
a
:hover
{
color
:
#444
;
}
div
#pwd_reset
p
{
margin-bottom
:
25.888px
;
}
div
#pwd_reset
input
[
type
=
"email"
]
{
margin-bottom
:
25.888px
;
}
div
#apply_name_change
,
div
#change_email
,
div
#unenroll
,
div
#deactivate-account
{
max-width
:
700px
;
}
div
#apply_name_change
ul
,
div
#change_email
ul
,
div
#unenroll
ul
,
div
#deactivate-account
ul
{
list-style
:
none
;
}
div
#apply_name_change
ul
li
,
div
#change_email
ul
li
,
div
#unenroll
ul
li
,
div
#deactivate-account
ul
li
{
margin-bottom
:
12.944px
;
}
div
#apply_name_change
ul
li
textarea
,
div
#apply_name_change
ul
li
input
[
type
=
"email"
],
div
#apply_name_change
ul
li
input
[
type
=
"number"
],
div
#apply_name_change
ul
li
input
[
type
=
"password"
],
div
#apply_name_change
ul
li
input
[
type
=
"search"
],
div
#apply_name_change
ul
li
input
[
type
=
"tel"
],
div
#apply_name_change
ul
li
input
[
type
=
"text"
],
div
#apply_name_change
ul
li
input
[
type
=
"url"
],
div
#apply_name_change
ul
li
input
[
type
=
"color"
],
div
#apply_name_change
ul
li
input
[
type
=
"date"
],
div
#apply_name_change
ul
li
input
[
type
=
"datetime"
],
div
#apply_name_change
ul
li
input
[
type
=
"datetime-local"
],
div
#apply_name_change
ul
li
input
[
type
=
"month"
],
div
#apply_name_change
ul
li
input
[
type
=
"time"
],
div
#apply_name_change
ul
li
input
[
type
=
"week"
],
div
#change_email
ul
li
textarea
,
div
#change_email
ul
li
input
[
type
=
"email"
],
div
#change_email
ul
li
input
[
type
=
"number"
],
div
#change_email
ul
li
input
[
type
=
"password"
],
div
#change_email
ul
li
input
[
type
=
"search"
],
div
#change_email
ul
li
input
[
type
=
"tel"
],
div
#change_email
ul
li
input
[
type
=
"text"
],
div
#change_email
ul
li
input
[
type
=
"url"
],
div
#change_email
ul
li
input
[
type
=
"color"
],
div
#change_email
ul
li
input
[
type
=
"date"
],
div
#change_email
ul
li
input
[
type
=
"datetime"
],
div
#change_email
ul
li
input
[
type
=
"datetime-local"
],
div
#change_email
ul
li
input
[
type
=
"month"
],
div
#change_email
ul
li
input
[
type
=
"time"
],
div
#change_email
ul
li
input
[
type
=
"week"
],
div
#unenroll
ul
li
textarea
,
div
#unenroll
ul
li
input
[
type
=
"email"
],
div
#unenroll
ul
li
input
[
type
=
"number"
],
div
#unenroll
ul
li
input
[
type
=
"password"
],
div
#unenroll
ul
li
input
[
type
=
"search"
],
div
#unenroll
ul
li
input
[
type
=
"tel"
],
div
#unenroll
ul
li
input
[
type
=
"text"
],
div
#unenroll
ul
li
input
[
type
=
"url"
],
div
#unenroll
ul
li
input
[
type
=
"color"
],
div
#unenroll
ul
li
input
[
type
=
"date"
],
div
#unenroll
ul
li
input
[
type
=
"datetime"
],
div
#unenroll
ul
li
input
[
type
=
"datetime-local"
],
div
#unenroll
ul
li
input
[
type
=
"month"
],
div
#unenroll
ul
li
input
[
type
=
"time"
],
div
#unenroll
ul
li
input
[
type
=
"week"
],
div
#deactivate-account
ul
li
textarea
,
div
#deactivate-account
ul
li
input
[
type
=
"email"
],
div
#deactivate-account
ul
li
input
[
type
=
"number"
],
div
#deactivate-account
ul
li
input
[
type
=
"password"
],
div
#deactivate-account
ul
li
input
[
type
=
"search"
],
div
#deactivate-account
ul
li
input
[
type
=
"tel"
],
div
#deactivate-account
ul
li
input
[
type
=
"text"
],
div
#deactivate-account
ul
li
input
[
type
=
"url"
],
div
#deactivate-account
ul
li
input
[
type
=
"color"
],
div
#deactivate-account
ul
li
input
[
type
=
"date"
],
div
#deactivate-account
ul
li
input
[
type
=
"datetime"
],
div
#deactivate-account
ul
li
input
[
type
=
"datetime-local"
],
div
#deactivate-account
ul
li
input
[
type
=
"month"
],
div
#deactivate-account
ul
li
input
[
type
=
"time"
],
div
#deactivate-account
ul
li
input
[
type
=
"week"
]
{
-webkit-box-sizing
:
border-box
;
-moz-box-sizing
:
border-box
;
box-sizing
:
border-box
;
display
:
block
;
width
:
100%
;
}
div
#apply_name_change
ul
li
textarea
,
div
#change_email
ul
li
textarea
,
div
#unenroll
ul
li
textarea
,
div
#deactivate-account
ul
li
textarea
{
height
:
60px
;
}
div
#apply_name_change
ul
li
input
[
type
=
"submit"
],
div
#change_email
ul
li
input
[
type
=
"submit"
],
div
#unenroll
ul
li
input
[
type
=
"submit"
],
div
#deactivate-account
ul
li
input
[
type
=
"submit"
]
{
white-space
:
normal
;
}
div
#feedback_div
form
ol
li
{
float
:
none
;
width
:
100%
;
}
div
#feedback_div
form
ol
li
textarea
#feedback_message
{
height
:
100px
;
}
lms/urls.py
View file @
be369938
...
...
@@ -95,7 +95,7 @@ if settings.COURSEWARE_ENABLED:
url
(
r'^masquerade/'
,
include
(
'masquerade.urls'
)),
url
(
r'^jumpto/(?P<probname>[^/]+)/$'
,
'courseware.views.jump_to'
),
url
(
r'^modx/(?P<id>.*?)/(?P<dispatch>[^/]*)$'
,
'courseware.module_render.modx_dispatch'
),
#reset_problem'),
url
(
r'^xqueue/(?P<user
name
>[^/]*)/(?P<id>.*?)/(?P<dispatch>[^/]*)$'
,
'courseware.module_render.xqueue_callback'
),
url
(
r'^xqueue/(?P<user
id
>[^/]*)/(?P<id>.*?)/(?P<dispatch>[^/]*)$'
,
'courseware.module_render.xqueue_callback'
),
url
(
r'^change_setting$'
,
'student.views.change_setting'
),
url
(
r'^s/(?P<template>[^/]*)$'
,
'static_template_view.views.auth_index'
),
# url(r'^course_info/$', 'student.views.courseinfo'),
...
...
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