Last active
December 12, 2017 09:37
-
-
Save memowe/6993495 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
tasks => [ | |
{ | |
name => 'simple-sum', | |
description => 'Implement a function that adds two numbers!', | |
template => "sub sum {\n my (\$x, \$y) = \@_;\n\n}", | |
tests => [ | |
{name => 'zeroes', test => 'sum(0, 0)', expected => 0}, | |
{name => 'left zero', test => 'sum(0, 42)', expected => 42}, | |
{name => 'right zero', test => 'sum(17, 0)', expected => 17}, | |
{name => 'some values', test => 'sum(42, 17)', expected => 59}, | |
{name => 'some values', test => 'sum(-17, 42)', expected => 25}, | |
{name => 'some values', test => 'sum(1742, -4217)', expected => -2475}, | |
], | |
}, | |
{ | |
name => 'sum', | |
description => 'Implement a function that sums all natural numbers up to the input!', | |
template => "sub sum {\n my \$n = shift;\n\n}", | |
tests => [ | |
{name => 'negative input', test => 'sum(-42)', expected => 0}, | |
{name => 'zero', test => 'sum(0)', expected => 0}, | |
{name => 'one', test => 'sum(1)', expected => 1}, | |
{name => 'six', test => 'sum(3)', expected => 6}, | |
{name => 'big sum', test => 'sum(42)', expected => 903}, | |
], | |
}, | |
{ | |
name => 'fibonacci', | |
description => 'Implement a fibonacci function!', | |
template => "sub fibonacci {\n my \$n = shift;\n\n}", | |
tests => [ | |
{name => 'negative input', test => 'fibonacci(-42)', expected => 0}, | |
{name => 'first fibonacci number', test => 'fibonacci(0)', expected => 0}, | |
{name => 'second fibonacci number', test => 'fibonacci(1)', expected => 1}, | |
{name => 'third fibonacci number', test => 'fibonacci(2)', expected => 1}, | |
{name => 'fifth fibonacci number', test => 'fibonacci(4)', expected => 3}, | |
{name => '18th fibonacci number', test => 'fibonacci(17)', expected => 1597}, | |
], | |
}, | |
], | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
use Mojolicious::Lite; | |
use List::Util 'first'; | |
use Safe; | |
# prepare sandbox | |
my $sandbox = Safe->new(); | |
# retrieve tasks | |
my @tasks = @{ plugin('Config')->{tasks} }; | |
# home page: list of tasks | |
get '/' => {tasks => \@tasks} => 'index'; | |
# task route | |
get '/task/:task' => sub { | |
my $self = shift; | |
my $task = first {$_->{name} eq $self->param('task')} @tasks; | |
return $self->render_not_found unless defined $task; | |
$self->stash( | |
task => $task, | |
template => 'task', | |
); | |
} => 'task'; | |
# task evaluation route | |
post "/task/:task" => sub { | |
my $self = shift; | |
my $code = $self->param('code'); | |
my $task = first {$_->{name} eq $self->param('task')} @tasks; | |
return $self->render_not_found unless defined $task; | |
# evaluate code-test pairs for all tests | |
my (@results, @correct); | |
for my $test (@{$task->{tests}}) { | |
my $test_code = $code . "\n" . $test->{test}; | |
my $result = $sandbox->reval($test_code); | |
push @results, $result; | |
push @correct, $result == $test->{expected}; | |
} | |
# done | |
$self->stash( | |
task => $task, | |
results => \@results, | |
correct => \@correct, | |
template => 'task', | |
); | |
} => "taskeval"; | |
app->start; | |
__DATA__ | |
@@ index.html.ep | |
% layout 'default'; | |
% title 'Welcome, stranger!'; | |
<h1>Welcome to PEasy, the easy Perl Easy!</h1> | |
<hr> | |
<p>Select a task:</p> | |
<ul> | |
% for my $task (@$tasks) { | |
% my $url = url_for 'task', task => $task->{name}; | |
<li><%= link_to $task->{name} => $url %></li> | |
% } | |
</ul> | |
@@ task.html.ep | |
% use List::Util 'first'; | |
% layout 'default'; | |
% title "Task $task->{name}"; | |
<h1><%= link_to PEasy => 'index' %>: the <%= $task->{name} %> task</h1> | |
<hr> | |
<h2>Description</h2> | |
<p><%== $task->{description} %></p> | |
<h2>Your solution</h2> | |
%= form_for 'taskeval', task => $task->{name} => begin | |
%= text_area code => $task->{template}, cols => 100, rows => 10 | |
%= tag p => begin | |
%= submit_button 'Evaluate!' | |
% end | |
% end | |
<h2>The test suite</h2> | |
<table border="1"> | |
<thead> | |
<th>Test name</th> | |
<th>test</th> | |
<th>expected output</th> | |
% if (defined stash('results')) { | |
<th>actual output</th | |
% } | |
</thead> | |
<tbody> | |
% for my $ti (0 .. $#{$task->{tests}}) { | |
% my $test = $task->{tests}[$ti]; | |
% my $class = ''; | |
% if (defined stash('results')) { | |
% $class = ' class="' . (stash('correct')->[$ti] ? 'ok' : 'fail') . '"'; | |
% } | |
<tr<%== $class %>> | |
<th><%= $test->{name} %></th> | |
<td><%= $test->{test} %></td> | |
<td><%= $test->{expected} %></td> | |
% if (defined stash('results')) { | |
<td><%= stash('results')->[$ti] %></td> | |
% } | |
</tr> | |
% } | |
</tbody> | |
</table> | |
@@ layouts/default.html.ep | |
<!DOCTYPE html> | |
<html> | |
<head><title><%= title %> - PEasy</title> | |
<style type="text/css"> | |
tr.ok th, tr.ok td { background-color: lime } | |
tr.fail th, tr.fail td { background-color: red } | |
</style></head> | |
<body> | |
%= content | |
<hr><p>© | |
<a href="http://mirko.westermeier.de/">Mirko Westermeier</a> | |
(<a href="http://twitter.com/memowe">@memowe</a>) | |
</p> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment