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
5fee1a49
Commit
5fee1a49
authored
Jan 30, 2013
by
Vik Paruchuri
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Document image class, fix logging and scoring issues
parent
48402055
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
110 additions
and
49 deletions
+110
-49
common/lib/xmodule/xmodule/combined_open_ended_module.py
+26
-23
common/lib/xmodule/xmodule/open_ended_image_submission.py
+65
-10
common/lib/xmodule/xmodule/open_ended_module.py
+10
-9
common/lib/xmodule/xmodule/openendedchild.py
+6
-4
common/lib/xmodule/xmodule/self_assessment_module.py
+3
-3
No files found.
common/lib/xmodule/xmodule/combined_open_ended_module.py
View file @
5fee1a49
...
@@ -38,9 +38,12 @@ MAX_SCORE = 1
...
@@ -38,9 +38,12 @@ MAX_SCORE = 1
#The highest score allowed for the overall xmodule and for each rubric point
#The highest score allowed for the overall xmodule and for each rubric point
MAX_SCORE_ALLOWED
=
3
MAX_SCORE_ALLOWED
=
3
IS_SCORED
=
False
IS_SCORED
=
False
ACCEPT_FILE_UPLOAD
=
True
ACCEPT_FILE_UPLOAD
=
True
#Contains all reasonable bool and case combinations of True
TRUE_DICT
=
[
"True"
,
True
,
"TRUE"
,
"true"
]
class
CombinedOpenEndedModule
(
XModule
):
class
CombinedOpenEndedModule
(
XModule
):
"""
"""
This is a module that encapsulates all open ended grading (self assessment, peer assessment, etc).
This is a module that encapsulates all open ended grading (self assessment, peer assessment, etc).
...
@@ -141,31 +144,31 @@ class CombinedOpenEndedModule(XModule):
...
@@ -141,31 +144,31 @@ class CombinedOpenEndedModule(XModule):
#Allow reset is true if student has failed the criteria to move to the next child task
#Allow reset is true if student has failed the criteria to move to the next child task
self
.
allow_reset
=
instance_state
.
get
(
'ready_to_reset'
,
False
)
self
.
allow_reset
=
instance_state
.
get
(
'ready_to_reset'
,
False
)
self
.
max_attempts
=
int
(
self
.
metadata
.
get
(
'attempts'
,
MAX_ATTEMPTS
))
self
.
max_attempts
=
int
(
self
.
metadata
.
get
(
'attempts'
,
MAX_ATTEMPTS
))
self
.
is_scored
=
(
self
.
metadata
.
get
(
'is_graded'
,
IS_SCORED
)
in
[
True
,
"True"
])
self
.
is_scored
=
self
.
metadata
.
get
(
'is_graded'
,
IS_SCORED
)
in
TRUE_DICT
self
.
accept_file_upload
=
(
self
.
metadata
.
get
(
'accept_file_upload'
,
ACCEPT_FILE_UPLOAD
)
in
[
True
,
"True"
])
self
.
accept_file_upload
=
self
.
metadata
.
get
(
'accept_file_upload'
,
ACCEPT_FILE_UPLOAD
)
in
TRUE_DICT
log
.
debug
(
self
.
metadata
.
get
(
'is_graded'
,
IS_SCORED
))
# Used for progress / grading. Currently get credit just for
# Used for progress / grading. Currently get credit just for
# completion (doesn't matter if you self-assessed correct/incorrect).
# completion (doesn't matter if you self-assessed correct/incorrect).
self
.
_max_score
=
int
(
self
.
metadata
.
get
(
'max_score'
,
MAX_SCORE
))
self
.
_max_score
=
int
(
self
.
metadata
.
get
(
'max_score'
,
MAX_SCORE
))
if
self
.
_max_score
>
MAX_SCORE_ALLOWED
:
if
self
.
_max_score
>
MAX_SCORE_ALLOWED
:
error_message
=
"Max score {0} is higher than max score allowed {1}"
.
format
(
self
.
_max_score
,
MAX_SCORE_ALLOWED
)
error_message
=
"Max score {0} is higher than max score allowed {1}"
.
format
(
self
.
_max_score
,
MAX_SCORE_ALLOWED
)
log
.
exception
(
error_message
)
log
.
exception
(
error_message
)
raise
Exception
raise
Exception
rubric_renderer
=
CombinedOpenEndedRubric
(
system
,
True
)
rubric_renderer
=
CombinedOpenEndedRubric
(
system
,
True
)
success
,
rubric_feedback
=
rubric_renderer
.
render_rubric
(
stringify_children
(
definition
[
'rubric'
]))
success
,
rubric_feedback
=
rubric_renderer
.
render_rubric
(
stringify_children
(
definition
[
'rubric'
]))
if
not
success
:
if
not
success
:
error_message
=
"Could not parse rubric : {0}"
.
format
(
definition
[
'rubric'
])
error_message
=
"Could not parse rubric : {0}"
.
format
(
definition
[
'rubric'
])
log
.
exception
(
error_message
)
log
.
exception
(
error_message
)
raise
Exception
raise
Exception
rubric_categories
=
rubric_renderer
.
extract_categories
(
stringify_children
(
definition
[
'rubric'
]))
rubric_categories
=
rubric_renderer
.
extract_categories
(
stringify_children
(
definition
[
'rubric'
]))
for
category
in
rubric_categories
:
for
category
in
rubric_categories
:
if
len
(
category
[
'options'
])
>
(
MAX_SCORE_ALLOWED
+
1
):
if
len
(
category
[
'options'
])
>
(
MAX_SCORE_ALLOWED
+
1
):
error_message
=
"Number of score points in rubric {0} higher than the max allowed, which is {1}"
.
format
(
len
(
category
[
'options'
])
,
MAX_SCORE_ALLOWED
)
error_message
=
"Number of score points in rubric {0} higher than the max allowed, which is {1}"
.
format
(
len
(
category
[
'options'
]),
MAX_SCORE_ALLOWED
)
log
.
exception
(
error_message
)
log
.
exception
(
error_message
)
raise
Exception
raise
Exception
...
@@ -176,7 +179,7 @@ class CombinedOpenEndedModule(XModule):
...
@@ -176,7 +179,7 @@ class CombinedOpenEndedModule(XModule):
'prompt'
:
definition
[
'prompt'
],
'prompt'
:
definition
[
'prompt'
],
'rubric'
:
definition
[
'rubric'
],
'rubric'
:
definition
[
'rubric'
],
'display_name'
:
self
.
display_name
,
'display_name'
:
self
.
display_name
,
'accept_file_upload'
:
self
.
accept_file_upload
,
'accept_file_upload'
:
self
.
accept_file_upload
,
}
}
self
.
task_xml
=
definition
[
'task_xml'
]
self
.
task_xml
=
definition
[
'task_xml'
]
...
@@ -269,13 +272,13 @@ class CombinedOpenEndedModule(XModule):
...
@@ -269,13 +272,13 @@ class CombinedOpenEndedModule(XModule):
elif
current_task_state
is
None
and
self
.
current_task_number
>
0
:
elif
current_task_state
is
None
and
self
.
current_task_number
>
0
:
last_response_data
=
self
.
get_last_response
(
self
.
current_task_number
-
1
)
last_response_data
=
self
.
get_last_response
(
self
.
current_task_number
-
1
)
last_response
=
last_response_data
[
'response'
]
last_response
=
last_response_data
[
'response'
]
current_task_state
=
json
.
dumps
({
current_task_state
=
json
.
dumps
({
'state'
:
self
.
ASSESSING
,
'state'
:
self
.
ASSESSING
,
'version'
:
self
.
STATE_VERSION
,
'version'
:
self
.
STATE_VERSION
,
'max_score'
:
self
.
_max_score
,
'max_score'
:
self
.
_max_score
,
'attempts'
:
0
,
'attempts'
:
0
,
'created'
:
True
,
'created'
:
True
,
'history'
:
[{
'answer'
:
last_response
}],
'history'
:
[{
'answer'
:
last_response
}],
})
})
self
.
current_task
=
child_task_module
(
self
.
system
,
self
.
location
,
self
.
current_task
=
child_task_module
(
self
.
system
,
self
.
location
,
self
.
current_task_parsed_xml
,
self
.
current_task_descriptor
,
self
.
static_data
,
self
.
current_task_parsed_xml
,
self
.
current_task_descriptor
,
self
.
static_data
,
...
@@ -327,8 +330,8 @@ class CombinedOpenEndedModule(XModule):
...
@@ -327,8 +330,8 @@ class CombinedOpenEndedModule(XModule):
'task_count'
:
len
(
self
.
task_xml
),
'task_count'
:
len
(
self
.
task_xml
),
'task_number'
:
self
.
current_task_number
+
1
,
'task_number'
:
self
.
current_task_number
+
1
,
'status'
:
self
.
get_status
(),
'status'
:
self
.
get_status
(),
'display_name'
:
self
.
display_name
,
'display_name'
:
self
.
display_name
,
'accept_file_upload'
:
self
.
accept_file_upload
,
'accept_file_upload'
:
self
.
accept_file_upload
,
}
}
return
context
return
context
...
@@ -587,11 +590,10 @@ class CombinedOpenEndedModule(XModule):
...
@@ -587,11 +590,10 @@ class CombinedOpenEndedModule(XModule):
last_response
=
self
.
get_last_response
(
self
.
current_task_number
)
last_response
=
self
.
get_last_response
(
self
.
current_task_number
)
max_score
=
last_response
[
'max_score'
]
max_score
=
last_response
[
'max_score'
]
score
=
last_response
[
'score'
]
score
=
last_response
[
'score'
]
log
.
debug
(
last_response
)
score_dict
=
{
score_dict
=
{
'score'
:
score
,
'score'
:
score
,
'total'
:
max_score
,
'total'
:
max_score
,
}
}
return
score_dict
return
score_dict
...
@@ -621,6 +623,7 @@ class CombinedOpenEndedModule(XModule):
...
@@ -621,6 +623,7 @@ class CombinedOpenEndedModule(XModule):
return
progress_object
return
progress_object
class
CombinedOpenEndedDescriptor
(
XmlDescriptor
,
EditingDescriptor
):
class
CombinedOpenEndedDescriptor
(
XmlDescriptor
,
EditingDescriptor
):
"""
"""
Module for adding combined open ended questions
Module for adding combined open ended questions
...
...
common/lib/xmodule/xmodule/open_ended_image_submission.py
View file @
5fee1a49
...
@@ -7,7 +7,7 @@ from django.conf import settings
...
@@ -7,7 +7,7 @@ from django.conf import settings
import
pickle
import
pickle
import
logging
import
logging
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
TRUSTED_IMAGE_DOMAINS
=
[
TRUSTED_IMAGE_DOMAINS
=
[
'wikipedia.com'
,
'wikipedia.com'
,
...
@@ -28,17 +28,29 @@ MAX_COLORS_TO_COUNT = 16
...
@@ -28,17 +28,29 @@ MAX_COLORS_TO_COUNT = 16
MAX_COLORS
=
20
MAX_COLORS
=
20
class
ImageProperties
(
object
):
class
ImageProperties
(
object
):
"""
Class to check properties of an image and to validate if they are allowed.
"""
def
__init__
(
self
,
image
):
def
__init__
(
self
,
image
):
"""
Initializes class variables
@param image: Image object (from PIL)
@return: None
"""
self
.
image
=
image
self
.
image
=
image
image_size
=
self
.
image
.
size
image_size
=
self
.
image
.
size
self
.
image_too_large
=
False
self
.
image_too_large
=
False
if
image_size
[
0
]
>
MAX_ALLOWED_IMAGE_DIM
or
image_size
[
1
]
>
MAX_ALLOWED_IMAGE_DIM
:
if
image_size
[
0
]
>
MAX_ALLOWED_IMAGE_DIM
or
image_size
[
1
]
>
MAX_ALLOWED_IMAGE_DIM
:
self
.
image_too_large
=
True
self
.
image_too_large
=
True
if
image_size
[
0
]
>
MAX_IMAGE_DIM
or
image_size
[
1
]
>
MAX_IMAGE_DIM
:
if
image_size
[
0
]
>
MAX_IMAGE_DIM
or
image_size
[
1
]
>
MAX_IMAGE_DIM
:
self
.
image
=
self
.
image
.
resize
((
MAX_IMAGE_DIM
,
MAX_IMAGE_DIM
))
self
.
image
=
self
.
image
.
resize
((
MAX_IMAGE_DIM
,
MAX_IMAGE_DIM
))
self
.
image_size
=
self
.
image
.
size
self
.
image_size
=
self
.
image
.
size
def
count_colors
(
self
):
def
count_colors
(
self
):
"""
Counts the number of colors in an image, and matches them to the max allowed
@return: boolean true if color count is acceptable, false otherwise
"""
colors
=
self
.
image
.
getcolors
(
MAX_COLORS_TO_COUNT
)
colors
=
self
.
image
.
getcolors
(
MAX_COLORS_TO_COUNT
)
if
colors
is
None
:
if
colors
is
None
:
colors
=
MAX_COLORS_TO_COUNT
colors
=
MAX_COLORS_TO_COUNT
...
@@ -50,9 +62,15 @@ class ImageProperties(object):
...
@@ -50,9 +62,15 @@ class ImageProperties(object):
return
too_many_colors
return
too_many_colors
def
get_skin_ratio
(
self
):
def
get_skin_ratio
(
self
):
"""
Gets the ratio of skin tone colors in an image
@return: True if the ratio is low enough to be acceptable, false otherwise
"""
im
=
self
.
image
im
=
self
.
image
skin
=
sum
([
count
for
count
,
rgb
in
im
.
getcolors
(
im
.
size
[
0
]
*
im
.
size
[
1
])
if
rgb
[
0
]
>
60
and
rgb
[
1
]
<
(
rgb
[
0
]
*
0.85
)
and
rgb
[
2
]
<
(
rgb
[
0
]
*
0.7
)
and
rgb
[
1
]
>
(
rgb
[
0
]
*
0.4
)
and
rgb
[
2
]
>
(
rgb
[
0
]
*
0.2
)])
skin
=
sum
([
count
for
count
,
rgb
in
im
.
getcolors
(
im
.
size
[
0
]
*
im
.
size
[
1
])
if
bad_color_val
=
float
(
skin
)
/
float
(
im
.
size
[
0
]
*
im
.
size
[
1
])
rgb
[
0
]
>
60
and
rgb
[
1
]
<
(
rgb
[
0
]
*
0.85
)
and
rgb
[
2
]
<
(
rgb
[
0
]
*
0.7
)
and
rgb
[
1
]
>
(
rgb
[
0
]
*
0.4
)
and
rgb
[
2
]
>
(
rgb
[
0
]
*
0.2
)])
bad_color_val
=
float
(
skin
)
/
float
(
im
.
size
[
0
]
*
im
.
size
[
1
])
if
bad_color_val
>
.
4
:
if
bad_color_val
>
.
4
:
is_okay
=
False
is_okay
=
False
else
:
else
:
...
@@ -61,16 +79,29 @@ class ImageProperties(object):
...
@@ -61,16 +79,29 @@ class ImageProperties(object):
return
is_okay
return
is_okay
def
run_tests
(
self
):
def
run_tests
(
self
):
"""
Does all available checks on an image to ensure that it is okay (size, skin ratio, colors)
@return: Boolean indicating whether or not image passes all checks
"""
image_is_okay
=
self
.
count_colors
()
and
self
.
get_skin_ratio
()
and
not
self
.
image_too_large
image_is_okay
=
self
.
count_colors
()
and
self
.
get_skin_ratio
()
and
not
self
.
image_too_large
log
.
debug
(
"Image too large: {0}"
.
format
(
self
.
image_too_large
))
log
.
debug
(
"Image too large: {0}"
.
format
(
self
.
image_too_large
))
log
.
debug
(
"Image Okay: {0}"
.
format
(
image_is_okay
))
log
.
debug
(
"Image Okay: {0}"
.
format
(
image_is_okay
))
return
image_is_okay
return
image_is_okay
class
URLProperties
(
object
):
class
URLProperties
(
object
):
"""
Checks to see if a URL points to acceptable content. Added to check if students are submitting reasonable
links to the peer grading image functionality of the external grading service.
"""
def
__init__
(
self
,
url_string
):
def
__init__
(
self
,
url_string
):
self
.
url_string
=
url_string
self
.
url_string
=
url_string
def
check_if_parses
(
self
):
def
check_if_parses
(
self
):
"""
Check to see if a URL parses properly
@return: success (True if parses, false if not)
"""
success
=
False
success
=
False
try
:
try
:
self
.
parsed_url
=
urlparse
.
urlparse
(
url_string
)
self
.
parsed_url
=
urlparse
.
urlparse
(
url_string
)
...
@@ -81,6 +112,10 @@ class URLProperties(object):
...
@@ -81,6 +112,10 @@ class URLProperties(object):
return
success
return
success
def
check_suffix
(
self
):
def
check_suffix
(
self
):
"""
Checks the suffix of a url to make sure that it is allowed
@return: True if suffix is okay, false if not
"""
good_suffix
=
False
good_suffix
=
False
for
suffix
in
ALLOWABLE_IMAGE_SUFFIXES
:
for
suffix
in
ALLOWABLE_IMAGE_SUFFIXES
:
if
self
.
url_string
.
endswith
(
suffix
):
if
self
.
url_string
.
endswith
(
suffix
):
...
@@ -89,17 +124,34 @@ class URLProperties(object):
...
@@ -89,17 +124,34 @@ class URLProperties(object):
return
good_suffix
return
good_suffix
def
run_tests
(
self
):
def
run_tests
(
self
):
"""
Runs all available url tests
@return: True if URL passes tests, false if not.
"""
url_is_okay
=
self
.
check_suffix
()
and
self
.
check_if_parses
()
url_is_okay
=
self
.
check_suffix
()
and
self
.
check_if_parses
()
return
url_is_okay
return
url_is_okay
def
run_url_tests
(
url_string
):
def
run_url_tests
(
url_string
):
"""
Creates a URLProperties object and runs all tests
@param url_string: A URL in string format
@return: Boolean indicating whether or not URL has passed all tests
"""
url_properties
=
URLProperties
(
url_string
)
url_properties
=
URLProperties
(
url_string
)
return
url_properties
.
run_tests
()
return
url_properties
.
run_tests
()
def
run_image_tests
(
image
):
def
run_image_tests
(
image
):
"""
Runs all available image tests
@param image: PIL Image object
@return: Boolean indicating whether or not all tests have been passed
"""
image_properties
=
ImageProperties
(
image
)
image_properties
=
ImageProperties
(
image
)
return
image_properties
.
run_tests
()
return
image_properties
.
run_tests
()
def
upload_to_s3
(
file_to_upload
,
keyname
):
def
upload_to_s3
(
file_to_upload
,
keyname
):
'''
'''
Upload file to S3 using provided keyname.
Upload file to S3 using provided keyname.
...
@@ -124,19 +176,22 @@ def upload_to_s3(file_to_upload, keyname):
...
@@ -124,19 +176,22 @@ def upload_to_s3(file_to_upload, keyname):
#k.set_metadata("Content-Type", 'images/png')
#k.set_metadata("Content-Type", 'images/png')
k
.
set_acl
(
"public-read"
)
k
.
set_acl
(
"public-read"
)
public_url
=
k
.
generate_url
(
60
*
60
*
24
*
365
)
# URL timeout in seconds.
public_url
=
k
.
generate_url
(
60
*
60
*
24
*
365
)
# URL timeout in seconds.
return
True
,
public_url
return
True
,
public_url
except
:
except
:
return
False
,
"Could not connect to S3."
return
False
,
"Could not connect to S3."
def
get_from_s3
(
s3_public_url
):
def
get_from_s3
(
s3_public_url
):
"""
Gets an image from a given S3 url
@param s3_public_url: The URL where an image is located
@return: The image data
"""
r
=
requests
.
get
(
s3_public_url
,
timeout
=
2
)
r
=
requests
.
get
(
s3_public_url
,
timeout
=
2
)
data
=
r
.
text
data
=
r
.
text
return
data
return
data
def
convert_image_to_string
(
image
):
return
image
.
tostring
()
common/lib/xmodule/xmodule/open_ended_module.py
View file @
5fee1a49
...
@@ -378,9 +378,9 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
...
@@ -378,9 +378,9 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
Return error message or feedback template
Return error message or feedback template
"""
"""
rubric_feedback
=
""
rubric_feedback
=
""
feedback
=
self
.
_convert_longform_feedback_to_html
(
response_items
)
feedback
=
self
.
_convert_longform_feedback_to_html
(
response_items
)
if
response_items
[
'rubric_scores_complete'
]
==
True
:
if
response_items
[
'rubric_scores_complete'
]
==
True
:
rubric_renderer
=
CombinedOpenEndedRubric
(
system
,
True
)
rubric_renderer
=
CombinedOpenEndedRubric
(
system
,
True
)
success
,
rubric_feedback
=
rubric_renderer
.
render_rubric
(
response_items
[
'rubric_xml'
])
success
,
rubric_feedback
=
rubric_renderer
.
render_rubric
(
response_items
[
'rubric_xml'
])
...
@@ -392,7 +392,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
...
@@ -392,7 +392,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
'grader_type'
:
response_items
[
'grader_type'
],
'grader_type'
:
response_items
[
'grader_type'
],
'score'
:
"{0} / {1}"
.
format
(
response_items
[
'score'
],
self
.
max_score
()),
'score'
:
"{0} / {1}"
.
format
(
response_items
[
'score'
],
self
.
max_score
()),
'feedback'
:
feedback
,
'feedback'
:
feedback
,
'rubric_feedback'
:
rubric_feedback
'rubric_feedback'
:
rubric_feedback
})
})
return
feedback_template
return
feedback_template
...
@@ -447,8 +447,8 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
...
@@ -447,8 +447,8 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
'success'
:
score_result
[
'success'
],
'success'
:
score_result
[
'success'
],
'grader_id'
:
score_result
[
'grader_id'
][
i
],
'grader_id'
:
score_result
[
'grader_id'
][
i
],
'submission_id'
:
score_result
[
'submission_id'
],
'submission_id'
:
score_result
[
'submission_id'
],
'rubric_scores_complete'
:
score_result
[
'rubric_scores_complete'
][
i
],
'rubric_scores_complete'
:
score_result
[
'rubric_scores_complete'
][
i
],
'rubric_xml'
:
score_result
[
'rubric_xml'
][
i
],
'rubric_xml'
:
score_result
[
'rubric_xml'
][
i
],
}
}
feedback_items
.
append
(
self
.
_format_feedback
(
new_score_result
,
system
))
feedback_items
.
append
(
self
.
_format_feedback
(
new_score_result
,
system
))
if
join_feedback
:
if
join_feedback
:
...
@@ -475,7 +475,8 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
...
@@ -475,7 +475,8 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
if
not
self
.
history
:
if
not
self
.
history
:
return
""
return
""
feedback_dict
=
self
.
_parse_score_msg
(
self
.
history
[
-
1
]
.
get
(
'post_assessment'
,
""
),
system
,
join_feedback
=
join_feedback
)
feedback_dict
=
self
.
_parse_score_msg
(
self
.
history
[
-
1
]
.
get
(
'post_assessment'
,
""
),
system
,
join_feedback
=
join_feedback
)
if
not
short_feedback
:
if
not
short_feedback
:
return
feedback_dict
[
'feedback'
]
if
feedback_dict
[
'valid'
]
else
''
return
feedback_dict
[
'feedback'
]
if
feedback_dict
[
'valid'
]
else
''
if
feedback_dict
[
'valid'
]:
if
feedback_dict
[
'valid'
]:
...
@@ -565,8 +566,8 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
...
@@ -565,8 +566,8 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
return
{
return
{
'success'
:
True
,
'success'
:
True
,
'error'
:
error_message
,
'error'
:
error_message
,
'student_response'
:
get
[
'student_answer'
]
'student_response'
:
get
[
'student_answer'
]
}
}
def
update_score
(
self
,
get
,
system
):
def
update_score
(
self
,
get
,
system
):
...
@@ -611,7 +612,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
...
@@ -611,7 +612,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
'msg'
:
post_assessment
,
'msg'
:
post_assessment
,
'child_type'
:
'openended'
,
'child_type'
:
'openended'
,
'correct'
:
correct
,
'correct'
:
correct
,
'accept_file_upload'
:
self
.
accept_file_upload
,
'accept_file_upload'
:
self
.
accept_file_upload
,
}
}
html
=
system
.
render_template
(
'open_ended.html'
,
context
)
html
=
system
.
render_template
(
'open_ended.html'
,
context
)
return
html
return
html
...
...
common/lib/xmodule/xmodule/openendedchild.py
View file @
5fee1a49
...
@@ -140,7 +140,9 @@ class OpenEndedChild(object):
...
@@ -140,7 +140,9 @@ class OpenEndedChild(object):
def
sanitize_html
(
answer
):
def
sanitize_html
(
answer
):
try
:
try
:
answer
=
autolink_html
(
answer
)
answer
=
autolink_html
(
answer
)
cleaner
=
Cleaner
(
style
=
True
,
links
=
True
,
add_nofollow
=
False
,
page_structure
=
True
,
safe_attrs_only
=
True
,
host_whitelist
=
open_ended_image_submission
.
TRUSTED_IMAGE_DOMAINS
,
whitelist_tags
=
set
([
'embed'
,
'iframe'
,
'a'
,
'img'
]))
cleaner
=
Cleaner
(
style
=
True
,
links
=
True
,
add_nofollow
=
False
,
page_structure
=
True
,
safe_attrs_only
=
True
,
host_whitelist
=
open_ended_image_submission
.
TRUSTED_IMAGE_DOMAINS
,
whitelist_tags
=
set
([
'embed'
,
'iframe'
,
'a'
,
'img'
]))
clean_html
=
cleaner
.
clean_html
(
answer
)
clean_html
=
cleaner
.
clean_html
(
answer
)
clean_html
=
re
.
sub
(
r'</p>$'
,
''
,
re
.
sub
(
r'^<p>'
,
''
,
clean_html
))
clean_html
=
re
.
sub
(
r'</p>$'
,
''
,
re
.
sub
(
r'^<p>'
,
''
,
clean_html
))
except
:
except
:
...
@@ -309,10 +311,10 @@ class OpenEndedChild(object):
...
@@ -309,10 +311,10 @@ class OpenEndedChild(object):
def
check_for_image_and_upload
(
self
,
get_data
):
def
check_for_image_and_upload
(
self
,
get_data
):
has_file_to_upload
=
False
has_file_to_upload
=
False
success
=
False
success
=
False
image_tag
=
""
image_tag
=
""
if
'can_upload_files'
in
get_data
:
if
'can_upload_files'
in
get_data
:
if
get_data
[
'can_upload_files'
]
==
'true'
:
if
get_data
[
'can_upload_files'
]
==
'true'
:
has_file_to_upload
=
True
has_file_to_upload
=
True
file
=
get_data
[
'student_file'
][
0
]
file
=
get_data
[
'student_file'
][
0
]
success
,
s3_public_url
=
self
.
upload_image_to_s3
(
file
)
success
,
s3_public_url
=
self
.
upload_image_to_s3
(
file
)
...
...
common/lib/xmodule/xmodule/self_assessment_module.py
View file @
5fee1a49
...
@@ -80,7 +80,7 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
...
@@ -80,7 +80,7 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
'state'
:
self
.
state
,
'state'
:
self
.
state
,
'allow_reset'
:
self
.
_allow_reset
(),
'allow_reset'
:
self
.
_allow_reset
(),
'child_type'
:
'selfassessment'
,
'child_type'
:
'selfassessment'
,
'accept_file_upload'
:
self
.
accept_file_upload
,
'accept_file_upload'
:
self
.
accept_file_upload
,
}
}
html
=
system
.
render_template
(
'self_assessment_prompt.html'
,
context
)
html
=
system
.
render_template
(
'self_assessment_prompt.html'
,
context
)
...
@@ -215,8 +215,8 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
...
@@ -215,8 +215,8 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
return
{
return
{
'success'
:
success
,
'success'
:
success
,
'rubric_html'
:
self
.
get_rubric_html
(
system
),
'rubric_html'
:
self
.
get_rubric_html
(
system
),
'error'
:
error_message
,
'error'
:
error_message
,
'student_response'
:
get
[
'student_answer'
],
'student_response'
:
get
[
'student_answer'
],
}
}
def
save_assessment
(
self
,
get
,
system
):
def
save_assessment
(
self
,
get
,
system
):
...
...
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