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
9c67e56d
Commit
9c67e56d
authored
Aug 16, 2013
by
Jay Zoldak
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #714 from edx/zoldak/hotfix-2013-08-16
Zoldak/hotfix 2013 08 16
parents
0350dea2
0a59cb65
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
170 additions
and
28 deletions
+170
-28
cms/djangoapps/contentstore/views/assets.py
+3
-0
common/lib/xmodule/xmodule/js/src/video/09_video_caption.js
+45
-6
common/lib/xmodule/xmodule/tests/test_video.py
+87
-4
common/lib/xmodule/xmodule/video_module.py
+24
-14
common/lib/xmodule/xmodule/x_module.py
+4
-4
common/lib/xmodule/xmodule/xml_module.py
+5
-0
lms/djangoapps/courseware/grades.py
+2
-0
No files found.
cms/djangoapps/contentstore/views/assets.py
View file @
9c67e56d
...
@@ -348,6 +348,8 @@ def generate_export_course(request, org, course, name):
...
@@ -348,6 +348,8 @@ def generate_export_course(request, org, course, name):
try
:
try
:
export_to_xml
(
modulestore
(
'direct'
),
contentstore
(),
loc
,
root_dir
,
name
,
modulestore
())
export_to_xml
(
modulestore
(
'direct'
),
contentstore
(),
loc
,
root_dir
,
name
,
modulestore
())
except
SerializationError
,
e
:
except
SerializationError
,
e
:
logging
.
exception
(
'There was an error exporting course {0}. {1}'
.
format
(
course_module
.
location
,
unicode
(
e
)))
unit
=
None
unit
=
None
failed_item
=
None
failed_item
=
None
parent
=
None
parent
=
None
...
@@ -380,6 +382,7 @@ def generate_export_course(request, org, course, name):
...
@@ -380,6 +382,7 @@ def generate_export_course(request, org, course, name):
})
})
})
})
except
Exception
,
e
:
except
Exception
,
e
:
logging
.
exception
(
'There was an error exporting course {0}. {1}'
.
format
(
course_module
.
location
,
unicode
(
e
)))
return
render_to_response
(
'export.html'
,
{
return
render_to_response
(
'export.html'
,
{
'context_course'
:
course_module
,
'context_course'
:
course_module
,
'successful_import_redirect_url'
:
''
,
'successful_import_redirect_url'
:
''
,
...
...
common/lib/xmodule/xmodule/js/src/video/09_video_caption.js
View file @
9c67e56d
...
@@ -312,15 +312,34 @@ function () {
...
@@ -312,15 +312,34 @@ function () {
var
newIndex
;
var
newIndex
;
if
(
this
.
videoCaption
.
loaded
)
{
if
(
this
.
videoCaption
.
loaded
)
{
time
=
Math
.
round
(
Time
.
convert
(
time
,
this
.
speed
,
'1.0'
)
*
1000
+
250
);
// Current mode === 'flash' can only be for YouTube videos. So, we
// don't have to also check for videoType === 'youtube'.
if
(
this
.
currentPlayerMode
===
'flash'
)
{
// Total play time changes with speed change. Also there is
// a 250 ms delay we have to take into account.
time
=
Math
.
round
(
Time
.
convert
(
time
,
this
.
speed
,
'1.0'
)
*
1000
+
250
);
}
else
{
// Total play time remains constant when speed changes.
time
=
Math
.
round
(
parseInt
(
time
,
10
)
*
1000
);
}
newIndex
=
this
.
videoCaption
.
search
(
time
);
newIndex
=
this
.
videoCaption
.
search
(
time
);
if
(
newIndex
!==
void
0
&&
this
.
videoCaption
.
currentIndex
!==
newIndex
)
{
if
(
newIndex
!==
void
0
&&
this
.
videoCaption
.
currentIndex
!==
newIndex
)
{
if
(
this
.
videoCaption
.
currentIndex
)
{
if
(
this
.
videoCaption
.
currentIndex
)
{
this
.
videoCaption
.
subtitlesEl
.
find
(
'li.current'
).
removeClass
(
'current'
);
this
.
videoCaption
.
subtitlesEl
.
find
(
'li.current'
)
.
removeClass
(
'current'
);
}
}
this
.
videoCaption
.
subtitlesEl
.
find
(
"li[data-index='"
+
newIndex
+
"']"
).
addClass
(
'current'
);
this
.
videoCaption
.
subtitlesEl
.
find
(
"li[data-index='"
+
newIndex
+
"']"
)
.
addClass
(
'current'
);
this
.
videoCaption
.
currentIndex
=
newIndex
;
this
.
videoCaption
.
currentIndex
=
newIndex
;
...
@@ -333,9 +352,29 @@ function () {
...
@@ -333,9 +352,29 @@ function () {
var
time
;
var
time
;
event
.
preventDefault
();
event
.
preventDefault
();
time
=
Math
.
round
(
Time
.
convert
(
$
(
event
.
target
).
data
(
'start'
),
'1.0'
,
this
.
speed
)
/
1000
);
this
.
trigger
(
'videoPlayer.onCaptionSeek'
,
{
'type'
:
'onCaptionSeek'
,
'time'
:
time
});
// Current mode === 'flash' can only be for YouTube videos. So, we
// don't have to also check for videoType === 'youtube'.
if
(
this
.
currentPlayerMode
===
'flash'
)
{
// Total play time changes with speed change. Also there is
// a 250 ms delay we have to take into account.
time
=
Math
.
round
(
Time
.
convert
(
$
(
event
.
target
).
data
(
'start'
),
'1.0'
,
this
.
speed
)
/
1000
);
}
else
{
// Total play time remains constant when speed changes.
time
=
parseInt
(
$
(
event
.
target
).
data
(
'start'
),
10
)
/
1000
;
}
this
.
trigger
(
'videoPlayer.onCaptionSeek'
,
{
'type'
:
'onCaptionSeek'
,
'time'
:
time
}
);
}
}
function
calculateOffset
(
element
)
{
function
calculateOffset
(
element
)
{
...
...
common/lib/xmodule/xmodule/tests/test_video.py
View file @
9c67e56d
...
@@ -15,6 +15,7 @@ the course, section, subsection, unit, etc.
...
@@ -15,6 +15,7 @@ the course, section, subsection, unit, etc.
import
unittest
import
unittest
from
.
import
LogicTest
from
.
import
LogicTest
from
lxml
import
etree
from
.
import
get_test_system
from
.
import
get_test_system
from
xmodule.modulestore
import
Location
from
xmodule.modulestore
import
Location
from
xmodule.video_module
import
VideoDescriptor
,
_create_youtube_string
from
xmodule.video_module
import
VideoDescriptor
,
_create_youtube_string
...
@@ -64,6 +65,32 @@ class VideoModuleTest(LogicTest):
...
@@ -64,6 +65,32 @@ class VideoModuleTest(LogicTest):
'1.25'
:
''
,
'1.25'
:
''
,
'1.50'
:
''
})
'1.50'
:
''
})
def
test_parse_youtube_invalid
(
self
):
"""Ensure that ids that are invalid return an empty dict"""
# invalid id
youtube_str
=
'thisisaninvalidid'
output
=
VideoDescriptor
.
_parse_youtube
(
youtube_str
)
self
.
assertEqual
(
output
,
{
'0.75'
:
''
,
'1.00'
:
''
,
'1.25'
:
''
,
'1.50'
:
''
})
# another invalid id
youtube_str
=
',::,:,,'
output
=
VideoDescriptor
.
_parse_youtube
(
youtube_str
)
self
.
assertEqual
(
output
,
{
'0.75'
:
''
,
'1.00'
:
''
,
'1.25'
:
''
,
'1.50'
:
''
})
# and another one, partially invalid
youtube_str
=
'0.75_BAD!!!,1.0:AXdE34_U,1.25:KLHF9K_Y,1.5:VO3SxfeD,'
output
=
VideoDescriptor
.
_parse_youtube
(
youtube_str
)
self
.
assertEqual
(
output
,
{
'0.75'
:
''
,
'1.00'
:
'AXdE34_U'
,
'1.25'
:
'KLHF9K_Y'
,
'1.50'
:
'VO3SxfeD'
})
def
test_parse_youtube_key_format
(
self
):
def
test_parse_youtube_key_format
(
self
):
"""
"""
Make sure that inconsistent speed keys are parsed correctly.
Make sure that inconsistent speed keys are parsed correctly.
...
@@ -263,6 +290,62 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
...
@@ -263,6 +290,62 @@ class VideoDescriptorImportTestCase(unittest.TestCase):
'data'
:
''
'data'
:
''
})
})
def
test_from_xml_double_quotes
(
self
):
"""
Make sure we can handle the double-quoted string format (which was used for exporting for
a few weeks).
"""
module_system
=
DummySystem
(
load_error_modules
=
True
)
xml_data
=
'''
<video display_name=""display_name""
html5_sources="["source_1", "source_2"]"
show_captions="false"
source=""http://download_video""
sub=""html5_subtitles""
track=""http://download_track""
youtube_id_0_75=""OEoXaMPEzf65""
youtube_id_1_25=""OEoXaMPEzf125""
youtube_id_1_5=""OEoXaMPEzf15""
youtube_id_1_0=""OEoXaMPEzf10""
/>
'''
output
=
VideoDescriptor
.
from_xml
(
xml_data
,
module_system
)
self
.
assert_attributes_equal
(
output
,
{
'youtube_id_0_75'
:
'OEoXaMPEzf65'
,
'youtube_id_1_0'
:
'OEoXaMPEzf10'
,
'youtube_id_1_25'
:
'OEoXaMPEzf125'
,
'youtube_id_1_5'
:
'OEoXaMPEzf15'
,
'show_captions'
:
False
,
'start_time'
:
0.0
,
'end_time'
:
0.0
,
'track'
:
'http://download_track'
,
'source'
:
'http://download_video'
,
'html5_sources'
:
[
"source_1"
,
"source_2"
],
'data'
:
''
})
def
test_from_xml_double_quote_concatenated_youtube
(
self
):
module_system
=
DummySystem
(
load_error_modules
=
True
)
xml_data
=
'''
<video display_name="Test Video"
youtube="1.0:"p2Q6BrNhdh8",1.25:"1EeWXzPdhSA"">
</video>
'''
output
=
VideoDescriptor
.
from_xml
(
xml_data
,
module_system
)
self
.
assert_attributes_equal
(
output
,
{
'youtube_id_0_75'
:
''
,
'youtube_id_1_0'
:
'p2Q6BrNhdh8'
,
'youtube_id_1_25'
:
'1EeWXzPdhSA'
,
'youtube_id_1_5'
:
''
,
'show_captions'
:
True
,
'start_time'
:
0.0
,
'end_time'
:
0.0
,
'track'
:
''
,
'source'
:
''
,
'html5_sources'
:
[],
'data'
:
''
})
def
test_old_video_format
(
self
):
def
test_old_video_format
(
self
):
"""
"""
Test backwards compatibility with VideoModule's XML format.
Test backwards compatibility with VideoModule's XML format.
...
@@ -344,7 +427,7 @@ class VideoExportTestCase(unittest.TestCase):
...
@@ -344,7 +427,7 @@ class VideoExportTestCase(unittest.TestCase):
desc
.
track
=
'http://www.example.com/track'
desc
.
track
=
'http://www.example.com/track'
desc
.
html5_sources
=
[
'http://www.example.com/source.mp4'
,
'http://www.example.com/source.ogg'
]
desc
.
html5_sources
=
[
'http://www.example.com/source.mp4'
,
'http://www.example.com/source.ogg'
]
xml
=
desc
.
export
_to_xml
(
None
)
# We don't use the `resource_fs` parameter
xml
=
desc
.
definition
_to_xml
(
None
)
# We don't use the `resource_fs` parameter
expected
=
dedent
(
'''
\
expected
=
dedent
(
'''
\
<video url_name="SampleProblem1" start_time="0:00:01" youtube="0.75:izygArpw-Qo,1.00:p2Q6BrNhdh8,1.25:1EeWXzPdhSA,1.50:rABDYkeK0x8" show_captions="false" end_time="0:01:00">
<video url_name="SampleProblem1" start_time="0:00:01" youtube="0.75:izygArpw-Qo,1.00:p2Q6BrNhdh8,1.25:1EeWXzPdhSA,1.50:rABDYkeK0x8" show_captions="false" end_time="0:01:00">
<source src="http://www.example.com/source.mp4"/>
<source src="http://www.example.com/source.mp4"/>
...
@@ -353,7 +436,7 @@ class VideoExportTestCase(unittest.TestCase):
...
@@ -353,7 +436,7 @@ class VideoExportTestCase(unittest.TestCase):
</video>
</video>
'''
)
'''
)
self
.
assertEquals
(
expected
,
xml
)
self
.
assertEquals
(
expected
,
etree
.
tostring
(
xml
,
pretty_print
=
True
)
)
def
test_export_to_xml_empty_parameters
(
self
):
def
test_export_to_xml_empty_parameters
(
self
):
"""Test XML export with defaults."""
"""Test XML export with defaults."""
...
@@ -361,7 +444,7 @@ class VideoExportTestCase(unittest.TestCase):
...
@@ -361,7 +444,7 @@ class VideoExportTestCase(unittest.TestCase):
location
=
Location
([
"i4x"
,
"edX"
,
"video"
,
"default"
,
"SampleProblem1"
])
location
=
Location
([
"i4x"
,
"edX"
,
"video"
,
"default"
,
"SampleProblem1"
])
desc
=
VideoDescriptor
(
module_system
,
{
'location'
:
location
})
desc
=
VideoDescriptor
(
module_system
,
{
'location'
:
location
})
xml
=
desc
.
export
_to_xml
(
None
)
xml
=
desc
.
definition
_to_xml
(
None
)
expected
=
'<video url_name="SampleProblem1"/>
\n
'
expected
=
'<video url_name="SampleProblem1"/>
\n
'
self
.
assertEquals
(
expected
,
xml
)
self
.
assertEquals
(
expected
,
etree
.
tostring
(
xml
,
pretty_print
=
True
)
)
common/lib/xmodule/xmodule/video_module.py
View file @
9c67e56d
...
@@ -240,7 +240,7 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
...
@@ -240,7 +240,7 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
video
=
cls
(
system
,
model_data
)
video
=
cls
(
system
,
model_data
)
return
video
return
video
def
export
_to_xml
(
self
,
resource_fs
):
def
definition
_to_xml
(
self
,
resource_fs
):
"""
"""
Returns an xml string representing this module.
Returns an xml string representing this module.
"""
"""
...
@@ -266,7 +266,7 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
...
@@ -266,7 +266,7 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
if
key
in
fields
and
fields
[
key
]
.
default
==
getattr
(
self
,
key
):
if
key
in
fields
and
fields
[
key
]
.
default
==
getattr
(
self
,
key
):
continue
continue
if
value
:
if
value
:
xml
.
set
(
key
,
str
(
value
))
xml
.
set
(
key
,
unicode
(
value
))
for
source
in
self
.
html5_sources
:
for
source
in
self
.
html5_sources
:
ele
=
etree
.
Element
(
'source'
)
ele
=
etree
.
Element
(
'source'
)
...
@@ -277,7 +277,7 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
...
@@ -277,7 +277,7 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
ele
=
etree
.
Element
(
'track'
)
ele
=
etree
.
Element
(
'track'
)
ele
.
set
(
'src'
,
self
.
track
)
ele
.
set
(
'src'
,
self
.
track
)
xml
.
append
(
ele
)
xml
.
append
(
ele
)
return
etree
.
tostring
(
xml
,
pretty_print
=
True
)
return
xml
@staticmethod
@staticmethod
def
_parse_youtube
(
data
):
def
_parse_youtube
(
data
):
...
@@ -287,19 +287,19 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
...
@@ -287,19 +287,19 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
XML-based courses.
XML-based courses.
"""
"""
ret
=
{
'0.75'
:
''
,
'1.00'
:
''
,
'1.25'
:
''
,
'1.50'
:
''
}
ret
=
{
'0.75'
:
''
,
'1.00'
:
''
,
'1.25'
:
''
,
'1.50'
:
''
}
if
data
==
''
:
return
ret
videos
=
data
.
split
(
','
)
videos
=
data
.
split
(
','
)
for
video
in
videos
:
for
video
in
videos
:
pieces
=
video
.
split
(
':'
)
pieces
=
video
.
split
(
':'
)
# HACK
try
:
# To elaborate somewhat: in many LMS tests, the keys for
speed
=
'
%.2
f'
%
float
(
pieces
[
0
])
# normalize speed
# Youtube IDs are inconsistent. Sometimes a particular
# Handle the fact that youtube IDs got double-quoted for a period of time.
# speed isn't present, and formatting is also inconsistent
# Note: we pass in "VideoFields.youtube_id_1_0" so we deserialize as a String--
# ('1.0' versus '1.00'). So it's necessary to either do
# it doesn't matter what the actual speed is for the purposes of deserializing.
# something like this or update all the tests to work
youtube_id
=
VideoDescriptor
.
_deserialize
(
VideoFields
.
youtube_id_1_0
.
name
,
pieces
[
1
])
# properly.
ret
[
speed
]
=
youtube_id
ret
[
'
%.2
f'
%
float
(
pieces
[
0
])]
=
pieces
[
1
]
except
(
ValueError
,
IndexError
):
log
.
warning
(
'Invalid YouTube ID:
%
s'
%
video
)
return
ret
return
ret
@staticmethod
@staticmethod
...
@@ -312,7 +312,6 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
...
@@ -312,7 +312,6 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
model_data
=
{}
model_data
=
{}
conversions
=
{
conversions
=
{
'show_captions'
:
json
.
loads
,
'start_time'
:
VideoDescriptor
.
_parse_time
,
'start_time'
:
VideoDescriptor
.
_parse_time
,
'end_time'
:
VideoDescriptor
.
_parse_time
'end_time'
:
VideoDescriptor
.
_parse_time
}
}
...
@@ -351,10 +350,21 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
...
@@ -351,10 +350,21 @@ class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor
# Convert XML attrs into Python values.
# Convert XML attrs into Python values.
if
attr
in
conversions
:
if
attr
in
conversions
:
value
=
conversions
[
attr
](
value
)
value
=
conversions
[
attr
](
value
)
else
:
# We export values with json.dumps (well, except for Strings, but
# for about a month we did it for Strings also).
value
=
VideoDescriptor
.
_deserialize
(
attr
,
value
)
model_data
[
attr
]
=
value
model_data
[
attr
]
=
value
return
model_data
return
model_data
@classmethod
def
_deserialize
(
cls
,
attr
,
value
):
"""
Handles deserializing values that may have been encoded with json.dumps.
"""
return
cls
.
get_map_for_field
(
attr
)
.
from_xml
(
value
)
@staticmethod
@staticmethod
def
_parse_time
(
str_time
):
def
_parse_time
(
str_time
):
"""Converts s in '12:34:45' format to seconds. If s is
"""Converts s in '12:34:45' format to seconds. If s is
...
...
common/lib/xmodule/xmodule/x_module.py
View file @
9c67e56d
...
@@ -173,11 +173,11 @@ class XModule(XModuleFields, HTMLSnippet, XBlock):
...
@@ -173,11 +173,11 @@ class XModule(XModuleFields, HTMLSnippet, XBlock):
# don't need to set category as it will automatically get from descriptor
# don't need to set category as it will automatically get from descriptor
elif
isinstance
(
self
.
location
,
Location
):
elif
isinstance
(
self
.
location
,
Location
):
self
.
url_name
=
self
.
location
.
name
self
.
url_name
=
self
.
location
.
name
if
not
hasattr
(
self
,
'category'
)
:
if
getattr
(
self
,
'category'
,
None
)
is
None
:
self
.
category
=
self
.
location
.
category
self
.
category
=
self
.
location
.
category
elif
isinstance
(
self
.
location
,
BlockUsageLocator
):
elif
isinstance
(
self
.
location
,
BlockUsageLocator
):
self
.
url_name
=
self
.
location
.
usage_id
self
.
url_name
=
self
.
location
.
usage_id
if
not
hasattr
(
self
,
'category'
)
:
if
getattr
(
self
,
'category'
,
None
)
is
None
:
raise
InsufficientSpecificationError
()
raise
InsufficientSpecificationError
()
else
:
else
:
raise
InsufficientSpecificationError
()
raise
InsufficientSpecificationError
()
...
@@ -467,11 +467,11 @@ class XModuleDescriptor(XModuleFields, HTMLSnippet, ResourceTemplates, XBlock):
...
@@ -467,11 +467,11 @@ class XModuleDescriptor(XModuleFields, HTMLSnippet, ResourceTemplates, XBlock):
self
.
system
=
self
.
runtime
self
.
system
=
self
.
runtime
if
isinstance
(
self
.
location
,
Location
):
if
isinstance
(
self
.
location
,
Location
):
self
.
url_name
=
self
.
location
.
name
self
.
url_name
=
self
.
location
.
name
if
not
hasattr
(
self
,
'category'
)
:
if
getattr
(
self
,
'category'
,
None
)
is
None
:
self
.
category
=
self
.
location
.
category
self
.
category
=
self
.
location
.
category
elif
isinstance
(
self
.
location
,
BlockUsageLocator
):
elif
isinstance
(
self
.
location
,
BlockUsageLocator
):
self
.
url_name
=
self
.
location
.
usage_id
self
.
url_name
=
self
.
location
.
usage_id
if
not
hasattr
(
self
,
'category'
)
:
if
getattr
(
self
,
'category'
,
None
)
is
None
:
raise
InsufficientSpecificationError
()
raise
InsufficientSpecificationError
()
else
:
else
:
raise
InsufficientSpecificationError
()
raise
InsufficientSpecificationError
()
...
...
common/lib/xmodule/xmodule/xml_module.py
View file @
9c67e56d
...
@@ -167,6 +167,11 @@ class XmlDescriptor(XModuleDescriptor):
...
@@ -167,6 +167,11 @@ class XmlDescriptor(XModuleDescriptor):
@classmethod
@classmethod
def
get_map_for_field
(
cls
,
attr
):
def
get_map_for_field
(
cls
,
attr
):
"""
Returns a serialize/deserialize AttrMap for the given field of a class.
Searches through fields defined by cls to find one named attr.
"""
for
field
in
set
(
cls
.
fields
+
cls
.
lms
.
fields
):
for
field
in
set
(
cls
.
fields
+
cls
.
lms
.
fields
):
if
field
.
name
==
attr
:
if
field
.
name
==
attr
:
from_xml
=
lambda
val
:
deserialize_field
(
field
,
val
)
from_xml
=
lambda
val
:
deserialize_field
(
field
,
val
)
...
...
lms/djangoapps/courseware/grades.py
View file @
9c67e56d
...
@@ -358,6 +358,8 @@ def get_score(course_id, user, problem_descriptor, module_creator, model_data_ca
...
@@ -358,6 +358,8 @@ def get_score(course_id, user, problem_descriptor, module_creator, model_data_ca
# with the LMS, so they need to always be scored. (E.g. foldit.)
# with the LMS, so they need to always be scored. (E.g. foldit.)
if
problem_descriptor
.
always_recalculate_grades
:
if
problem_descriptor
.
always_recalculate_grades
:
problem
=
module_creator
(
problem_descriptor
)
problem
=
module_creator
(
problem_descriptor
)
if
problem
is
None
:
return
(
None
,
None
)
score
=
problem
.
get_score
()
score
=
problem
.
get_score
()
if
score
is
not
None
:
if
score
is
not
None
:
return
(
score
[
'score'
],
score
[
'total'
])
return
(
score
[
'score'
],
score
[
'total'
])
...
...
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