Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
David Paul
Python3 Automarker
Commits
35f66844
Commit
35f66844
authored
Mar 22, 2022
by
David Paul
Browse files
Upgrade to newer versions of libraries and switch to Monaco code editor
parent
4dfd9d89
Changes
13
Expand all
Hide whitespace changes
Inline
Side-by-side
.gitignore
View file @
35f66844
...
...
@@ -25,4 +25,7 @@ Network Trash Folder
Temporary Items
.apdisk
bower_components/*
node_modules/*
package-lock.json
__pycache__/*
LICENSE
View file @
35f66844
MIT License
Copyright (c) 2016 David John Paul
Copyright (c) 2016
-2022
David John Paul
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
...
...
automarker_client.py
View file @
35f66844
...
...
@@ -3,10 +3,13 @@ from browser import alert
from
browser
import
document
from
browser
import
html
from
browser
import
window
jq
=
window
.
jQuery
.
noConflict
(
True
)
window
.
jq
=
jq
;
editor
=
window
.
editor
def
echo_prompt
(
prompt
=
""
):
"""Function to make prompt to input appear properly"""
print
(
prompt
,
end
=
""
)
...
...
@@ -14,17 +17,27 @@ def echo_prompt(prompt = ""):
print
(
value
,
end
=
"
\n
"
)
return
value
def
fake_input
(
prompt
=
""
):
"""Function that avoids input by directly reading standard input, and also echos the prompt"""
print
(
prompt
,
end
=
""
)
value
=
sys
.
stdin
.
readline
()
print
(
value
,
end
=
"
\n
"
)
return
value
class
Output
:
"""Writes output to #output"""
def
write
(
self
,
*
args
):
for
arg
in
args
:
jq
(
"#output"
).
val
(
jq
(
"#output"
).
val
()
+
arg
)
def
display_exercise
(
exercise
):
"""Displays the given exercise"""
window
.
exercise
.
html
=
exercise
.
title
window
.
instructions
.
html
=
exercise
.
instructions
window
.
editor
.
setValue
(
exercise
.
code
,
-
1
)
window
.
editor
.
setValue
(
exercise
.
code
)
window
.
tests
.
clear
()
for
test_id
in
range
(
len
(
exercise
.
tests
)):
test
=
exercise
.
tests
[
test_id
]
...
...
@@ -35,8 +48,9 @@ def display_exercise(exercise):
list_element
.
bind
(
"click"
,
show_test
)
list_element
.
bind
(
"dblclick"
,
run_test
)
window
.
tests
<=
list_element
jq
(
"#output-row"
).
addClass
(
"hidden"
)
jq
(
"#test-row"
).
addClass
(
"hidden"
)
jq
(
"#output-row"
).
addClass
(
"visually-hidden"
)
jq
(
"#test-row"
).
addClass
(
"visually-hidden"
)
def
update_tests
(
remove_active
=
False
):
"""Checks if all tests have passed, removing the active class if requested"""
...
...
@@ -56,32 +70,38 @@ def update_tests(remove_active = False):
if
all_passed
:
jq
(
"#grade"
).
removeClass
(
"disabled"
)
def
display_test
(
id
):
"""Displays the test with the given id"""
update_tests
(
True
)
jq
(
"#output-row"
).
addClass
(
"hidden"
)
jq
(
"#test-row"
).
removeClass
(
"hidden"
)
jq
(
"#output-row"
).
addClass
(
"
visually-
hidden"
)
jq
(
"#test-row"
).
removeClass
(
"
visually-
hidden"
)
jq
(
"#test_%d"
%
id
).
addClass
(
"active"
)
test
=
exercise
.
tests
[
id
]
jq
(
"#expected"
).
val
(
test
.
expected_output
)
jq
(
"#actual"
).
val
(
test
.
actual_output
)
jq
(
"#input"
).
val
(
test
.
input
)
window
.
updateDiff
()
def
show_test
(
ev
):
"""Displays the test that was selected"""
id
=
int
(
ev
.
target
.
id
[
len
(
"test_"
):])
display_test
(
id
)
def
run_test
(
ev
):
"""Runs the test that was selected"""
id
=
int
(
ev
.
target
.
id
[
len
(
"test_"
):])
execute_test
(
exercise
.
tests
[
id
])
display_test
(
id
)
def
get_code
():
"""Gets the code currently in the editor"""
return
window
.
editor
.
getValue
()
def
display_checks
(
code
):
"""Displays alerts for any check that fails - returns True if all checks pass, False otherwise"""
for
check
in
exercise
.
checks
:
...
...
@@ -91,54 +111,62 @@ def display_checks(code):
return
False
return
True
def
execute_test
(
test
):
"""Runs the code to complete a test"""
code
=
get_code
()
if
not
display_checks
(
code
):
return
test
.
run
(
code
,
echo_promp
t
)
test
.
run
(
code
,
fake_inpu
t
)
update_tests
()
def
execute_run
(
*
args
):
"""Runs the code for the user to interact with"""
jq
(
"#test-row"
).
addClass
(
"hidden"
)
jq
(
"#output-row"
).
removeClass
(
"hidden"
)
jq
(
"#test-row"
).
addClass
(
"
visually-
hidden"
)
jq
(
"#output-row"
).
removeClass
(
"
visually-
hidden"
)
jq
(
"#output"
).
val
(
""
)
code
=
get_code
()
execute
(
code
,
output
,
output
,
sys
.
stdin
,
echo_prompt
)
def
execute_tests
(
*
args
):
"""Executes each test for the exercise"""
code
=
get_code
()
if
not
display_checks
(
code
):
return
exercise
.
run
(
code
,
echo_promp
t
)
exercise
.
run
(
code
,
fake_inpu
t
)
display_test
(
0
)
def
grade_code
():
if
jq
(
"#grade"
).
hasClass
(
"disabled"
):
alert
(
"Run all tests successfully to allow grade upload"
)
else
:
window
.
submitGrade
();
def
code_change
(
*
args
):
"""Handles any time the code changes - test results become invalid"""
jq
(
"#warning"
).
text
(
""
)
jq
(
"#output-row"
).
addClass
(
"hidden"
)
jq
(
"#test-row"
).
addClass
(
"hidden"
)
jq
(
"#output-row"
).
addClass
(
"
visually-
hidden"
)
jq
(
"#test-row"
).
addClass
(
"
visually-
hidden"
)
for
test
in
exercise
.
tests
:
test
.
actual_output
=
""
update_tests
(
True
)
output
=
Output
()
exercise
=
get_exercise
(
window
.
exercise_id
)
window
.
exercise
.
html
=
"No Exercise Specified"
window
.
instructions
.
html
=
"No exercise was specified, or the exercise is unavailable. Please contact your instructor."
exercise
=
get_exercise
(
window
.
exercise_id
)
display_exercise
(
exercise
)
document
[
"run"
].
bind
(
"click"
,
execute_run
)
document
[
"test-all"
].
bind
(
"click"
,
execute_tests
)
document
[
"grade"
].
bind
(
"click"
,
grade_code
)
editor
.
on
(
"input"
,
code_change
)
editor
.
on
DidChangeModelContent
(
code_change
)
automarker_server.py
View file @
35f66844
...
...
@@ -2,6 +2,7 @@ from exercise import *
from
exercises
import
*
import
sys
def
get_exercise
(
id
=
0
):
"""Loads the exercise to be completed"""
try
:
...
...
@@ -13,14 +14,17 @@ def get_exercise(id = 0):
return
exercises
[
id
]
original_input
=
input
def
output_input
(
prompt
=
""
):
"""A function to output the value that is input before it is returned."""
value
=
original_input
(
prompt
)
print
(
value
)
return
value
if
__name__
==
"__main__"
:
exercise_id
=
sys
.
argv
[
-
2
]
exercise
=
get_exercise
(
exercise_id
)
...
...
bower.json
deleted
100644 → 0
View file @
4dfd9d89
{
"name"
:
"python-automarker"
,
"authors"
:
[
"David Paul <david@davidjohnpaul.com>"
],
"description"
:
"A Python 3 AutoMarker"
,
"main"
:
""
,
"keywords"
:
[
"python"
,
"automarker"
],
"license"
:
"MIT"
,
"homepage"
:
"https://bitbucket.org/davidjohnpaul/automarker"
,
"ignore"
:
[
"**/.*"
,
"node_modules"
,
"bower_components"
,
"test"
,
"tests"
],
"dependencies"
:
{
"bootstrap"
:
"^3.3.6"
,
"ace"
:
"git://github.com/ajaxorg/ace-builds.git#^1.2.3"
,
"pythonauto"
:
"https://github.com/csev/pythonauto.git"
,
"html5shiv"
:
"^3.7.3"
,
"Brython-3.3.0.tar"
:
"https://github.com/brython-dev/brython/releases/download/3.3.0/Brython-3.3.0.tar.gz"
}
}
exercise.py
View file @
35f66844
...
...
@@ -5,8 +5,9 @@ import traceback
# Pattern to remove Traceback from before an exec call
error_pattern
=
".*?\$exec_\d+.*? "
regex_error
=
re
.
compile
(
error_pattern
,
re
.
DOTALL
)
def
execute
(
code
,
stdout
=
sys
.
stdout
,
stderr
=
sys
.
stderr
,
stdin
=
sys
.
stdin
,
input
=
input
):
def
execute
(
code
,
stdout
=
sys
.
stdout
,
stderr
=
sys
.
stderr
,
stdin
=
sys
.
stdin
,
new_input
=
input
):
"""Executes the given code, with standard output and standard error going to the given values"""
old_stdout
=
sys
.
stdout
old_stderr
=
sys
.
stderr
...
...
@@ -18,35 +19,38 @@ def execute(code, stdout = sys.stdout, stderr = sys.stderr, stdin = sys.stdin, i
try
:
available_vars
=
{}
available_vars
[
"input"
]
=
input
available_vars
[
"input"
]
=
new_
input
exec
(
code
,
available_vars
)
return
True
except
Exception
as
exc
:
msg
=
traceback
.
format_exc
()
msg
=
regex_error
.
sub
(
""
,
msg
,
1
)
print
(
msg
)
exc
.
filename
=
"automarker.py"
traceback
.
print_exception
(
exc
)
return
False
finally
:
sys
.
stdout
=
old_stdout
sys
.
stderr
=
old_stderr
sys
.
stdin
=
old_stdin
class
Test
:
"""A test to run over the given code"""
def
__init__
(
self
,
name
,
expected_output
=
""
,
input
=
""
):
def
__init__
(
self
,
name
,
expected_output
=
""
,
test_input
=
""
):
"""Gives the test the give name, expected output, and input that it will provide when run"""
self
.
name
=
name
self
.
expected_output
=
expected_output
self
.
actual_output
=
""
self
.
input
=
input
self
.
input
=
test_
input
self
.
remaining_input
=
""
def
write
(
self
,
*
args
):
"""Writes the output to the test object"""
for
arg
in
args
:
self
.
actual_output
+=
arg
def
read
(
self
,
*
args
):
"""Reads the input from the test object"""
if
len
(
self
.
remaining_input
)
<=
0
:
...
...
@@ -55,32 +59,38 @@ class Test:
self
.
remaining_input
=
self
.
remaining_input
[
1
:]
return
ret_val
def
readline
(
self
,
*
args
):
"""Reads the input from the test object"""
remaining
=
self
.
remaining_input
.
partition
(
"
\n
"
)
self
.
remaining_input
=
remaining
[
2
]
return
remaining
[
0
]
def
close
(
self
,
*
args
):
"""Allow Test to be stdin"""
pass
def
run
(
self
,
code
,
input
=
input
):
def
run
(
self
,
code
,
new_input
=
input
):
"""Executes this test, returning True if the test passes (False otherwise)"""
self
.
remaining_input
=
self
.
input
self
.
actual_output
=
""
execute
(
code
,
self
,
self
,
self
,
input
)
execute
(
code
,
self
,
self
,
self
,
new_
input
)
return
self
.
actual_output
==
self
.
expected_output
class
Check
:
"""Performs a check on the code"""
def
__init__
(
self
,
text
,
regex
,
ensure_no_match
=
False
):
"""Sets the text and the pattern to match"""
self
.
text
=
text
self
.
regex
=
re
.
compile
(
regex
)
self
.
ensure_no_match
=
ensure_no_match
def
check
(
self
,
code
):
"""Ensures this check succeeds"""
match
=
self
.
regex
.
search
(
code
)
...
...
@@ -88,9 +98,11 @@ class Check:
return
self
.
ensure_no_match
return
not
self
.
ensure_no_match
class
Exercise
:
"""The exercise to be completed"""
def
__init__
(
self
,
title
,
instructions
=
""
,
code
=
""
,
tests
=
[],
checks
=
[]):
"""Sets the title, instructions, initial code, tests, and checks to be performed to complete this exercise"""
self
.
title
=
title
...
...
@@ -98,6 +110,8 @@ class Exercise:
self
.
code
=
code
self
.
tests
=
tests
self
.
checks
=
checks
self
.
filename
=
"Exercise"
def
run_checks
(
self
,
code
):
"""Ensures all checks pass on the given code, returning True if all checks succeed (False otherwise)"""
...
...
@@ -106,13 +120,15 @@ class Exercise:
all_succeeded
=
check
.
check
(
code
)
and
all_succeeded
return
all_succeeded
def
run_tests
(
self
,
code
,
input
=
input
):
def
run_tests
(
self
,
code
,
new_input
=
input
):
"""Runs all tests in this exercise, returning True if all succeed (False otherwise)"""
all_succeeded
=
True
for
test
in
self
.
tests
:
all_succeeded
=
test
.
run
(
code
,
input
)
and
all_succeeded
all_succeeded
=
test
.
run
(
code
,
new_
input
)
and
all_succeeded
return
all_succeeded
def
run
(
self
,
code
,
input
=
input
):
def
run
(
self
,
code
,
new_input
=
input
):
"""Runs all checks and, if they succeed, all tests, returning True if all checks and tests succeed (False otherwise)"""
return
self
.
run_checks
(
code
)
and
self
.
run_tests
(
code
,
input
)
return
self
.
run_checks
(
code
)
and
self
.
run_tests
(
code
,
new_
input
)
grade.php
View file @
35f66844
<?php
# Based on https://github.com/csev/pythonauto/blob/master/grade.php
require_once
(
'
bower_components/pythonauto/
util/lti_util.php'
);
require_once
(
'
lti_
util/lti_util.php'
);
session_start
();
if
(
isset
(
$_REQUEST
[
"exercise"
])
&&
preg_match
(
"/^\d+$/"
,
$_REQUEST
[
"exercise"
]))
{
...
...
index.php
View file @
35f66844
<?php
session_start
();
require_once
(
"
bower_components/pythonauto/
util/lti_util.php"
);
require_once
(
"
lti_
util/lti_util.php"
);
?>
<!DOCTYPE html>
<html>
<head>
<title>
Python Automarker
</title>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0"
>
<link
href=
"
bower_component
s/bootstrap/dist/css/bootstrap.min.css"
rel=
"stylesheet"
media=
"screen"
>
<link
href=
"css/automarker.css"
rel=
"stylesheet"
media=
"screen"
>
<link
href=
"
node_module
s/bootstrap/dist/css/bootstrap.min.css"
rel=
"stylesheet"
media=
"screen"
/
>
<link
href=
"css/automarker.css"
rel=
"stylesheet"
media=
"screen"
/
>
<!--[if lt IE 9]>
<script src="
bower_component
s/html5shiv/dist/html5shiv-printshiv.min.js"></script>
<script src="
node_module
s/html5shiv/dist/html5shiv-printshiv.min.js"></script>
<![endif]-->
<script
type=
"text/javascript"
src=
"
bower_component
s/jquery/dist/jquery.min.js"
></script>
<script
type=
"text/javascript"
src=
"
bower_component
s/bootstrap/dist/js/bootstrap.min.js"
></script>
<script
type=
"text/javascript"
src=
"
bower_component
s/
B
rython
3.3.0.tar
/brython.js"
></script>
<script
type=
"text/javascript"
src=
"
bower_component
s/
B
rython
3.3.0.tar
/brython_stdlib.js"
></script>
<script
type=
"text/javascript"
src=
"
bower_components/ace/src-min-noconflict/ace
.js"
></script>
<script
type=
"text/javascript"
src=
"
node_module
s/jquery/dist/jquery.min.js"
></script>
<script
type=
"text/javascript"
src=
"
node_module
s/bootstrap/dist/js/bootstrap.min.js"
></script>
<script
type=
"text/javascript"
src=
"
node_module
s/
b
rython/brython.
min.
js"
></script>
<script
type=
"text/javascript"
src=
"
node_module
s/
b
rython/brython_stdlib.js"
></script>
<script
type=
"text/javascript"
src=
"
node_modules/monaco-editor/min/vs/loader
.js"
></script>
<script
type=
"text/javascript"
>
exercise_id
=
<?php
echo
isset
(
$_REQUEST
[
"exercise_id"
])
?
$_REQUEST
[
"exercise_id"
]
:
0
;
?>
;
editor
=
document
.
getElementById
(
'
editor
'
);
jQuery
(
document
).
ready
(
function
()
{
editor
=
ace
.
edit
(
"
editor
"
);
editor
.
session
.
setMode
(
"
ace/mode/python
"
);
editor
.
$blockScrolling
=
Infinity
;
brython
();
require
.
config
({
paths
:
{
vs
:
'
node_modules/monaco-editor/min/vs
'
}
});
require
([
'
vs/editor/editor.main
'
],
function
()
{
editor
=
monaco
.
editor
.
create
(
document
.
getElementById
(
'
editor
'
),
{
value
:
""
,
language
:
'
python
'
,
minimap
:
{
enabled
:
false
}});
diffEditor
=
monaco
.
editor
.
createDiffEditor
(
document
.
getElementById
(
'
diffEditor
'
));
brython
();
});
});
</script>
</head>
<body
class=
"container"
>
<div
class=
"row"
id=
"header-row"
>
<div
class=
"col-md-12 panel-primary"
>
<h1
id=
"exercise"
class=
"panel-heading"
>
Loading...
</h1>
<p
id=
"instructions"
class=
"panel-body"
>
Loading...
</p>
</div>
</div>
<div
class=
"row"
id=
"code-row"
>
<div
class=
"col-md-8"
>
<pre
id=
"editor"
style=
"height: 240px;"
></pre>
</div>
<div
class=
"col-md-4"
>
<h3
class=
"text-center"
>
Tests
</h3>
<div
id=
"tests"
class=
"list-group"
></div>
</div>
</div>
<div
class=
"row"
id=
"controls-row"
>
<div
class=
"col-md-12 text-center"
>
<div
class=
"form-group"
>
<button
id=
"run"
class=
"btn"
>
Run
</button>
<button
id=
"test-all"
type=
"button"
class=
"btn"
>
Run Tests
</button>
<button
id=
"grade"
type=
"button"
class=
"btn disabled"
>
Grade
</button>
<span
id=
"nograde"
class=
"hidden"
>
Connect through a LMS to submit grade information
</span>
<div
class=
"accordian col-md-12"
id=
"accordianMain"
>
<!-- Instructions -->
<div
class=
"accordian-item"
>
<h2
class=
"accordian-header"
id=
"headingOne"
>
<button
class=
"accordion-button"
type=
"button"
data-bs-toggle=
"collapse"
data-bs-target=
"#collapseOne"
aria-expanded=
"true"
aria-controls=
"collapseOne"
>
<h1
id=
"exercise"
>
Loading...
</h1>
</button>
</h2>
<div
id=
"collapseOne"
class=
"accordion-collapse collapse show"
aria-labelledby=
"headingOne"
data-bs-parent=
"#accordionMain"
>
<div
class=
"accordion-body"
>
<span
id=
"instructions"
>
Loading...
</span>
</div>
</div>
</div>
</div>
<div
class=
"row"
>
<div
class=
"col-md-12 text-center"
>
<span
id=
"warning"
></span>
</div>
</div>
<!-- Code -->
<div
class=
"accordion-item"
>
<h2
class=
"accordion-header"
id=
"headingTwo"
>
<button
class=
"accordion-button"
type=
"button"
data-bs-toggle=
"collapse"
data-bs-target=
"#collapseTwo"
aria-expanded=
"true"
aria-controls=
"collapseTwo"
>
Code
</button>
</h2>
<div
id=
"collapseTwo"
class=
"accordion-collapse collapse show"
aria-labelledby=
"headingTwo"
data-bs-parent=
"#accordionMain"
>
<div
class=
"accordion-body"
>
<div
id=
"editor"
style=
"height: 400px;"
></div>
<div
class=
"form-group text-center"
>
<button
id=
"run"
class=
"btn btn-secondary"
>
Run
</button>
<button
id=
"test-all"
type=
"button"
class=
"btn btn-primary"
>
Run Tests
</button>
<button
id=
"grade"
type=
"button"
class=
"btn btn-success disabled"
>
Grade
</button>
<span
id=
"nograde"
class=
"visually-hidden"
>
Connect through a LMS to submit grade information
</span>
</div>
<div><span
id=
"warning"
></span></div>
<div
class=
"visually-hidden"
id=
"output-row"
>
<h3>
Output
</h3>
<div
class=
"form-group"
>
<textarea
id=
"output"
readonly
class=
"form-control"
></textarea>
</div>
</div>
</div>
</div>
<div
class=
"row hidden"
id=
"output-row"
>
<div
class=
"col-md-12"
>
<h3
class=
"text-center"
>
Output
</h3>
<div
id=
"container"
style=
"width: 100%"
></div>
<textarea
id=
"output"
readonly
class=
"form-control"
style=
"height: 240px"
></textarea>
</div>
</div>
<!-- Tests -->
<div
class=
"accordion-item"
>
<h2
class=
"accordion-header"
id=
"headingThree"
>
<button
class=
"accordion-button"
type=
"button"
data-bs-toggle=
"collapse"
data-bs-target=
"#collapseThree"
aria-expanded=
"true"
aria-controlls=
"collapseThree"
>
Tests
</button>
</h2>
<div
id=
"collapseThree"
class=
"accordion-collapse collapse show"
aria-labelledby=
"headingThree"
data-bs-parent=
"#accordionMain"
>
<div
class=
"accordion-body"
>
<div
id=
"tests"
class=
"list-group"
></div>
<div
class=
"row hidden"
id=
"test-row"
>
<div
class=
"col-md-12 text-center"
>
<h3>
Expected Output
</h3>
<div
class=
"form-group"
>
<textarea
id=
"expected"
readonly
class=
"form-control"
></textarea>
</div>
<div
class=
"visually-hidden"
id=
"test-row"
>
<h3>
Comparison of Expected and Actual Output
</h3>
<div
class=
"form-group"
>
<div
id=
"diffEditor"
style=
"height:400px; width: 800px;"
class=
"form-control"
></div>
</div>
<h3>
Actual
Output
</h3>
<div
class=
"form-group"
>
<textarea
id=
"
actual
"
readonly
class=
"form-control"
></textarea>
</div>
<h3>
Expected
Output
</h3>
<div
class=
"form-group"
>
<textarea
id=
"
expected
"
readonly
class=
"form-control"
></textarea>
</div>
<h3>
Test Input
</h3>
<div
class=
"form-group"
>
<textarea
id=
"input"
readonly
class=
"form-control"
></textarea>
</div>
</div>
<h3>
Actual Output
</h3>
<div
class=
"form-group"
>
<textarea
id=
"actual"
readonly
class=
"form-control"
></textarea>
</div>
<h3>
Test Input
</h3>
<div
class=
"form-group"
>
<textarea
id=
"input"
readonly
class=
"form-control"
></textarea>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script
type=
"text/python"
src=
"automarker_client.py"
></script>
<script
type=
"text/javascript"
>
submission_url
=
''
;
redirect_url
=
''
;
<?php
if
(
!
is_lti_request
())
{
echo
" jQuery('#grade').addClass('hidden');
\n
"
;
echo
" jQuery('#nograde').removeClass('hidden');
\n
"
;
echo
"jQuery(document).ready(function() {\n"
;
echo
" jQuery('#grade').addClass('visually-hidden');
\n
"
;
echo
" jQuery('#nograde').removeClass('visually-hidden');
\n
"
;
echo
" jQuery('#nograde').show();
\n
"
;
echo
"});
\n
"
;
}
else
{
$oauth_consumer_key
=
""
;
$oauth_consumer_secret
=
""
;
...
...
@@ -111,9 +135,11 @@ require_once("bower_components/pythonauto/util/lti_util.php");
}
$context
=
new
BLTI
(
$oauth_consumer_secret
,
true
,
false
);
if
(
!
$context
->
valid
)
{
echo
" jQuery('#grade').addClass('hidden');
\n
"
;
echo
" jQuery('#nograde').removeClass('hidden');
\n
"
;
echo
" jQuery(document).ready(function() {\n"
;
echo
" jQuery('#grade').addClass('visually-hidden');
\n
"
;
echo
" jQuery('#nograde').removeClass('visually-hidden');
\n
"
;
echo
" jQuery('#nograde').show();
\n
"
;
echo
" });
\n
"
;
}
else
{
echo
" submission_url = '"
.
$context
->
addSession
(
"grade.php"
)
.
"';
\n
"
;
if
(
isset
(
$_POST
[
'launch_presentation_return_url'
]))
{
...
...
@@ -142,6 +168,14 @@ require_once("bower_components/pythonauto/util/lti_util.php");
alert
(
"
Connect through a LMS to submit grade information
"
);
}
}
function
updateDiff
()
{
diffEditor
.
setModel
({
original
:
monaco
.
editor
.
createModel
(
document
.
getElementById
(
"
expected
"
).
value
,
"
text/plain
"
),
modified
:
monaco
.
editor
.
createModel
(
document
.
getElementById
(
"
actual
"
).
value
,
"
text/plain
"
)
});
}
</script>
<script
type=
"text/python"
src=
"automarker_client.py"
></script>
</body>
</html>
lti_util/LICENSE
0 → 100644
View file @
35f66844
The MIT License
Copyright (c) 2007 Andy Smith
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,