Skip to content
This repository was archived by the owner on Jun 7, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added runestone/showeval/READEME.md
Empty file.
1 change: 1 addition & 0 deletions runestone/showeval/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .showeval import *
13 changes: 13 additions & 0 deletions runestone/showeval/css/showEval.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@charset "UTF-8";

.evalCont {
font-family: monospace;
line-height: 1.5em;
padding: 9.5px;
background-color: #F5F5F5;
border: 1px solid #CCC;
border-radius: 4px;
display: block;
width: auto;
color: #333
}
130 changes: 130 additions & 0 deletions runestone/showeval/js/showEval.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
ShowEval, a JS module for creating visualizations of expression evaluation. Mainly for programming tutorials.
0.9.1

Al Sweigart
al@inventwithpython.com
https://github.com/asweigart/
*/

var SHOWEVAL = (function () {
var thisModule = {};

thisModule.version = '0.9.1';

thisModule.ShowEval = function(container, steps, showTrace) {
this.container = container;
this.container.addClass('showEval');
this.steps = steps.slice();
this.currentStep = 0;
this.createTrace = showTrace; // TODO - reset doesn't work for traces

// create elements
this.currentStepDiv = $('<div>').addClass('currentStepDiv');
this.container.append(this.currentStepDiv);
this.currentStepDiv.append($('<span>').addClass('pre'));
this.currentStepDiv.append($('<span>').addClass('eval'));
this.currentStepDiv.append($('<span>').addClass('post'));

// parse steps and turn into a 4-string array: ['pre', 'before eval', 'after eval', 'post']
for (var i = 0 ; i < this.steps.length; i++) {
var s = this.steps[i];
this.steps[i] = [s.substring(0, s.indexOf('{{')), // 'pre'
s.substring(s.indexOf('{{') + 2, s.indexOf('}}{{')), // 'before eval'
s.substring(s.indexOf('}}{{') + 4, s.indexOf('}}', s.indexOf('}}{{') + 4)), // 'after eval'
s.substring(s.indexOf('}}', s.indexOf('}}{{') + 4) + 2)]; // 'post'
}
this.reset();
};

thisModule.ShowEval.prototype.setNextButton = function(nextButtonSelector) {
var thisObj = this; // uhg, javascript
$(nextButtonSelector).click(function() { thisObj.evaluateStep(nextButtonSelector); });
};

thisModule.ShowEval.prototype.setResetButton = function(resetButtonSelector) {
var thisObj = this; // uhg, javascript
$(resetButtonSelector).click(function() { thisObj.reset(0); });
};

thisModule.ShowEval.prototype.reset = function() {
this.container.find('.previousStep').remove();
this.setStep(0);
};

thisModule.ShowEval.prototype.setStep = function(step) {
this.currentStep = step;
newWidth = this.getWidth(this.steps[this.currentStep][1]);
this.currentStepDiv.children('.eval').width(newWidth);
this.currentStepDiv.children('.pre').html(this.steps[step][0]);
this.currentStepDiv.children('.eval').html(this.steps[step][1]);
this.currentStepDiv.children('.post').html(this.steps[step][3]);
};

thisModule.ShowEval.prototype.getWidth = function(text) { // TODO - class style must match or else width will be off.
var newElem = $("<div>").addClass('showEval evalCont').hide().html(text);
$('body').append(newElem);
console.log(newElem.width());
var newWidth = newElem.width() + 1; // +1 is a hack
console.log(newWidth);
newElem.remove();

return newWidth;
};

thisModule.ShowEval.prototype.createPreviousStepDiv = function(step) {
this.currentStepDiv.before($('<div>').addClass('previousStep').html(this.steps[step][0] + this.steps[step][1] + this.steps[step][3]));
};

thisModule.ShowEval.prototype.evaluateStep = function(buttonId, step) {
$(buttonId).attr("disabled", true);
if (step === undefined) {
step = this.currentStep;
}
if (this.currentStep >= this.steps.length) {
//this.currentStep = 0;
//step = 0;
$(buttonId).attr("disabled", false);
return; // do nothing if on last step
}
this.setStep(step);

var fadeInSpeed = 0;
if (this.createTrace) {
this.createPreviousStepDiv(step);
this.currentStepDiv.hide();
fadeInSpeed = 200;
}

newWidth = this.getWidth(this.steps[step][2]);
var evalElem = this.currentStepDiv.children('.eval');

var thisShowEval = this;

evalElem.css('color', 'red');

this.currentStepDiv.fadeTo(fadeInSpeed, 1, function() {
window.setTimeout(function() {
evalElem.fadeTo(400, 0, function() {
//evalElem.css('overflow', 'hidden');
evalElem.animate({width: newWidth, duration: 400}, function() {
evalElem.html(thisShowEval.steps[step][2]);
evalElem.fadeTo(400, 1, function() {
window.setTimeout(function() {
//evalElem.css('overflow', 'visible');
evalElem.css('color', '#333');
thisShowEval.currentStep += 1;
if (thisShowEval.currentStep < thisShowEval.steps.length) {
thisShowEval.setStep(thisShowEval.currentStep);
}
}, 600);
});
});
});
}, 600);
});
$(buttonId).attr("disabled", false);
};

return thisModule;
}());
115 changes: 115 additions & 0 deletions runestone/showeval/showeval.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Copyright (C) 2017 Tyler Conzett
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
__author__ = 'tconzett'

from docutils import nodes
from docutils.parsers.rst import directives
from docutils.parsers.rst import Directive
from runestone.server.componentdb import addQuestionToDB, addHTMLToDB
from runestone.common.runestonedirective import RunestoneDirective

def setup(app):
app.add_directive('showeval', ShowEval)
app.add_javascript('showEval.js')
app.add_stylesheet('showEval.css')

CODE = """\
<div data-childcomponent="showeval" class="runestone explainer alert alert-warning">
<button class="btn btn-success" id="%(divid)s_nextStep">Next Step</button>
<button class="btn btn-default" id ="%(divid)s_reset">Reset</button>
<div class="evalCont">
<div id="%(divid)s">%(preReqLines)s</div>
</div>
</div>
"""

SCRIPT = """\
<script>
$(document).ready(function() {
steps = %(steps)s;
%(divid)s_object = new SHOWEVAL.ShowEval($('#%(divid)s'), steps, %(trace_mode)s);
%(divid)s_object.setNextButton('#%(divid)s_nextStep');
%(divid)s_object.setResetButton('#%(divid)s_reset');
});
</script>
"""

class ShowEval(RunestoneDirective):
"""
.. showeval:: unique_id_goes_here
:trace_mode: boolean <- Required option that enables 'Trace Mode'

~~Prerequisite Information~~

~~~~

~~Steps~~

"""
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
has_content = True
option_spec = {'trace_mode':directives.unchanged_required}

def run(self):
"""
All prerequisite information that should be displayed above the directive,
such as variable declaration, are separated from the step strings by "-----".

The step animations follow the "-----" and are written one per line. Use
"{{" and "}}" braces to surround the part of the line that should be replaced,
followed by the replacement text also in "{{" and "}}".

Example:

.. showeval:: showEval_0
:trace_mode: false

eggs = ['dogs', 'cats', 'moose']
~~~~

''.join({{eggs}}{{['dogs', 'cats', 'moose']}}).upper().join(eggs)
{{''.join(['dogs', 'cats', 'moose'])}}{{'dogscatsmoose'}}.upper().join(eggs)
{{'dogscatsmoose'.upper()}}{{'DOGSCATSMOOSE'}}.join(eggs)
'DOGSCATSMOOSE'.join({{eggs}}{{['dogs', 'cats', 'moose']}})
{{'DOGSCATSMOOSE'.join(['dogs', 'cats', 'moose'])}}{{'dogsDOGSCATSMOOSEcatsDOGSCATSMOOSEmoose'}}

"""

addQuestionToDB(self)

self.options['divid'] = self.arguments[0]
self.options['trace_mode'] = self.options['trace_mode'].lower()
self.options['preReqLines'] = ''
self.options['steps'] = []

step = False
count = 0
for line in self.content:
if step == True:
if line != '':
self.options['steps'].append(str(line))
elif '~~~~' in line:
step = True
else:
self.options['preReqLines'] += line + '<br />\n'


res = (CODE + SCRIPT) % self.options

addHTMLToDB(self.options['divid'], self.options['basecourse'], res)
return [nodes.raw(self.block_text, res, format='html')]
128 changes: 128 additions & 0 deletions runestone/showeval/test/_sources/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
=====================
This Is A New Project
=====================

.. Here is were you specify the content and order of your new book.

.. Each section heading (e.g. "SECTION 1: A Random Section") will be
a heading in the table of contents. Source files that should be
generated and included in that section should be placed on individual
lines, with one line separating the first source filename and the
:maxdepth: line.

.. Sources can also be included from subfolders of this directory.
(e.g. "DataStructures/queues.rst").

SECTION 1: Introduction
:::::::::::::::::::::::

Congratulations! If you can see this file you have probably successfully run the ``runestone init`` command. If you are looking at this as a source file you should now run ``runestone build`` to generate html files. Once you have run the build command you can run ``runestone serve`` and then view this in your browser at ``http://localhost:8000``

This is just a sample of what you can do. The index.rst file is the table of contents for your entire project. You can put all of your writing in the index, or you can include additional rst files. Those files may even be in subdirectories that you can reference using a relative path.


::


.. toctree::
:maxdepth: 2

some/path/myfile.rst


Section 2: Links
::::::::::::::::

Runestone uses the ``restructuredText`` (rst) markup language. We chose this over markdown largely because rst is extensible. Nearly all of the basic markup tasks are already handled by restructuredText. You should check out the docs for the basics of restructuredText (link below). Our extensions are all for the interactive elements. One key hint about restructuredText: Its like **Python** -- *indentation matters!*

* `restructuredText Docs <http://docutils.sourceforge.net/rst.html>`_
* `Runestone Docs <http://runestoneinteractive.org/build/html/index.html>`_
* Join the discussion on our `Google Group <https://groups.google.com/forum/#!forum/runestone_instructors>`_
* Tell us about problems on `Github <https://github.com/RunestoneInteractive/RunestoneComponents>`_



SECTION 3: Sample Directives
::::::::::::::::::::::::::::

ShowEval Trace Mode
-------------------

.. showeval:: showEval_0
:trace_mode: true

eggs = ['dogs', 'cats', 'moose']
~~~~

''.join({{eggs}}{{['dogs', 'cats', 'moose']}}).upper().join(eggs)
{{''.join(['dogs', 'cats', 'moose'])}}{{'dogscatsmoose'}}.upper().join(eggs)
{{'dogscatsmoose'.upper()}}{{'DOGSCATSMOOSE'}}.join(eggs)
'DOGSCATSMOOSE'.join({{eggs}}{{['dogs', 'cats', 'moose']}})
{{'DOGSCATSMOOSE'.join(['dogs', 'cats', 'moose'])}}{{'dogsDOGSCATSMOOSEcatsDOGSCATSMOOSEmoose'}}


ShowEval Replace Mode
---------------------

.. showeval:: showEval_1
:trace_mode: false

eggs = ['dogs', 'cats', 'moose']
~~~~

''.join({{eggs}}{{['dogs', 'cats', 'moose']}}).upper().join(eggs)
{{''.join(['dogs', 'cats', 'moose'])}}{{'dogscatsmoose'}}.upper().join(eggs)
{{'dogscatsmoose'.upper()}}{{'DOGSCATSMOOSE'}}.join(eggs)
'DOGSCATSMOOSE'.join({{eggs}}{{['dogs', 'cats', 'moose']}})
{{'DOGSCATSMOOSE'.join(['dogs', 'cats', 'moose'])}}{{'dogsDOGSCATSMOOSEcatsDOGSCATSMOOSEmoose'}}

ShowEval Trace Mode 2
---------------------

.. showeval:: showEval_2
:trace_mode: true

eggs = ['dogs', 'cats', 'moose']
ham = ['elk', 'salmon']
eggs = eggs + ham
~~~~
eggs = {{eggs}}{{['dogs', 'cats', 'moose']}} + ham
eggs = ['dogs', 'cats', 'moose'] + {{ham}}{{['elk', 'salmon']}}
eggs = {{['dogs', 'cats', 'moose'] + ['elk', 'salmon']}}{{['dogs', 'cats', 'moose', 'elk', 'salmon']}}


CodeLens
--------

.. codelens:: ch08_acc2

def removeVowels(s):
vowels = "aeiouAEIOU"
sWithoutVowels = ""
for eachChar in s:
if eachChar not in vowels:
sWithoutVowels = sWithoutVowels + eachChar
return sWithoutVowels

print(removeVowels("compsci"))

Multiple Choice
---------------

.. mchoice:: question1_2
:multiple_answers:
:correct: a,b,d
:answer_a: red
:answer_b: yellow
:answer_c: black
:answer_d: green
:feedback_a: Red is a definitely on of the colors.
:feedback_b: Yes, yellow is correct.
:feedback_c: Remember the acronym...ROY G BIV. B stands for blue.
:feedback_d: Yes, green is one of the colors.

Which colors might be found in a rainbow? (choose all that are correct)

These are just two of the many interactive components for writing online course materials. You can see examples of all of them `On our Example Page <http://interactivepython.org/runestone/static/overview/overview.html>`_

Now feel free to modify this file to start creating your own interactive page.
Empty file.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added runestone/showeval/test/_static/clock.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added runestone/showeval/test/_static/close.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added runestone/showeval/test/_static/first.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added runestone/showeval/test/_static/last.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added runestone/showeval/test/_static/next.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added runestone/showeval/test/_static/pause.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added runestone/showeval/test/_static/prev.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<li class="dropdown globaltoc-container">
<a href="{{ pathto(master_doc) }}"
class="dropdown-toggle"
data-toggle="dropdown">{{ theme_navbar_site_name }} <b class="caret"></b></a>
<ul class="dropdown-menu globaltoc"
>{{ toctree(maxdepth=theme_globaltoc_depth|toint, collapse=False, includehidden=theme_globaltoc_includehidden|tobool) }}</ul>
</li>
Loading