To be able to edit code and run cells, you need to run the notebook yourself. Where would you like to run the notebook?

This notebook takes about 30 seconds to run.

In the cloud (experimental)

Binder is a free, open source service that runs scientific notebooks in the cloud! It will take a while, usually 2-7 minutes to get a session.

On your computer

(Recommended if you want to store your changes.)

  1. Copy the notebook URL:
  2. Run Pluto

    (Also see: How to install Julia and Pluto)

  3. Paste URL in the Open box

Frontmatter

If you are publishing this notebook on the web, you can set the parameters below to provide HTML metadata. This is useful for search engines and social media.

Author 1
👀 Reading hidden code
begin
import Pluto
import UUIDs: UUID
import Distributed
using PlutoUI
using DataFrames
import CSV
end
7.2 s
true
👀 Reading hidden code
let
function solution_pascal(n)
if n <= 1
[1.0]
else
prev = solution_pascal(n - 1)
0.5 * ([prev..., 0] .+ [0, prev...])
end
end

function solution_gaussian_kernel(n)
end

K[1] < K[5] < K[9] > K[13] > K[17]
end
722 ms

Part 1: autograding

👀 Reading hidden code
161 μs

Step 1: Select submission files

👀 Reading hidden code
160 μs

You need to write some code that returns the absolute paths to the students' homework submissions. The following code works for me, but probably not for you.

👀 Reading hidden code
230 μs
Error message

IOError: readdir("/home/fons/disorganised-mess/autograding/submissions/"): no such file or directory (ENOENT)

Stack trace

Here is what happened, the most recent locations are first:

  1. uv_error
  2. readdir(dir::String; join::Bool, sort::Bool)
  3. submission_files = let	all = readdir("/home/fons/disorganised-mess/autograding/submissions/"; join=true)	filter(f -> endswith(f, ".jl"), all)
Probably not your fault!
submission_files = let
all = readdir("/home/fons/disorganised-mess/autograding/submissions/"; join=true)
filter(f -> endswith(f, ".jl"), all)
end
👀 Reading hidden code
---

It should return an arrays of strings, something like:

👀 Reading hidden code
208 μs
👀 Reading hidden code
14.4 μs
Error message

Another cell defining submission_files contains errors.

C'est la vie !
if !all(isabspath, submission_files)
md"""
!!! warning
Submission paths need to be _absolute_
"""
end
👀 Reading hidden code
---

Step 2: autograde actions

👀 Reading hidden code
165 μs

I have already written these, you can ignore this.

👀 Reading hidden code
172 μs
👀 Reading hidden code
48.9 ms
all (generic function with 11 methods)
all
👀 Reading hidden code
9.0 μs
107.5
sum(actions) do action
try
action.points_value
catch
0
end
end
👀 Reading hidden code
19.9 ms
Error message

UndefVarError: HTMLTable not defined

Stack trace

Here is what happened, the most recent locations are first:

  1. HTMLTable(autograde_results_df)
HTMLTable(autograde_results_df)
👀 Reading hidden code
---

Step 3: autograde all notebooks

👀 Reading hidden code
165 μs
Error message

Another cell defining submission_files contains errors.

md"**Click to start running the notebooks:**

$(@bind run_notebooks CheckBox()) run $(length(submission_files)) notebooks

---"
👀 Reading hidden code
---
pluto_session = Pluto.ServerSession(;options=Pluto.Configuration.from_flat_kwargs(
launch_browser=false,
require_secret_for_open_links=false,
require_secret_for_access=false,
workspace_use_distributed=false,
port=2468,
))
👀 Reading hidden code
215 ms
submission_files_to_run = run_notebooks ? Pluto.tamepath.(submission_files) : String[]
👀 Reading hidden code
216 μs
Pluto
Pluto
👀 Reading hidden code
9.5 μs
notebooks = let
for nb in values(pluto_session.notebooks)
Pluto.SessionActions.shutdown(pluto_session, nb)
end
map(submission_files_to_run) do path
nb = Pluto.load_notebook(Pluto.tamepath(path))
pluto_session.notebooks[nb.notebook_id] = nb
Pluto.update_save_run!(pluto_session, nb, nb.cells; run_async=false, prerender_text=true)
nb
end
end
👀 Reading hidden code
86.1 μs
autograde_results = map(notebooks) do nb
map(actions) do action
do_action(nb, action)
end
end
👀 Reading hidden code
27.0 ms
👀 Reading hidden code
66.3 μs
(This table has no columns)
(This table has no rows)
👀 Reading hidden code
384 ms
👀 Reading hidden code
436 ms

Part 2: manual review

👀 Reading hidden code
166 μs

Step 1: start notebook server

👀 Reading hidden code
660 μs

Click to start notebook server:

run notebook server


👀 Reading hidden code
918 μs
if run_server
@async Pluto.run(pluto_session)
md"> Server is running at [https://localhost:2468](https://localhost:2468)"
end
👀 Reading hidden code
5.0 ms

Step 2: manual grade actions

👀 Reading hidden code
165 μs
👀 Reading hidden code
37.6 ms
53
👀 Reading hidden code
7.8 ms

Step 3: select notebook

👀 Reading hidden code
161 μs
Error message

BoundsError: attempt to access 0-element Vector{Pair} at index [1]

Stack trace

Here is what happened, the most recent locations are first:

  1. getindex
  2. first(a::Vector{Pair})
  3. get(select::PlutoUI.BuiltinsNotebook.Select)
  4. macro expansion
  5. Show more...
@bind inspected_notebook_index_str Select([string(i) => nb.path for (i,nb) in enumerate(notebooks)])
👀 Reading hidden code
---

Autograde results for selected homework

👀 Reading hidden code
168 μs
Error message

Another cell defining inspected_notebook_index_str contains errors.

Silly computer!
autograde_results_df[inspected_notebook_index, :]
👀 Reading hidden code
---

Editable view of selected homework

👀 Reading hidden code
175 μs
👀 Reading hidden code
269 μs

Manual grading

👀 Reading hidden code
187 μs

Currently stored grades for this notebook:

👀 Reading hidden code
174 μs
Error message

Another cell defining inspected_notebook_index_str and inspected_manual_results contains errors.

Silly computer!
if inspected_manual_results === missing
get(manual_results_dict, basename(inspected_notebook.path),
md"_Scores for this homework are not yet saved._"
)
else
inspected_manual_results
end
👀 Reading hidden code
---
Error message

Another cell defining inspected_notebook_index_str contains errors.

# struct ManualCheckAction <: GradingAction
# name
# points_value::Number
# rubric
# end
begin
inspected_notebook
manual_results_dict
@bind inspected_manual_results let
boxes = map(enumerate(manual)) do (i,action)
"""<tr>
<td><input type='number' id='field$(i)' min=0 max=$(action.points_value) step=1 value=$(action.points_value)><code> / $(action.points_value)</code></td>
<td>$(repr(MIME"text/html"(), action.rubric))</td>
</tr>"""
end
"""
<div id="hello">
<table>
<tbody>
$(join(boxes))
</tbody>
</table>
<input type="submit" value="Save!">
</div>

<style>
div#hello table td {
text-align: left;
}
div#hello table input[type=number] {
width: 4em;
text-align: center;
}
</style>
<script>
const div = this.querySelector("#hello")
const table = div.querySelector("table")
const inputs = table.querySelectorAll("input")
const update_value = () => {
//div.value = Object.fromEntries(Array.from(inputs).map((b) => [b.id, b.value]))
div.value = Array.from(inputs).map((b) => Number(b.value))
}
inputs.forEach(el => {
el.oninput = (e) => {
update_value()
e.stopPropagation()
}
})
const submit = div.querySelector("input[type=submit]")
submit.onclick = () => {
update_value()
div.dispatchEvent(new CustomEvent("input", {}))
}

</script>
""" |> HTML
end
end
👀 Reading hidden code
---
👀 Reading hidden code
38.5 ms
👀 Reading hidden code
22.3 μs
Error message

Another cell defining inspected_notebook_index_str and inspected_notebook contains errors.

manual_results_df = DataFrame(map(enumerate(collect(updated_manual_results_dict))) do (i,(filename, results))
(;
map(zip(manual, results)) do (action, result)
Symbol(displayname(action)) => result
end...,
autograde_results_df[1,:]...,
)
end)
👀 Reading hidden code
---
Error message

Another cell defining inspected_notebook_index_str and inspected_notebook contains errors.

DownloadButton(sprint(CSV.write, manual_results_df), "manual_results.csv")
👀 Reading hidden code
---
👀 Reading hidden code
67.0 μs
Error message

Another cell defining inspected_notebook_index_str and inspected_notebook contains errors.

# reactively add the result to our Dict
updated_manual_results_dict = let
if inspected_manual_results !== missing
manual_results_dict[inspected_notebook_index] = inspected_manual_results
end
manual_results_dict
end
👀 Reading hidden code
---
Error message

Another cell defining inspected_notebook_index_str contains errors.

inspected_notebook_index = parse(Int, inspected_notebook_index_str)
👀 Reading hidden code
---
Error message

Another cell defining inspected_notebook_index_str contains errors.

Be patient :)
inspected_notebook = notebooks[inspected_notebook_index]
👀 Reading hidden code
---

Appendix

👀 Reading hidden code
165 μs

Grading actions

👀 Reading hidden code
162 μs
abstract type GradingAction end
👀 Reading hidden code
346 μs
struct AutoTestAction <: GradingAction
name
points_value::Number
test::Expr
end
👀 Reading hidden code
1.4 ms
struct GetValue <: GradingAction
name
getter::Expr
end
👀 Reading hidden code
1.2 ms
ManualScoreAction
begin
struct ManualScoreAction <: GradingAction
name
points_value::Number
rubric
end
ManualScoreAction(name, points_value) = ManualScoreAction(name, points_valie, name)
end
👀 Reading hidden code
1.6 ms
ManualCheckAction
begin
struct ManualCheckAction <: GradingAction
name
points_value::Number
rubric
end
ManualCheckAction(name, points_value) = ManualCheckAction(name, points_valie, name)
end
👀 Reading hidden code
1.6 ms
do_action (generic function with 2 methods)
begin
function do_action(notebook::Pluto.Notebook, action::AutoTestAction)
tester = quote
try
$(action.test)
catch
false
end
end
if eval_in_notebook(notebook, tester) === true
action.points_value
else
zero(action.points_value)
end
end
function do_action(notebook::Pluto.Notebook, action::GetValue)
eval_in_notebook(notebook, action.getter)
end
end
👀 Reading hidden code
1.1 ms
displayname (generic function with 1 method)
begin
# default
displayname(action::GradingAction) = action.name
end
👀 Reading hidden code
388 μs

Misc

👀 Reading hidden code
175 μs
eval_in_notebook (generic function with 1 method)
function eval_in_notebook(notebook::Pluto.Notebook, expr)
ws = Pluto.WorkspaceManager.get_workspace((pluto_session, notebook))
fetcher = :(Core.eval($(ws.module_name), $(expr |> QuoteNode)))
Distributed.remotecall_eval(Main, ws.pid, fetcher)
end
👀 Reading hidden code
745 μs

Not used

👀 Reading hidden code
161 μs
struct GradedStudent
name
email
grader
end
👀 Reading hidden code
874 μs
""
👀 Reading hidden code
10.6 μs
Error message

MethodError: no method matching Main.workspace#3.GradedStudent(::SubString{String})

Closest candidates are:

Main.workspace#3.GradedStudent(::Any, ::Any, ::Any) at ~/work/disorganised-mess/disorganised-mess/autograding/updated.jl#==#0796b462-f85c-11ea-1bf2-53ad24ec447c:2

Stack trace

Here is what happened, the most recent locations are first:

  1. anonymous function
    graders = map(split(graders_raw, '\n')) do line	GradedStudent(split(line, '\t')...)end
  2. Show more...
Silly computer!
graders = map(split(graders_raw, '\n')) do line
GradedStudent(split(line, '\t')...)
end
👀 Reading hidden code
---