Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
crowdsourcehinter
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
OpenEdx
crowdsourcehinter
Commits
7667b206
Commit
7667b206
authored
Apr 13, 2015
by
solashirai
Committed by
Piotr Mitros
Oct 12, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
code improvement
parent
14587bca
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
97 additions
and
80 deletions
+97
-80
crowdsourcehinter/crowdsourcehinter.py
+7
-7
crowdsourcehinter/static/html/crowdsourcehinter.html
+1
-1
crowdsourcehinter/static/js/src/crowdsourcehinter.js
+89
-72
No files found.
crowdsourcehinter/crowdsourcehinter.py
View file @
7667b206
...
...
@@ -102,7 +102,7 @@ class CrowdsourceHinter(XBlock):
frag
.
add_javascript_url
(
'//cdnjs.cloudflare.com/ajax/libs/mustache.js/0.8.1/mustache.min.js'
)
frag
.
add_css
(
self
.
resource_string
(
"static/css/crowdsourcehinter.css"
))
frag
.
add_javascript
(
self
.
resource_string
(
"static/js/src/crowdsourcehinter.js"
))
frag
.
initialize_js
(
'CrowdsourceHinter'
,
{
'hinting_element'
:
self
.
Element
,
'isStaff'
:
self
.
Element
})
frag
.
initialize_js
(
'CrowdsourceHinter'
,
{
'hinting_element'
:
self
.
Element
,
'isStaff'
:
self
.
xmodule_runtime
.
user_is_staff
})
return
frag
@XBlock.json_handler
...
...
@@ -115,7 +115,7 @@ class CrowdsourceHinter(XBlock):
data['submittedanswer']: The string of text that the student submits for a problem.
returns:
'Hints
ToUse
': the highest rated hint for an incorrect answer
'Hints': the highest rated hint for an incorrect answer
or another random hint for an incorrect answer
or 'Sorry, there are no more hints for this answer.' if no more hints exist
"""
...
...
@@ -146,12 +146,12 @@ class CrowdsourceHinter(XBlock):
# currently set by default to True
if
best_hint
not
in
self
.
Reported
.
keys
():
self
.
Used
.
append
(
best_hint
)
return
{
'Hints
ToUse
'
:
best_hint
,
"StudentAnswer"
:
answer
}
return
{
'Hints'
:
best_hint
,
"StudentAnswer"
:
answer
}
if
best_hint
not
in
self
.
Used
:
# choose highest rated hint for the incorrect answer
if
best_hint
not
in
self
.
Reported
.
keys
():
self
.
Used
.
append
(
best_hint
)
return
{
'Hints
ToUse
'
:
best_hint
,
"StudentAnswer"
:
answer
}
return
{
'Hints'
:
best_hint
,
"StudentAnswer"
:
answer
}
# choose another random hint for the answer.
temporary_hints_list
=
[]
for
hint_keys
in
self
.
hint_database
[
str
(
answer
)]:
...
...
@@ -160,16 +160,16 @@ class CrowdsourceHinter(XBlock):
temporary_hints_list
.
append
(
str
(
hint_keys
))
not_used
=
random
.
choice
(
temporary_hints_list
)
self
.
Used
.
append
(
not_used
)
return
{
'Hints
ToUse
'
:
not_used
,
"StudentAnswer"
:
answer
}
return
{
'Hints'
:
not_used
,
"StudentAnswer"
:
answer
}
# find generic hints for the student if no specific hints exist
if
len
(
self
.
generic_hints
)
!=
0
:
not_used
=
random
.
choice
(
self
.
generic_hints
)
self
.
Used
.
append
(
not_used
)
return
{
'Hints
ToUse
'
:
not_used
,
"StudentAnswer"
:
answer
}
return
{
'Hints'
:
not_used
,
"StudentAnswer"
:
answer
}
else
:
# if there are no more hints left in either the database or defaults
self
.
Used
.
append
(
str
(
"There are no hints for"
+
" "
+
answer
))
return
{
'Hints
ToUse
'
:
"Sorry, there are no hints for this answer."
,
"StudentAnswer"
:
answer
}
return
{
'Hints'
:
"Sorry, there are no hints for this answer."
,
"StudentAnswer"
:
answer
}
def
find_hints
(
self
,
answer
):
"""
...
...
crowdsourcehinter/static/html/crowdsourcehinter.html
View file @
7667b206
...
...
@@ -62,7 +62,7 @@
<div
class=
"crowdsourcehinter_block"
>
<div
class=
'csh_hint_reveal'
>
<div
class=
'csh_Hints
ToUse
'
student_answer =
''
hint_received=
''
>
<div
class=
'csh_Hints'
student_answer =
''
hint_received=
''
>
</div>
<div
class=
'csh_HintQuickFeedback'
>
<div
role=
"button"
class=
"csh_rate_hint"
data-rate=
"upvote"
title=
"This hint was helpful!"
>
...
...
crowdsourcehinter/static/js/src/crowdsourcehinter.js
View file @
7667b206
...
...
@@ -4,10 +4,13 @@ function CrowdsourceHinter(runtime, element, data){
var
executeHinter
=
true
;
$
(
".crowdsourcehinter_block"
,
element
).
hide
();
if
(
executeHinter
){
if
(
!
executeHinter
){
return
;
}
var
isShowingHintFeedback
=
false
;
var
voted
=
false
;
$
(
".csh_HintsToUse"
,
element
).
text
(
""
)
;
var
correctSubmission
=
false
;
function
stopScript
(){
//This function is used to prevent a particular instance of the hinter from acting after
...
...
@@ -18,44 +21,52 @@ function CrowdsourceHinter(runtime, element, data){
Logger
.
listen
(
'seq_prev'
,
null
,
stopScript
);
Logger
.
listen
(
'seq_goto'
,
null
,
stopScript
);
//data about the problem obtained from Logger.listen('problem_graded') is passed on to the onStudentSubmission.
//directly passing data to onStudentSubmission does not appear to work
function
get_event_data
(
event_type
,
data
,
element
){
onStudentSubmission
(
data
);
//send student answer data and receive a hint from ajax call.
//pass data to showHint to actually show hint to student
function
get_hint
(
data
){
$
(
".crowdsourcehinter_block"
,
element
).
show
();
$
.
ajax
({
type
:
"POST"
,
url
:
runtime
.
handlerUrl
(
element
,
'get_hint'
),
data
:
JSON
.
stringify
({
"submittedanswer"
:
unescape
(
data
[
0
])}),
success
:
showHint
});
}
Logger
.
listen
(
'problem_graded'
,
data
.
hinting_element
,
get_event_data
);
function
onStudentSubmission
(
problem_graded_event_data
){
//This function will determine whether or not the student correctly answered the question.
//If it was correctly answered it will begin the process for giving feedback on hints.
if
(
problem_graded_event_data
[
1
].
search
(
/class="correct/
)
===
-
1
){
$
(
".crowdsourcehinter_block"
,
element
).
show
();
$
.
ajax
({
type
:
"POST"
,
url
:
runtime
.
handlerUrl
(
element
,
'get_hint'
),
data
:
JSON
.
stringify
({
"submittedanswer"
:
unescape
(
problem_graded_event_data
[
0
])}),
success
:
seehint
});
}
else
{
$
(
'.csh_correct'
,
element
).
show
();
$
(
".csh_hint_reveal"
,
element
).
hide
();
//send empty data for ajax call because not having a data field causes error
$
.
ajax
({
type
:
"POST"
,
url
:
runtime
.
handlerUrl
(
element
,
'get_feedback'
),
data
:
JSON
.
stringify
({}),
success
:
getFeedback
});
}
//first step to starting student feedback for hints
//this function will be called after student correctly answers question
function
start_feedback
(){
$
(
'.csh_correct'
,
element
).
show
();
$
(
".csh_hint_reveal"
,
element
).
hide
();
//send empty data for ajax call because not having a data field causes error
$
.
ajax
({
type
:
"POST"
,
url
:
runtime
.
handlerUrl
(
element
,
'get_feedback'
),
data
:
JSON
.
stringify
({}),
success
:
showStudentContribution
});
}
function
seehint
(
result
){
//Show a hint to the student after an incorrect answer is submitted.
$
(
'.csh_HintsToUse'
,
element
).
attr
(
'student_answer'
,
result
.
StudentAnswer
);
$
(
'.csh_HintsToUse'
,
element
).
attr
(
'hint_received'
,
result
.
HintsToUse
);
$
(
'.csh_HintsToUse'
,
element
).
text
(
"Hint: "
+
result
.
HintsToUse
);
Logger
.
log
(
'crowd_hinter.seehint'
,
{
"student_answer"
:
result
.
StudentAnswer
,
"hint_received"
:
result
.
HintsToUse
});
//This function will determine whether or not the student correctly answered the question.
//if incorrect, call function to get hint to show to student
//if correct, call function to start student feedback on hints
function
onStudentSubmission
(){
return
function
(
event_type
,
data
,
element
){
//search method of correctness of problem is brittle due to checking for a class within
//the problem block.
if
(
data
[
1
].
search
(
/class="correct/
)
===
-
1
){
get_hint
(
data
);
}
else
{
//if the correct answer is submitted
start_feedback
();
}
}}
Logger
.
listen
(
'problem_graded'
,
data
.
hinting_element
,
onStudentSubmission
());
function
showHint
(
result
){
//Show a hint to the student after an incorrect answer is submitted.
$
(
'.csh_Hints'
,
element
).
attr
(
'student_answer'
,
result
.
StudentAnswer
);
$
(
'.csh_Hints'
,
element
).
attr
(
'hint_received'
,
result
.
Hints
);
$
(
'.csh_Hints'
,
element
).
text
(
"Hint: "
+
result
.
Hints
);
Logger
.
log
(
'crowd_hinter.showHint'
,
{
"student_answer"
:
result
.
StudentAnswer
,
"hint_received"
:
result
.
Hints
});
}
function
showHintFeedback
(
hint
,
student_answer
){
...
...
@@ -93,7 +104,7 @@ function CrowdsourceHinter(runtime, element, data){
$
(
".csh_reported_hints"
,
element
).
append
(
html
);
}
function
s
etStudentAnswers
(
student_answers
){
function
s
howStudentSubmissionHistory
(
student_answers
){
//Append new divisions into html for each answer the student submitted before correctly
//answering the question. showHintFeedback appends new hints into these divs.
//When the hinter is set to show best, only one div will be created
...
...
@@ -106,7 +117,7 @@ function CrowdsourceHinter(runtime, element, data){
$
(
".csh_feedback"
,
element
).
append
(
html
);
}
function
getFeedback
(
result
){
function
showStudentContribution
(
result
){
//Set up the student feedback stage. Each student answer and all answer-specific hints for that answer are shown
//to the student, as well as an option to create a new hint for an answer.
if
(
data
.
isStaff
){
...
...
@@ -121,7 +132,7 @@ function CrowdsourceHinter(runtime, element, data){
if
(
!
isShowingHintFeedback
){
$
.
each
(
result
,
function
(
index
,
value
)
{
if
(
value
!=
"Reported"
){
s
etStudentAnswers
(
value
);
s
howStudentSubmissionHistory
(
value
);
student_answer
=
value
;
hint
=
index
;
//hints return null if no answer-specific hints exist
...
...
@@ -151,17 +162,17 @@ function CrowdsourceHinter(runtime, element, data){
}
}
$
(
element
).
on
(
'click'
,
'.csh_student_hint_creation'
,
function
(
){
function
create_text_input
(){
return
function
(
clicked
){
//create text input area for contributing a new hint
$
(
'.csh_student_hint_creation'
,
element
).
each
(
function
(){
$
(
this
).
show
();
$
(
clicked
.
currentTarget
).
show
();
});
$
(
'.csh_student_text_input'
,
element
).
remove
();
$
(
'.csh_submit_new'
,
element
).
remove
();
$
(
this
).
hide
();
student_answer
=
$
(
this
).
parent
().
parent
().
find
(
'.csh_answer_text'
).
attr
(
'answer'
);
$
(
clicked
.
currentTarget
).
hide
();
student_answer
=
$
(
clicked
.
currentTarget
).
parent
().
parent
().
find
(
'.csh_answer_text'
).
attr
(
'answer'
);
$
(
".csh_student_answer"
,
element
).
each
(
function
(){
if
(
$
(
this
).
find
(
'.csh_answer_text'
).
attr
(
'answer'
)
==
student_answer
){
if
(
$
(
'.csh_answer_text'
,
element
).
attr
(
'answer'
)
==
student_answer
){
var
html
=
""
;
$
(
function
(){
var
template
=
$
(
'#student_hint_creation'
).
html
();
...
...
@@ -171,12 +182,13 @@ function CrowdsourceHinter(runtime, element, data){
$
(
this
).
append
(
html
);
}
});
})
}}
$
(
element
).
on
(
'click'
,
'.csh_student_hint_creation'
,
create_text_input
(
$
(
this
)));
$
(
element
).
on
(
'click'
,
'.csh_submit_new'
,
function
(
){
function
submit_new_hint
(){
return
function
(
clicked
){
//add the newly created hint to the hinter's pool of hints
if
(
$
(
this
).
parent
().
parent
().
find
(
'.csh_student_text_input'
).
val
().
length
>
0
){
var
answerdata
=
unescape
(
$
(
this
).
attr
(
'answer'
)
);
if
(
$
(
'.csh_student_text_input'
,
element
).
val
().
length
>
0
){
var
answerdata
=
unescape
(
clicked
.
currentTarget
.
attributes
[
'answer'
].
value
);
var
newhint
=
unescape
(
$
(
'.csh_student_text_input'
).
val
());
$
(
'.csh_submitbutton'
,
element
).
show
();
$
.
ajax
({
...
...
@@ -185,28 +197,31 @@ function CrowdsourceHinter(runtime, element, data){
data
:
JSON
.
stringify
({
"submission"
:
newhint
,
"answer"
:
answerdata
}),
success
:
Logger
.
log
(
'crowd_hinter.submit_new.click.event'
,
{
"student_answer"
:
answerdata
,
"new_hint_submission"
:
newhint
})
});
$
(
this
).
parent
().
parent
().
find
(
'.csh_student_text_input'
).
remove
();
$
(
this
).
remove
();
$
(
'.csh_student_text_input'
,
element
).
remove
();
$
(
clicked
.
currentTarget
).
remove
();
}
})
}}
$
(
element
).
on
(
'click'
,
'.csh_submit_new'
,
submit_new_hint
(
$
(
this
)));
$
(
element
).
on
(
'click'
,
'.csh_rate_hint'
,
function
(
){
function
rate_hint
(){
return
function
(
clicked
){
//send info to hinter indicating whether the hint was upvoted, downvoted, or reported
if
(
!
voted
||
$
(
this
).
attr
(
'data-rate'
)
==
"report"
){
if
(
$
(
this
).
attr
(
'data-rate'
)
==
"report"
){
alert
(
"This hint has been reported for review."
);
}
hint
=
$
(
'.csh_HintsToUse'
,
element
).
attr
(
'hint_received'
);
student_answer
=
$
(
'.csh_HintsToUse'
,
element
).
attr
(
'student_answer'
);
$
.
ajax
({
type
:
"POST"
,
url
:
runtime
.
handlerUrl
(
element
,
'rate_hint'
),
data
:
JSON
.
stringify
({
"student_rating"
:
$
(
this
).
attr
(
'data-rate'
),
"hint"
:
hint
,
"student_answer"
:
student_answer
}),
success
:
Logger
.
log
(
'crowd_hinter.rate_hint.click.event'
,
{
"hint"
:
hint
,
"student_answer"
:
student_answer
,
"rating"
:
$
(
this
).
attr
(
'data-rate'
)})
});
voted
=
true
;
}
});
rating
=
clicked
.
currentTarget
.
attributes
[
'data-rate'
].
value
;
if
(
!
voted
||
rating
==
"report"
){
if
(
rating
==
"report"
){
alert
(
"This hint has been reported for review."
);
}
hint
=
$
(
'.csh_Hints'
,
element
).
attr
(
'hint_received'
);
student_answer
=
$
(
'.csh_Hints'
,
element
).
attr
(
'student_answer'
);
$
.
ajax
({
type
:
"POST"
,
url
:
runtime
.
handlerUrl
(
element
,
'rate_hint'
),
data
:
JSON
.
stringify
({
"student_rating"
:
rating
,
"hint"
:
hint
,
"student_answer"
:
student_answer
}),
success
:
Logger
.
log
(
'crowd_hinter.rate_hint.click.event'
,
{
"hint"
:
hint
,
"student_answer"
:
student_answer
,
"rating"
:
rating
})
});
voted
=
true
;
}
}}
$
(
element
).
on
(
'click'
,
'.csh_rate_hint'
,
rate_hint
(
$
(
this
)));
function
removeFeedback
(){
//remove a hint from the staff feedback area after a staff member has
...
...
@@ -218,17 +233,19 @@ function CrowdsourceHinter(runtime, element, data){
});
}
$
(
element
).
on
(
'click'
,
'.csh_staff_rate'
,
function
(
){
function
staff_rate_hint
(){
return
function
(
clicked
){
//Staff "rating" removes or returns a reported hint from/to the hinter's pool of hints
hint
=
$
(
this
).
parent
().
find
(
".csh_hint"
).
text
();
hint
=
$
(
clicked
.
currentTarget
).
parent
().
find
(
".csh_hint"
).
text
();
rating
=
clicked
.
currentTarget
.
attributes
[
'data-rate'
].
value
student_answer
=
"Reported"
;
Logger
.
log
(
'crowd_hinter.staff_rate_hint.click.event'
,
{
"hint"
:
hint
,
"student_answer"
:
student_answer
,
"rating"
:
$
(
this
).
attr
(
'data-rate'
)
});
Logger
.
log
(
'crowd_hinter.staff_rate_hint.click.event'
,
{
"hint"
:
hint
,
"student_answer"
:
student_answer
,
"rating"
:
rating
});
$
.
ajax
({
type
:
"POST"
,
url
:
runtime
.
handlerUrl
(
element
,
'rate_hint'
),
data
:
JSON
.
stringify
({
"student_rating"
:
$
(
this
).
attr
(
'data-rate'
)
,
"hint"
:
hint
,
"student_answer"
:
student_answer
}),
data
:
JSON
.
stringify
({
"student_rating"
:
rating
,
"hint"
:
hint
,
"student_answer"
:
student_answer
}),
success
:
removeFeedback
()
});
})
}}
$
(
element
).
on
(
'click'
,
'.csh_staff_rate'
,
staff_rate_hint
(
$
(
this
)));
}
}
}
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