# Decision Tree Entropy

These are some basic notes on how entropy is used when making decision trees. The examples are taken from Process Mining: Data Science In Action.

## Entropy

The equation for entropy is $$E = - \sum\limits_{i=1}^n p_i \log_2 p_i$$, where $$p_i$$ is the probability of variable $$i$$. In other words, for variable $$i$$, $$p_i$$ is the count of instances for that variable divided by the total number of instances for all variables. Well, I'm probably not saying this clearly enough. A concrete example might be better.

## Dying Young

This example uses a data set that contains various attributes that might predict if someone died 'young' (less than 70) or 'not young' (70 or older). There are 860 entries with 546 dying young and 314 dying old. We can calculate the entropy for the root node using the proportions of $$young$$ (died young) and $$\lnot young$$ (didn't die young).

$E = -(E_{young} + E_{\lnot young})\\ = -(\frac{546}{860} \log_2 \frac{546}{860} + \frac{314}{860} \log_2 \frac{314}{860})\\ \approx 0.9468$

# Ubuntu 16.04 and the Brother HL-2140 Printer

## Introduction

I (relatively) recently bought a ZaReason Limbo Desktop PC which comes with Ubuntu 16.04. I'm debating whether to update it to 16.10, given that updating broke the USB WiFi adapter I had on my older computer (the USB is recognized but not the WiFi adapter), but, in any case, I wanted to print something using my new computer today and ran into the same problem that I had when I updated my old computer to Ubuntu 14.10 - the default printer driver printed out a bunch of blank pages rather than the page I wanted to print. The last time I solved it by choosing a different model (the HL-2142) but this time out I found a stack overflow post that suggested using the Brother HL-2140 Foomatic/hl1250 [en] driver instead. I tried it and it worked for me, so here goes.

## How To Choose the Correct Printer Driver

First, open Dash (the windows-key launches it on my keyboard), type in Printers and click on the icon.

This brings up the printers dialog.

Double-click on the HL-2140-series icon to bring up the Printer Properties dialog.

Click on the Make and Model "Change" button (the fourth row). Let the program find the drivers and it will bring up the Choose Driver dialog.

Use the Brother (recommended) option (it should already be selected) and click on the "Forward" button. This brings up the Change Driver dialog with the postscript driver chosen (which is the one that does not work for me).

Select the hl1250 driver (by clicking on it) and click on the "Forward" button.

This will bring up the Existing Settings dialog. I've tried different options and haven't noticed a difference so I just leave it at whatever the default option is and click "Apply".

At this point your driver should be updated so click on the "OK" button.

If your experience is the same as mine, you will be able to print your documents at this point.

## Conclusion

The basic method to get the Brother HL-2140 to print in Ubuntu 16.04 is to select the hl1250 driver instead of the default. Since I only do this when I need to set up a new computer, I alway have to do some googling to remember what to do, so hopefully this will help me save some searching if I ever have to do this again.

# Seek With Cocos2D

This is an implementation of Craig Reynold's flocking behavior based on the book Python Game Programming By Example. Reynolds mentions many variations for flocking. This will implement a basic boid that flocks to the mouse pointer.

## Imports

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
# third party
from cocos.cocosnode import CocosNode
from cocos.euclid import Vector2
import cocos
import cocos.particle_systems as particle_system


## Constants

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
CHASE = 1
RUN_AWAY = -1
CHANGE_BEHAVIOR = -1


## The Boid

### Boid Settings

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
class BoidSettings(object):
"""a settings object"""
def __init__(self):
self.position = None
self.velocity = None
self.speed = None
self.max_force = None
self._attributes = None
return

@property
def attributes(self):
"""list of required attributes"""
if self._attributes is None:
self._attributes = ("position",
"velocity",
"speed",
"max_force")
return self._attributes

def x_y(self, position):
"""sets the initial x, y coordinates
Parameters
----------

position: tuple
(x, y) coordinates
"""
self.position = position
self.check_types(position, "position", (list, tuple))
for item in position:
self.check_numeric(item, "position")
return self

def velocity_vector(self, velocity):
"""initial velocity

Parameters
----------

velocity: Vector2
2-d vector representing boid's velocity
"""
self.velocity = velocity
self.check_type(velocity, "velocity", Vector2)
return self

def speed_scalar(self, speed):
"""scalar for the velocity vector

Parameters
----------

speed: number
pixels per frame to scale velocity
"""
self.speed = speed
self.check_numeric(speed, "speed")
return self

"""denominator to create ratio to slow down

Used to reduce steering-force (distance/radius)

Parameters
----------

steering-force reduction factor
"""
return self

def maximum_force(self, max_force):
"""sets the max force magnitude

Parameters
----------
max_force: numeric
upper-bound for the steering force
"""
self.max_force = max_force
self.check_numeric(max_force, "max force")
return self

def maximum_velocity(self, max_velocity):
"""sets the max-velocity

Parameters
----------

max_velocity: numeric
upper-bound for magnitude of velocity
"""
self.max_velocity = max_velocity
self.check_numeric(max_velocity, "max velocity")
return self

def check_numeric(self, value, identifier):
"""checks value is numeric

Parameters
----------

value: object
item to check

identifier: string
name for error message

Raises
------

TypeError if value is not int or float
"""
self.check_types(value, identifier, (int, float))
return

def check_types(self, value, identifier, expected):
"""checks type of value
Parameters
----------

value: object
the thing to check
identifier: string
id for error message
expected: collection
types to check if value is one of them

Raises
------

TypeError if type of value not in expected
"""
if type(value) not in expected:
raise TypeError("{0} must be one of {1}, not {2}".format(
identifier,
expected,
value))
return

def check_type(self, value, identifier, expected):
"""checks type of the value
Parameters
----------

value: object
thing to check
identifier: string
id for error messages
expected: type
what the value should be

Raises
------
TypeError if type of value is not expected
"""
if not isinstance(value, expected):
raise TypeError("{0} must be {1} not {2}".format(identifier,
expected,
value))
return

def __call__(self):
"""checks all the attributes are set

Raises
------

TypeError if an attribute is None
"""
for attribute in self.attributes:
if getattr(self, attribute) is None:
raise TypeError("{0} must be set, not None".format(attribute))
return self


### the Constructor

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
class Boid(CocosNode):
"""represents a boid
Parameters
----------

settings: BoidSettings
settings for this node
"""
def __init__(self, settings):
super(Boid, self).__init__()
self.settings = settings
self.position = settings.position
self.velocity = Vector2(0, 0)
self.speed = settings.speed
self.max_force = settings.max_force
self.max_velocity = settings.max_velocity
self.target = None


I'm not a fan of method calls in the constructor, but these next two lines help set up the node.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
self.add(particle_system.Sun())
self.schedule(self.update)
return


The add method sets the Sun instance as a child of the Boid node and the schedule method sets the Boid's update method to be called once per frame.

### The Current Position

This is just a convenience attribute. It probably takes a performance hit, but the original code was a little obscure so I thought I'd pull it out to document it.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
@property
def current_position(self):
"""this node's position

Returns
-------

Vector2: the current of this node
"""
return Vector2(self.x, self.y)


I had to look it up, since there's no setting of self.x or self.y here - these two attributes are built into the CocosNode object and are always the current values.

### The Update Method

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def update(self, delta):
"""updates the current position

Parameters
----------

delta: float
seconds since the last clock tick
"""
if self.target is None:
return


The target is going to be set when the mouse is move. Because of this it's initially not set, so we need to short circuit if that's the case.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
distance = self.target - self.current_position
ramp_down = min(distance.magnitude()/self.slowing_radius, 1)
steering_force = distance * self.speed * ramp_down - self.velocity
steering_force = self.limit(steering_force, self.max_force)
self.velocity = self.limit(self.velocity + steering_force,
self.max_velocity)
self.position += self.velocity * delta
return


In the snippet above, distance is a vector with the tail on our current position and the head on the target. The steering-force is created by scaling the distance by our speed and then subtracting our current velocity, creating a vector that over-compensates to turn us toward the target. The new velocity is our old velocity plus the steering-force and our position is updated to be our new velocity times the elapsed time. That doesn't look like it's doing anything, but position is another special attribute on the CocosNode.

This next method reduces a vector if its magnitude is above a given threshold.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def limit(self, vector, upper_bound):
"""limits magnitude of vector

Re-scales all values in the vector if the magnitude exceeds limit

Parameters
----------

vector:
vector to check

upper_bound: number
upper limit for magnitude of vector

Returns
-------

vector whose magnitude is no greater than upper_bound
"""
try:
magnitude = vector.magnitude()
except OverflowError:
print(vector)
raise
return (vector if magnitude <= upper_bound
else vector*(upper_bound/magnitude))


## Main Layer

This is the class to act as the event handler.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
class MainLayer(cocos.layer.Layer):
"""sets up the interaction

Parameters
----------

boids: collection
boids to maintain
"""
is_event_handler = True


That value (is_event_handler) has to be true or the Layer class doesn't handle events.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def __init__(self, boids):
super(MainLayer, self).__init__()
self.boids = boids
for boid in boids:
return

def on_mouse_motion(self, x, y, dx, dy):
"""sets the boids' targets

Parameters
----------

x, y:
current mouse cursor position

dx, dy:
change in position since the last report
"""
for boid in self.boids:
boid.target = Vector2(x, y)
return

def on_mouse_press(self, x, y, button, modifiers):
"""handles mouse-clicks"""
for boid in self.boids:
boid.speed *= CHANGE_BEHAVIOR
return


The on_mouse_motion method is a pass through to pyglet so the method is documented there more than on the cocos2d site.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
if __name__ == "__main__":
boid_settings = (BoidSettings()
.x_y((300, 200))
.velocity_vector(Vector2())
.speed_scalar(10)
.slow_down_distance(200)
.maximum_force(5)
.maximum_velocity(2000)())
cocos.director.director.init(caption="Seeker")
boid = Boid(boid_settings)
scene = cocos.scene.Scene(MainLayer([boid]))
cocos.director.director.run(scene)


The first thing to note is that the cocos.director.init function has to be called before any of the other cocos2D objects are created. If you move the instantiation of the Boid above that line, for instance, it will crash with a AttributeError: 'Director' object has no attribute '_window_virtual_width' error.

# Flocking With Cocos2D

This is an implementation of Craig Reynold's flocking behavior based on the book Python Game Programming By Example.

## Imports

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
# third party
from cocos.cocosnode import CocosNode
import cocos
import cocos.euclid as euclid
import cocos.particle_system as particle_system


## The Boid

### Boid Settings

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
class BoidSettings(object):
"""a settings object"""
def __init__(self):
self.position = None
self.velocity = None
self.speed = None
self.max_force = None
self._attributes = None
return

@property
def attributes(self):
"""list of required attributes"""
if self._attributes is None:
self._attributes = ("position",
"velocity",
"speed",
"max_force")
return self._attributes

def x_y(self, position):
"""sets the initial x, y coordinates
Parameters
----------

position: tuple
(x, y) coordinates
"""
self.position = position
self.check_types(position, "position", (list, tuple))
for item in position:
self.check_numeric(item, "position")
return

def velocity_vector(self, velocity):
"""initial velocity

Parameters
----------

velocity: Vector2
2-d vector representing boid's velocity
"""
self.velocity = velocity
self.check_type(velocity, "velocity", Vector2)
return

def pixels_per_frame(self, speed):
"""initial speed of the boid

Parameters
----------

speed: number
number of pixels to move per frame
"""
self.speed = speed
self.check_numeric(speed, "speed")
return

def maximum_force(self, max_force):
"""sets the max force magnitude

Parameters
----------
max_force: numeric
upper-bound for the steering force
"""
self.max_force = max_force
self.check_numeric(max_force)
return

def maximum_velocity(self, max_velocity):
"""sets the max-velocity

Parameters
----------

max_velocity: numeric
upper-bound for magnitude of velocity
"""
self.max_velocity = max_velocity
self.check_numeric(max_velocity)
return

def check_numeric(self, value, identifier):
"""checks value is numeric

Parameters
----------

value: object
item to check

identifier: string
name for error message

Raises
------

TypeError if value is not int or float
"""
self.check_types(value, identifier, (int, float))
return

def check_types(self, value, identifier, expected):
"""checks type of value
Parameters
----------

value: object
the thing to check
identifier: string
id for error message
expected: collection
types to check if value is one of them

Raises
------

TypeError if type of value not in expected
"""
if type(value) not in expected:
raise TypeError("{0} must be one of {1}, not {2}".format(
identifier,
expected,
value))
return

def check_type(self, value, identifier, expected):
"""checks type of the value
Parameters
----------

value: object
thing to check
identifier: string
id for error messages
expected: type
what the value should be

Raises
------
TypeError if type of value is not expected
"""
if not isinstance(value, expected):
raise TypeError("{0} must be {1} not {2}".format(identifier,
expected,
value))
return


### Boid Node

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
class Boid(CocosNode):
"""represents a boid
Parameters
----------

settings: BoidSettings
settings for this node
"""
def __init__(self):
super(Boid, self).__init__()
self.settings = settings
self.position = settings.position
self.velocity = euclid.Vector2(0, 0)
self.speed = settings.speed
self.max_force = settings.max_force
self.max_velocity = settings.max_velocity
self.target = None


I'm not a fan of method calls in the constructor, but these next two lines help set up the node.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
self.add(particle_system.Sun())
self.schedule(self.update)
return


The add method sets the Sun instance as a child of the Boid node and the schedule method sets the Boid's update method to be called once per frame.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def update(self, delta):
"""updates the current position

Parameters
----------

delta: float
seconds since the last clock tick
"""
if self.target is None:
return


The target

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
distance = self.target - euclid.Vector2(self.x, self.y)
steering_force = distance * self.speed - self.velocity
steering_force = truncate(self.velocity + steering, self.max_velocity)
self.position += self.velocity * delta
return


# Breakout With Tkinter

A tkinter breakout implementation from the book Python Game Programming by Example. Although Tkinter is referred to primarily as a GUI builder, this example shows you how to use it to re-create the arcade game Breakout using only the python standard library.

## Pre-Installation

Although the tkinter python library is part of the standard python installation, it relies on Tcl/Tk and a c-python binary that you have to build or install. To get it in ubuntu you can use apt-get.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
  sudo apt-get python3-tk


## Imports

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
# python standard library
from abc import ABCMeta
from abc import abstractproperty
from collections import namedtuple
from copy import copy
import re
import string
import tkinter


## Constants

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
BLUE = "#0000ff"
LAVENDER = "#aaaaff"
WHITE = "#ffffff"
NUMERIC = (int, float)

REVERSE_DIRECTION = -1
LEFT = -1
RIGHT = LEFT * REVERSE_DIRECTION
UP = -1
EDGE_OF_SCREEN = 0
NO_MOVEMENT = 0


## Base Classes

### Coordinates

This is a named tuple to see if I can keep the coordinates returned by tkinter straight.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
Coordinates = namedtuple("Coordinates", ["top_left_x",
"top_left_y",
"bottom_right_x",
"bottom_right_y"])


### Base Widget

A base-class to implement the methods common to all the game objects. The python 3 syntax seems to have changed slightly so you have to use metaclass=ABCMeta in place of object instead of putting __metaclass__==ABCMeta the way I used to in python 2.7.

#### The item property

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
class BaseWidget(metaclass=ABCMeta):
"""base class for game object's

Parameters
----------

canvas: tkinter.Canvas
canvas to draw on
"""
@abstractproperty
def item(self):
"""the canvas item"""
return


The item will be an identifier pointing to a tkinter widget. It gets returned by the function call to create the widget (e.g. canvas.create_oval).

#### Position

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
@property
def position(self):
"""the coordinates of the object on the canvas

Returns
-------

tuple: x0, y0, x1, y1
"""
x0, y0, x1, y1 = self.canvas.coords(self.item)
return Coordinates(top_left_x=x0,
top_left_y=y0,
bottom_right_x=x1,
bottom_right_y=y1)


The call to canvas.coords returns the coordinates of the bounding-box for the widget. The first two values are the x and y coordinates for the upper-left corner of the box and the last two values are the x and y coordinates of the bottom-right corner.

#### Move

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def move(self, horizontal_offset, vertical_offset):
"""move this object to the coordinates

Parameters
----------

horizontal_offset: int
x-axis pixels to move
vertical_offset: int
y-axis pixels to move
"""
self.canvas.move(self.item, horizontal_offset, vertical_offset)
return


This moves the object. Rather than giving it coordinates, the move method moves the object vertically and horizontally the number of pixels you pass in for each axis. You could think of the values as being added to each of the coordinates (so negative numbers will move the object in the opposite direction from positive numbers).

#### Delete

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def delete(self):
"""destroy this canvas item"""
self.canvas.delete(self.item)
return


This deletes the object from the canvas. If you attempt to use it after this tkinter will raise an exception.

### Base Settings

A base class to hold settings. It (partly) implements the fluent interface design pattern. I'm not one-hundred percent convinced that it's a good idea in python, but I wanted to add value checking and document the values I expect a little better.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
class BaseSettings(metaclass=ABCMeta):
"""fluent interface"""
_hex_pattern = None

@abstractproperty
def attributes(self):
"""list of attribute names
This is used by the call to check the attributes
"""
return


The attributes will be a list (or tuple) of strings that match the variable-names in the settings objects that are required (e.g. to require that self.table has a value other than None, put "table" in the list). This gets used by the __call__ method (defined below).

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
@property
def hex_pattern(self):
"""compiled regex to match hex-colors"""
if BaseSettings._hex_pattern is None:
hex_character = "\da-fA-f"
base = "(?P<{{0}}[{0}])(?P={{0}})".format(hex_character)
BaseSettings._hex_pattern = re.compile("#" +
base.format("r") +
base.format("g") +
base.format("b"))
return BaseSettings._hex_pattern


The hex_pattern will match any string that starts with a pound sign (#) followed by three sets of hex-digit pairs. A hex-digit is an integer from 0 to 9 or one of the letters from a to f (case insensitive). Since it requires pairs, each hex-digit has to be repeated twice. So it will match #aabbff but not #abf or #0123ab. It's used by the next method.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def check_hex_color(self, value, identifier):
"""checks the color is a valid hex-code
Parameters
----------
value: string
color-code to check
identifier: string
error-message identifier

Raises
------
TypeError: if string is malformed
"""
if not re.match("#" + "[{0}]".format(string.hexdigits) * 6, value):
raise TypeError("{0} must be a 6-digit hex string, not {1}".format(
identifier, value))

return


The colors set in this code are based on RGB hex-strings. The check_hex_color method validates that they are look something like "#aabbcc".

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def assert_positive_number(self, value, identifier):
"""checks the value

Parameters
----------

value: int or float
value to check
identifier: string
something for the error message

Raises
------
TypeError if value is not a positive number
"""
self.check_numeric(value, identifier)
self.check_positive(value, identifier)
return


assert_positive_number checks that the value passed in is a number greater than 0.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def check_positive(self, value, identifier):
"""check that value is greater than zero

Parameters
----------

value: numeric
value to check

identifier: str
description for error messages

Raises
------

TypeError: if value is <= 0
"""
if not value > 0:
raise TypeError("{0} must be greater than 0 not {1}".format(
identifier,
value))
return


The check_positive method raises a TypeError if the value passed in isn't greater than zero. It doesn't check that the value is numeric so if it isn't it will still raise a TypeError but the error message won't be as helpful. I did it this way because I (at least originally) assumed some values had to be integers so I wanted to leave the check for type as a separate operation.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def check_type(self, thing, identifier, expected):
"""checks that the value is the correct type
Parameters
----------

thing:
object to check
identifier: string
message to identify the thing
expected: object
what the thing is expected to be

Raises
------

TypeError: if thing isn't as expected
"""
if not isinstance(thing, expected):
raise TypeError("Expected {0} to be {1} not {2}".format(identifier,
expected,
thing))
return


The check_type was the original method I created. I'm not sure it's as useful as checking ranges of values (which I'm not doing enough of yet), but it's at least useful to check if my expectations of what's being passed in to the methods is correct.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def check_types(self, thing, identifier, expected):
"""check that thing is one of multiple types

Parameters
----------

thing: object
thing to check
identifier: string
identifier for error message
expected: collection
types that thing might be

Raises
------

TypeError if type of thing not in expected
"""
if not type(thing) in expected:
raise TypeError("{0} should be one of {1}, not {2}".format(
identifier,
expected,
thing))
return


check_types allows you you specify a collection of possible types for the value.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def check_numeric(self, thing, identifier):
"""check if thing is int or float

Parameters
----------

thing: object
thing to check if is numeric
identifier: string
identifier for error message

Raises
------
TypeError if thing is not numeric
"""
self.check_types(thing, identifier, NUMERIC)
return


check_numeric will raise a TypeError if the value isn't an integer or float.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def __call__(self):
"""checks that everything was set
Raises
------

TypeError:
if any attributes weren't set

Returns
-------

GameSettings: this object
"""
for attribute in self.attributes:
if getattr(self, attribute) is None:
raise TypeError("{0} attribute not set".format(attribute))
return self


The __call__ is meant to be the final method called when the parameters are set. It checks that all the properties in the attributes list have been set to something other than None and raises a TypeError if any of them hasn't been set.

## The Ball Class

### Ball Directions

This is an object to use instead of the list like they use in the book. The first value (x-direction) is set positive to make it move from left to right, and negative to move right to left. The second value is set positive to move the ball downwards and negative to move it upwards.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
class BallDirections(object):
"""holds the current direction of the ball
Parameters
----------

horizontal: int
positive to move left to right, negative otherwise
vertical: int
positive to move down, negative to move up
"""
def __init__(self, horizontal, vertical):
self.horizontal = horizontal
self.vertical = vertical
return


### Ball Settings

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
class BallSettings(BaseSettings):
"""settings for the ball"""
def __init__(self):
self.x = None
self.y = None
self.direction = None
self.speed = None
self.fill = None
self._attributes = None
return

@property
def attributes(self):
"""required attributes"""
if self._attributes is None:
self._attributes = ("x",
"y",
"direction",
"speed",
"fill")
return self._attributes

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def x_position(self, x):
"""initial horizontal position

Parameters
----------
x: int or float
pixels from the left of the canvas to start the ball
"""
self.x = x
self.assert_positive_number(x, "x")
return self

def y_position(self, y):
"""initial vertical position

Parameters
----------

y: int
pixels from the top of the canvas
"""
self.y = y
self.assert_positive_number(y, "y")
return self


The x and y values for the ball are actually set in the code based on the initial location of the paddle, so requiring them here is a bad idea. Oh, well.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def circle_radius(self, radius):
"""radius of the ball
Parameters
----------
pixel width and height for the circle
"""
return self


Ovals in tkinter are set by specifying the corners of their bounding boxes, the same as with creating a rectangle. So the radius is used as an offset to calculate where the corners should be. For example, if you have the center x-value for the oval, subtracting the radius gives you the top-left x-value and adding the radius gives you the bottom-right x-value. See the Game.ball property to get an idea of how it's used.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def direction_vector(self, direction):
"""2-d vector for direction"""
self.direction = direction
self.check_type(direction, "ball direction", BallDirections)
return self


The direction values determine what direction the object is moving on the vertical and horizontal axes. Positive values move to the right and down, while negative values move to the left and up.

Horizontal Vertical Direction
Positive Positive Down-Right
Positive Negative Up-Right
Negative Positive Down-Left
Negative Negative Up-Left
/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def velocity(self, speed):
"""speed of the ball
Parameters
----------

speed: number
pixels per move
"""
self.speed = speed
self.assert_positive_number(speed, "speed")
return self

def color(self, fill):
"""fill color

Parameters
----------
fill: str
hex-color to fill in the ball
"""
self.fill = fill
self.check_hex_color(fill, "fill")
return self


The speed and fill are the number of pixels to move the ball each time and the fill is the color to put inside it.

### The Ball

The ball-widget holds the reference to the ball that the player uses to smash bricks to try and break-out.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
class BallWidget(BaseWidget):
"""representation of the ball

Parameters
----------

canvas: tkinter.Canvas
what to create the ball from

settings: BallSettings
initial ball settings
"""
def __init__(self, canvas, settings):
self.canvas = canvas
self.settings = settings
self._item = None
self.direction = self.settings.direction
self.speed = self.settings.speed
return

@property
def item(self):
"""canvas item representing the ball"""
if self._item is None:
x, y = self.settings.x, self.settings.y
self._item = self.canvas.create_oval(
fill=self.settings.fill,
)
return self._item

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def update(self):
"""moves the ball
if the ball hits something, reverses direction
"""
ball = self.position
width = self.canvas.winfo_width()
if ball.top_left_x <= EDGE_OF_SCREEN or ball.bottom_right_x >= width:
self.direction.horizontal *= REVERSE_DIRECTION
if ball.top_left_y <= EDGE_OF_SCREEN:
self.direction.vertical *= REVERSE_DIRECTION
self.move(self.direction.horizontal * self.speed,
self.direction.vertical * self.speed)


The update method gets its current position and if it is off-screen on either side it inverts the horizontal direction. If the ball is above the top of the screen it reverses its vertical direction. It doesn't check the bottom of the screen because going off the bottom is how the player loses so it's an expected behavior. Once it has the directions set it moves the ball by the amount defined by the speed variable.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def collide(self, others):
"""handles collisions

Parameters
----------

others: list
collection of ther objects that the ball collided with
"""
if len(others) > 1:
self.direction.vertical *= REVERSE_DIRECTION
elif len(others) == 1:
ball = self.position
x = (ball.top_left_x + ball.bottom_right_x)/2

other = others[0].position
if x > other.bottom_right_x:
self.direction.horizontal = RIGHT
elif x < other.top_left_x:
self.direction.horizontal = LEFT
else:
self.direction.vertical *= REVERSE_DIRECTION
for other in others:
if isinstance(other, BrickWidget):
other.hit()
return


The collide method handles when a ball collides with another object. If it collided with more than one object it always reverses directions (this would only happen with bricks, not the paddle). If it collided with a single object then if the object is to the left of it (the ball's mean x-value is greater than the rightmost x-value for the object) then it sets its horizontal direction to move to the right (it bounces off it to the right). If the other object is to the right of the ball then the ball moves to the left. Otherwise the ball hit the object on top or below it so it changes vertical direction. If any of the objects are bricks then their hit methods are called.

A representation of the player's paddle.

### The Paddle Settings

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
class PaddleSettings(BaseSettings):
"""settings for the player's paddle"""
def __init__(self):
self._attributes = None
self.width = None
self.height = None
self.speed = None
self.x = None
self.y = None
self.fill = None
return

@property
def attributes(self):
"""list of required settings"""
if self._attributes is None:
self._attributes = ("width",
"height",
"speed",
"x",
"y",
"fill")
return self._attributes

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def pixel_width(self, width):
"""width of the paddle
Parameters
----------

width: int
pixel-width for the paddle
"""
self.width = width
self.check_type(width, "width", int)
self.check_positive(width, "width")
return self

def pixel_height(self, height):
"""height of the paddle

Parameters
----------

height: int
pixel-height of the paddle
"""
self.height = height
self.check_type(height, "height", int)
self.check_positive(height, "height")
return self


The height and width are offsets to add to the upper-left corner coordinates of the bounding box to locate the lower-right corner of the bounding box, thus defining the size of the paddle.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def velocity(self, speed):
"""rate at which to move the paddle
Parameters
----------

speed: number
amount to move paddle with each key stroke
"""
self.speed = speed
return self


The speed of the paddle is the amount it will move every-time an arrow key is hit. I think it's in pixels, but the units aren't clear.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def x_position(self, x):
"""initial x-position
Parameters
----------

x: int
pixels from the left of the canvas
"""
self.x = x
self.check_numeric(x, "x")
self.check_positive(x, "x")
return self

def y_position(self, y):
"""initial y-position

Parameters
----------

y: int
pixels from the top of the canvas
"""
self.y = y
self.check_numeric(y, 'y')
self.check_positive(y, "y")
return self


The x and y settings determine where the paddle will be at the start (and since it only moves horizontally the y value is where it will be vertically throughout the game).

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def color(self, fill):
"""fill color for the rectangle

Parameters
----------

fill: str
hex-code for the fill color
"""
self.fill = fill
self.check_hex_color(fill, "fill")
return self


Like with the Ball the fill value for the Paddle decides what color to fill it with.

### The Paddle Class

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
class PaddleWidget(BaseWidget):
Parameters
----------

canvas: tkinter.Canvas
the canvas to draw on
initial settings for the paddle
"""
def __init__(self, canvas, settings):
self.canvas = canvas
self.settings = settings
self._item = None
self.ball = None
return

@property
def item(self):
"""the canvas item for the paddle"""
if self._item is None:
half_width = self.settings.width/2
half_height = self.settings.height/2
x, y = self.settings.x, self.settings.y
self._item = self.canvas.create_rectangle(
x - half_width, y - half_height,
x + half_width, y + half_height,
fill=self.settings.fill
)
return self._item


The item property creates a rectangle of width x height dimensions centered around (x, y).

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def move(self, offset):
if has a ball, also moves the ball

if already flush left or flush right, does nothing

Parameters
----------

offset: int
amount to move the paddle and ball horizontally
"""
coordinates = self.position
width = self.canvas.winfo_width()
if (coordinates.top_left_x + offset >= 0 and
coordinates.bottom_right_x + offset <= width):  # noqa: E129
if self.ball is not None:
self.ball.move(offset, 0)
return


The move method moves the paddle horizontally by some offset. If moving it would place it offscreen to the left or right then it doesn't do anything. The paddle should only have the ball before the game starts (so that if the player moves the paddle the ball will stay with it until the game starts).

## The Brick

### Brick Settings

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
class BrickSettings(BaseSettings):
"""settings for the brick widget"""
def __init__(self):
self.x = None
self.y = None
self.width = None
self.height = None
self.colors = None
self.tags = None
self._attributes = None
self._hits = None
return

@property
def attributes(self):
"""list of required values"""
if self._attributes is None:
self._attributes = ("width",
"height",
"colors",
"tags",
"x",
"y",
"hits")
return self._attributes

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
@property
def hits(self):
"""the number of hits each brick will take
"""
if self._hits is None:
self._hits = max(self.colors)
return self._hits

def maximum_hits(self, hits):
"""number of hits brick will take
Parameters
----------

hits: int
number of hits before deleting bricks
"""
self._hits = hits
self.check_type(hits, "hits", int)
self.check_positive(hits, "hits")
return self


The hits value is the number of times a brick gets hit by a ball before it deletes itself. I originally make it always use the largest value but then found out different rows use different values so I added a setter method.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def x_position(self, x):
"""horizontal position
Parameters
----------
x: int or float
pixels from the left
"""
self.x = x
self.check_numeric(x, "x")
self.check_positive(x, "x")
return self

def y_position(self, y):
"""vertical position
Parameters
----------

y: int or float
pixels from the top
"""
self.y = y
self.check_numeric(y, "y")
self.check_positive(y, "y")
return self


The x and y are the center-positions for a brick. Since they don't move this is their permanent position. Like the ball, this actually gets calculated when the game is set up so making this required was probably a bad ide.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def pixel_width(self, width):
"""width of the brick
Parameters
----------

width: int
pixel-width of the brick
"""
self.width = width
self.check_type(width, "width", int)
self.check_positive(width, "width")
return self

def pixel_height(self, height):
"""height of the brick
Parameters
----------

height: int
pixel-height of the brick
"""
self.height = height
self.check_type(height, "height", int)
self.check_positive(height, "height")
return self


The height and width give the dimensions of the brick.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def level_colors(self, colors):
"""map of level to colors

Parameters
----------
colors: dict
map of integers to colors
"""
self.colors = colors
for level in range(1, len(colors) + 1):
if level not in colors:
raise TypeError("colors keys must be range starting at 1")
for level, color in colors.items():
self.check_hex_color(color, "level {0} color".format(level))
return self


As a brick gets hit it changes colors. The colors dictionary is a mapping between the number of remaining times the brick can be hit before being deleted (the level of the brick) and the color for that level.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def label(self, tags):
"""string to tag bricks

Parameters
----------

tags: str
identifier for bricks
"""
self.tags = tags
self.check_type(tags, "tags", str)
return self


The tags attribute is a string given to tkinter to identify a class of related widgets.

### Brick Widget

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
class BrickWidget(BaseWidget):
"""represents a single brick

Parameters
----------

canvas: tkinter.Canvas
what to draw the brick on
settings: BrickSettings
initial settings for the brick
"""
def __init__(self, canvas, settings):
self.canvas = canvas
self.settings = settings
self.hits = self.settings.hits
self._item = None
return

@property
def item(self):
"""canvas rectangle"""
if self._item is None:
half_height = self.settings.height/2
half_width = self.settings.width/2
x, y = self.settings.x, self.settings.y
self._item = self.canvas.create_rectangle(
x - half_width, y - half_height,
x + half_width, y + half_height,
fill=self.settings.colors[self.hits],
tags=self.settings.tags
)
return self._item


The item creation is almost the same as the one for the Paddle except that the color is based on the number of remaining hits it starts with and it gets a tag

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def hit(self):
"""the brick has been hit event
Decrements the counter and changes the color or deletes the brick
"""
self.hits -= 1
if self.hits == 0:
self.delete()
else:
self.canvas.itemconfig(self.item,
fill=self.settings.colors[self.hits])
return


The hit method decrements the number of hits the brick has remaining and deletes it if it doesn't have any left. If it does have hits left it re-colors the brick to match the number of hits remaining.

## The Frame

### The Frame Settings

These are settings for the Tkinter Frame.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
class FrameSettings(BaseSettings):
"""holds the settings for the game"""
def __init__(self):
self.width = None
self.height = None
self.color = None
self.title = None
self._attributes = None
return

@property
def attributes(self):
"""list of required attributes"""
if self._attributes is None:
self._attributes = ("width",
"height",
"color",
"title")
return self._attributes

def window_width(self, width):
"""width of window
Parameters
----------
width: int
pixel-width for the tkinter window

Returns
-------

GameSettings: this object
"""
self.width = width
self.check_type(width, "width", int)
self.check_positive(width, "width")
return self

def window_height(self, height):
"""height of window
Parameters
----------

height: int
pixel height of the window

Returns
-------

GameSettings: this object
"""
self.height = height
self.check_type(height, "height", int)
self.check_positive(height, "height")
return self

def canvas_color(self, color):
"""background color

Parameters
----------

color: string
hex-color for canvas background

Returns
-------

GameSettings: this object
"""
self.color = color
self.check_hex_color(color, 'background color')
return self

def window_title(self, title):
"""title of the window
Parameters
----------

title: str
name to give the title

Returns
-------

GameSettings: this object
"""
self.title = title
self.check_type(title, "window title", str)
return self


### The Frame Class

The Tk class creates the main window. Within it the Frame class creates a container which you pass the main window on instantiation. Within the frame a Canvas is placed to actually draw things. The pack method tells the children to display their widgets on their parents.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
class BreakoutFrame(tkinter.Frame):
"""creates the breakout game

Parameters
----------

settings: GameSettings
object with the settings
parent: Tk
parent window for this frame
"""
def __init__(self, settings, parent):
super(BreakoutFrame, self).__init__(parent)
self.parent = parent
self.parent.title(settings.title)
self.settings = settings
self._canvas = None
self.height = settings.height
return

@property
def canvas(self):
"""canvas to render images"""
if self._canvas is None:
self._canvas = tkinter.Canvas(self,
width=self.settings.width,
height=self.settings.height,
bg=self.settings.color)
return self._canvas

def __call__(self):
"""runs the main-loop"""
self.canvas.pack()
self.pack()
self.parent.mainloop()
return


## The Game

### Game Settings

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
class GameSettings(BaseSettings):
"""settings for the game"""
def __init__(self):
self.lives = None
self.text_x = None
self.text_y = None
self.text_size = None
self._attributes = None
return

@property
def attributes(self):
"""required attributes"""
if self._attributes is None:
self._attributes = ("lives",
"text_x",
"text_y",
return self._attributes

def font_size(self, size):
"""text size in pixels
Parameters
----------

size: int
size for fonts
"""
self.text_size = size
self.check_type(size, "text size", int)
self.check_positive(size, "text size")
return self

def allowed_failures(self, lives):
"""number of times player can fail

Parameters
----------

lives: int
number of failures per game
"""
self.lives = lives
self.check_type(lives, "lives", int)
self.check_positive(lives, "lives")
return self

def text_horizontal_position(self, text_x):
"""pixel indent for text

Parameters
----------

text_x: int
number of pixels from the left
"""
self.text_x = text_x
self.check_type(text_x, "text indent", int)
self.check_positive(text_x, "text indent")
return self

def text_vertical_position(self, text_y):
"""pixel vertical position for text
Parameters
----------

text_y: int
pixels from the top
"""
self.text_y = text_y
self.check_type(text_y, "text y", int)
self.check_positive(text_y, "text y")
return self

"""outer margins

Parameters
----------

pixels to put around the edge of the canvas
"""
return self


### Game Class

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
class Game(object):
"""builds and holds the game

Parameters
----------

game_settings: GameSettings
settings for the game overall

frame_settings: FrameSettings
settings to set-up the tkinter window

settings to set-up the paddle_settings

brick_settings: BrickSettings
settings to set-up the bricks

ball_settings: BallSettings
settings to set-up the ball
"""
def __init__(self, game_settings, frame_settings, paddle_settings,
brick_settings, ball_settings):
self.game_settings = game_settings
self.frame_settings = frame_settings
self.brick_settings = brick_settings
self.ball_settings = ball_settings
self.collidable = {}
self.hud = None
self._frame = None
self._canvas = None
self._bricks = None
self._ball = None
return

@property
def frame(self):
"""the tkinter frame"""
if self._frame is None:
self._frame = BreakoutFrame(self.frame_settings, tkinter.Tk())
return self._frame

@property
def canvas(self):
"""tkinter canvas to draw on"""
if self._canvas is None:
self._canvas = self.frame.canvas
return self._canvas

@property
if self._paddle is None:
.y_position(self.frame_settings.height -


The Paddle is created centered horizontally and at the height specified in the settings.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
@property
def ball(self):
"""the ball widget"""
if self._ball is None:
(self.ball_settings
.direction_vector(BallDirections(RIGHT, UP)))
self._ball = BallWidget(self.canvas, self.ball_settings)
return self._ball


The ball is created sitting on top of the paddle in its horizontal center (the mean of its x-coordinates). Even though I'm forcing the user to set the x and y values they actually get overwritten here. I also had to make sure that the ball is created above the paddle, which is why I'm adding twice the radius to the y-position, otherwise it would register as a collision and end up going down instead of up.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def add_brick(self, x, y, settings):
"""add a brick to items

Parameters
----------

x: int
pixels from the left
y: int
pixels from the top
"""
settings = (copy(settings)
.x_position(x)
.y_position(y))
brick = BrickWidget(self.canvas, settings)
self.collidable[brick.item] = brick
return

half_width = self.brick_settings.width/2
first_row = 50
second_row = first_row + self.brick_settings.height
third_row = second_row + self.brick_settings.height
first_settings = copy(self.brick_settings).maximum_hits(3)
second_settings = copy(self.brick_settings).maximum_hits(2)
third_settings = copy(self.brick_settings).maximum_hits(1)
for x in range(5, self.frame_settings.width - 5, 75):
this_x = x + half_width
return


The add_bricks method creates three rows of bricks with a 5-pixel left margin and a 50 pixel top margin. The top-row of bricks takes three hits each, the second two hits each and the bricks in the bottom row will be deleted after one hit.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def setup_canvas(self):
"""sets up some canvas settings"""
self.canvas.focus_set()
self.canvas.bind(
"<Left>",
)
self.canvas.bind(
"<Right>",
)
self.canvas.bind("<space>", lambda _: self.start())
return


The setup_canvas causes the canvas to steal focus and then sets up the keys the user uses to control the paddle and start the game.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def draw_text(self, x, y, text):
"""draws the text

Parameters
----------

x: int
left indent
y: int
right indent
text: string
what to output

Returns
-------
text-object
"""
font = ("Helvetica", self.game_settings.text_size)
return self.canvas.create_text(x,
y,
text=text, font=font)

def update_lives_text(self):
"""updates the text when a player fails"""
text = "Lives: {0}".format(self.lives)
if self.hud is None:
self.hud = self.draw_text(self.game_settings.text_x,
self.game_settings.text_y,
text)
else:
self.canvas.itemconfig(self.hud, text=text)
return

def reset(self):
"""sets up the game after it's ended"""
self.lives = self.game_settings.lives
self.setup_canvas()
self.ball.delete()
self._ball = None
self.update_lives_text()
return

def set_up(self):
"""populates the collidable items dict"""
self.lives = self.game_settings.lives
self.setup_canvas()
self.ball.delete()
self._ball = None
self.update_lives_text()
self.text = self.draw_text(300, 200, "Press Space to Start")
return

def set_up_in_between(self):
"""sets things up when the player still has lives"""
self.ball.delete()
self._ball = None
self.update_lives_text()
self.setup_canvas()
self.text = self.draw_text(300, 200, "Press Space to Start")
return

def start(self):
"""starts the game"""
self.canvas.unbind("<space>")
self.canvas.delete(self.text)
self.game_loop()
return


The start method un-binds the spacebar from the start method so the game won't restart if the player accidentally hits the spacebar. It also deletes the message to hit the spacebar to start the game, removes the ball from the paddle and starts the game-loop

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def game_loop(self):
"""runs the game"""
self.check_collisions()
num_bricks = len(self.canvas.find_withtag("brick"))
if num_bricks == 0:
self.ball.speed = None
self.text = self.draw_text(300, 200, "You Win. Whatever. (Hit the spacebar to restart)")
self.reset()
elif self.ball.position.bottom_right_y >= self.frame.height:
self.ball.speed = None
self.lives -= 1
if self.lives < 0:
self.text = self.draw_text(300, 200, "Loser (Hit the spacebar to restart)")
self.reset()
else:
self.frame.after(1000, self.set_up_in_between)
else:
self.ball.update()
self.frame.after(50, self.game_loop)
return


Besides checking for collisions, the game_loop method check's if the bricks have all been removed (in which case the player has won) or if the ball has fallen off the screen. If the ball has fallen off the screen and the player is out of lives then it ends the game, otherwise it decrements the players remaining lives. If there are still bricks and the ball is on the screen then it calls the ball's update method to move it.

The frame.after method sets a timer that will call the callback function you pass in after the delay (in milliseconds) that you pass in has expired.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def check_collisions(self):
"""checks if the ball has collided with anything"""
ball = self.ball.position
items = self.canvas.find_overlapping(*ball)
collisions = [self.collidable[item] for item in items
if item in self.collidable]
self.ball.collide(collisions)
return


check_collisions finds all the items that we added whose coordinates overlap with those of the ball then passes those items to the BallWidget.collide method to process. The overlapping widgets are filtered so that they only contain items of interest (not text-widgets, for instance).

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
def __call__(self):
"""sets up the game"""
self.set_up()
self.frame()
return


## The Main Loop

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
if __name__ == '__main__':
frame_settings = (FrameSettings()
.window_width(600)
.window_height(400)
.canvas_color(WHITE)
.window_title("Breakout! Not Pong!")())
ball_settings = (BallSettings()
.x_position(10)
.y_position(10)
.direction_vector(BallDirections(horizontal=NO_MOVEMENT,
vertical=UP))
.velocity(10)
.color(LAVENDER)())
.pixel_width(80)
.pixel_height(5)
.x_position(40)
.y_position(80)
.velocity(10)
.color(BLUE)
())

brick_settings = (BrickSettings()
.x_position(75)
.y_position(20)
.label("brick")
.pixel_width(75)
.pixel_height(20)
.level_colors({1: "#999999",
2: "#555555",
3: "#222222"})())

game_settings = (GameSettings()
.allowed_failures(3)
.text_horizontal_position(50)
.text_vertical_position(20)
.font_size(15)
)
game = Game(game_settings, frame_settings, paddle_settings, brick_settings,
ball_settings)
game()


# Inserting Text Between Methods in Org-Mode

This is an attempt to get org-mode to insert text between methods in a class definition using the noweb-ref property. I think you can also do it by just tangling everything to the same file, but I like the noweb notation better.

## The Tangle

To keep it simple I'm just going to include a section for the class definition and a main section to check out the results. Note that to be able to break up the class definition I had to turn off org-mode's clean-up so all the python blocks have to be indented exactly the way they will be in the final python file.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
<<first-class>>

<<main>>


## The First Class

This first class won't do much, but if I understand the documentation I should be able to insert text between the parts of it and still have it work when the python gets tangled out. The org-mode source block starts like this - #+BEGIN_SRC python :noweb-ref first-class.

### The Constructor

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
   class FirstClass(object):
"""a class that is first
Parameters
----------

name: string
some kind of identifier
"""
def __init__(self, name):
self.name = name
return


### The Call

The call emits the name. To concatenate this method to the previous block I'm using the same org-mode source-block header as I did with the constructor (#+BEGIN_SRC python :noweb-ref first-class). You could use a different name and insert another reference in the tangle but this seems more logical to me. One problem here is that python-mode (or some other mode) will interpret the methods as stand-alone functions and move them flush left. To fix this I had to turn off the automatic indentation using (setq org-src-preserve-indentation t). This means that you have to keep track of the indentation yourself, regardless of where the code sits in the org-mode document (so as you create sub-sections it will look uglier and uglier in the original document, at least to me). Putting the method in a separate block also requires that you to insert an empty line before the method to keep it from being stuck to the bottom of the previous one, but it doesn't include it when it gets exported to HTML, so you can't see it in this post. In fact, I noticed afterwards that the HTML export also stripped out the indentation on the left so you can't really see what I'm talking about.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
   def __call__(self):
"""prints the name"""
print(self.name)
return


## The Main

This part constructs the FirstClass object and calls it.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
  if __name__ == "__main__":
thing = FirstClass("Bob")
thing()


## Trying it out

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
  python noweb_ref.py

Bob



## Summary

The point of trying this out is that I want to be able to break up and document class-methods better. Unfortunately it requires you to do a little more fiddling with the white-space yourself and makes the source org-mode file a little harder to read (I think) but I'm going to try it for a little while and see if the resulting documents are worth the extra headache. Maybe I'll just have to stick with docstrings for documenting the separate methods…

This bit at the end makes it so the indentation is always preserved, even if the init.el file isn't set up that way.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
  # Local Variables:
# org-src-preserve-indentation: t
# End:


# Org-Babel Stderr Results

If you execute a code-block in org-mode the default behavior when the executed code sends output to stderr is to open a pop-up buffer rather than including it in the org-babel file. Sometimes, though, you might want to document actual output from stderr but, as it turns out, this is how org-mode is designed so you are mostly stuck with it. There is a simple work-around though, just put an entry in the source-block that outputs to stdout at the end of the block and everyhing will show up in the results.

This is how you could include the output when there are failing tests run by py.test:

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
#+BEGIN_SRC sh :results verbatim
py.test tests/
echo
#+END_SRC


This will run all the tests in the tests folder and include the output in the org-mode file even if there are failures, thanks to the echo at the end.

I got this from Stack Overflow, of course.

# Install Chrome Extensions in Vivaldi

This was taken from the vivaldi forums. It explains how to install the LastPass extension into the vivaldi browser and should work for other plugins as well (although I haven't tried yet).

## The Procedure

1. Install the Chrome extension source viewer (CRX Viewer) in Chrome
2. Go to the Chrome Web Store and search for the LastPass extension
3. Right click on the LastPass search result to bring up the context menu
4. In the context menu selecte View extension source
5. In the page that opens, click on the Download link in the upper corner
6. Go to the Downloads folder and make a new folder (e.g. mkdir lastpass)
7. Move the zip-file that you downloaded into the folder (mine was called hdokiejnpimakedhajhdlcegeplioahd.zip so I assume the names are random)
9. Re-name _metadata to metadata (the post suggests deleting it, so that might work too)
10. In Vivaldi, open the link vivaldi://chrome/extensions
11. Click the Developer mode checkbox
12. Click on Load unpacked extension
13. Select the folder you unpacked the zip file into (lastpass in this case)
14. Configure Last Pass

## Conclusion

This gives the procedure for installing extensions like LastPass into the Vivaldi browser. In the course of writing this up I found out that you don't need to do this for all the extensions (just the ones with leading underscores in some of their folder names, I think). For other extensions just install them from the store - they seem to work out of the box.

# Org-Babel PDF Export

These are my notes on exporting a PDF from an org-babel file.

## First Try

The key sequence to export a PDF from an org file is C-c C-e l p (c as in… c, e as in export, l as in LaTex, and p as in PDF). My first try produced this error:

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
! LaTeX Error: File ulem.sty not found.


The actual output had ulem.sty ending with an apostrophe (which I can't show here because org either renders the apostrophe as an accent or if I put it in an inline verbatim block it disables the verbatim markup - seems like a bug) but either nikola or org or something else marked the single apostrophe as an error with a red box around it in the output so I changed it to a backtick () to get rid of the box.

Past experience told me that the error indicated I was likely missing a (debian) package.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
apt-cache search ulem

texlive-generic-recommended - TeX Live: Generic recommended packages
libextutils-modulemaker-perl - Perl extension to build module from scratch



Since I'm doing something with LaTex, not perl I decided that installing the texlive-generic-recommended package was probably what I should do.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
sudo apt-get install texlive-generic-recommended


## Second try

I hit C-c C-e l p again and this time it did output a PDF, but there was no syntax-highlighting of the code. Followng this blog post I added this to my init.el file:

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
;; export to latex/pdf
(require 'ox-latex)

;; syntax-highlighting for pdf's
(add-to-list 'org-latex-packages-alist '("" "minted"))
(setq org-latex-listings 'minted)
(setq org-latex-pdf-process '("pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"))


Once I re-loaded the init.el file, the PDF's came out with the syntax highlighting working.

The original post used xelatex instead of pdflatex but I don't use xelatex. Also minted can be found in the texlive-latex-extras package if it isn't already installed. The post also mentions needing pygments but I didn't need it, possibly because it's a dependency for other python libraries that I've already installed.

# Org-Babel Cheat Sheet

## Keyboard Shortcuts

### Code Block Shortcuts

Keys Command Effect
C-c C-c org-babel-execute-src-block Execute the code in the current block.
C-c '   Open/close edit-buffer with mode set to match the code-block language.
C-c C-v C-z org-babel-switch-to-session Open a python/ipython console (only works with :session)

### Buffer-wide Shortcuts

Keys Command Effect
<s Tab   Create a code block.
C-c C-v C-b org-babel-execute-buffer Execute all code blocks in buffer.
C-c C-v C-f org-babel-tangle-file Tangle all blocks marked to :tangle
C-c C-v C-t org-babel-tangle Seems like an alias for tangle file…

## Code Block Headers

This is the subset of headers/header values that I'm interested in right now.

### Code to tangle

The pattern I use to tangle (create an external code file) is:

• python as the language (since I'm not using it with an interactive session, no need for ipython)
• :noweb tangle is turned on from init.el so that I can substitute code defined elsewhere into the block
• :tangle <path to file>
/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
  #+begin_src python :tangle literate_python/literate.py
"""A docstring for the literate.py module"""

# imports
import sys
<<literate-main-imports>>

# constants

# exception classes

# interface functions

# classes

<<LiterateClass-definition>>

# internal functions & classes

<<literate-main>>

if __name__ == "__main__":
status = main()
sys.exit(status)
#+end_src


Since I have :noweb tangle set, the substitions (e.g. <<literate-main-imports>>) don't get expanded in HTML/Latex output (although they do when you create the python file).

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
  """A docstring for the literate.py module"""

# imports
import sys
<<literate-main-imports>>


If you want to show the substitutions when exporting use :noweb yes in the header.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
  """A docstring for the literate.py module"""

# imports
import sys


### A named section

The noweb substitution above (<<literate-main-imports>>) worked because there was a named-section (defined here) that it could use:

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
  #+name: literate-main-imports
#+begin_src python
from argparse import ArgumentParser
#+end_src


#### Update

I now prefer to use :noweb-ref in the header instead of the separate #+name: block.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
  #+begin_src python :noweb-ref literate-main-imports
from argparse import ArgumentParser
#+end_src


### Results

The :results header argument declares how to handle what's returned from executing a code block. There are three classes of arguments and you can use up to one of each in the header.

#### Result Classes

Class Meaning
collection How the results should be collected if there's multiple outputs.
type Declare what type of result the code block will return.
handling How should results be handled.

#### Collection Class

Option Meaning
value (Default) Uses the value of the last statement in the block (python requires a return statement)
output (:results output) Collects everything sent to stdout in the block.

#### Type Class

Option Example Meaning
table :results value table Return an org-mode table (vector)
scalar :results value scalar Return exactly the value returned (string)
file :results value file Return an org-mode link to a file
raw :results value raw Return as org-mode command
html :results value html Expect contents for #+begin_html
latex :results value latex Expect contents for #+begin_latex
code :results value code Expect contents for #+begin_src
pp :results value pp Expect code and pretty-print it

#### Handling Class

Option Example Meaning
silent :results output silent Don't output in org-mode buffer
replace :results output replace (Default) Overwrite any previous result
append :results output append Append output after any previous output
prepend :results output prepend Put output above any previous output

### Exports

This argument tells org-babel what to put in any exported HTML or Latex files.

Option Example Meaning
code :exports code (default) The code in the block will be included in the export.
results :exports results The result of evaluating the code will be included.
both :exports both Include code and results in the file.
none :exports none Don't include anything in the file.

## Running Tests

Say there was another section in the document that tangled a test-file (named testliterate.py) to test our main source file. Once both are tangled you can run it in the document using sh as the language. The org-mode documentation shows a more complex version of this which builds a pass-fail table, but that's beyond me right now.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
   #+name: shell-run-pytest
#+begin_src sh :results output :exports both
py.test -v literate_python/testliterate.py
#+end_src

============================= test session starts ==============================
platform linux -- Python 3.5.1+, pytest-3.0.5, py-1.4.32, pluggy-0.4.0 -- /home/cronos/.virtualenvs/nikola/bin/python3
cachedir: .cache
rootdir: /home/cronos/projects/nikola/posts, inifile:
plugins: faker-2.0.0, bdd-2.18.1
collecting ... collected 1 items

literate_python/testliterate.py::test_constructor PASSED

=========================== 1 passed in 0.06 seconds ===========================


## Specific Block Cases

### Plant UML

Besides setting the language to plantuml you need to specify and output-file path and set :exports results so that the actual plantuml code won't be in the exported document but the diagram will.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
#+begin_src plantuml :file literate_python/literateclass.png :exports results
skinparam monochrome true

LiterateClass : String who
LiterateClass : String ()
#+end_src


### ob-ipython

The main thing to remember for ob-ipython is that you need to run it as a :session. I didn't do it for most of the examples, but I've found since I first wrote this that using named sessions makes it a lot easier to work. Otherwise you might have more than one buffer with an org-babel document and they will be sharing the same ipython process, which can cause mysterious errors.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
#+begin_src ipython :session session1
# python standard library
import os
#+end_src


When using pandas most of the methods produce values, but the info method instead prints to stdout so you have to specify this as the :results or it will popup a separate buffer with the output.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
#+begin_src ipython :session session1 :results output
housing.info()
#+end_src


When you create figures, besides making sure that you use the %matplotlib inline magic, you also need to specify a file path where matplotlib can save the image.

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
#+BEGIN_SRC ipython :session session1 :file "images/ocean_proximity_count.png"
figure = seaborn.countplot(x="ocean_proximity", data=housing)
#+end_src


## Set Up

### Dependencies

I'm using ob-ipython to use jupyter/ipython with org-babel so you have to install it (I used MELPA). In addition you need to install the python dependencies, the main ones being ipython and jupyter. Additionally, I use elpy (also from MELPA) which has its own dependencies. I think the easiest way to check and see what elpy dependencies you need is to install elpy (there's two components, an emacs one you install from melpa and a python component you install from pip) then run M-x elpy-config to see what's missing.

### init.el

Since I mentioned ob-ipython and elpy I'll list what I have in my init.el file for elpy and org-babel.

#### Elpy

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
;; elpy
(elpy-enable)
(setq elpy-rpc-backend "jedi")
'(define-key python-mode-map "\C-cx" 'jedi-direx:pop-to-buffer))
(elpy-use-ipython)


#### org-babel

/home/athena/.virtualenvs/necromuralist.github.io/bin/python3: No module named virtualfish
;; org-babel
;;; syntax-highlighting/editing
(add-to-list 'org-src-lang-modes '("rst" . "rst"))
(add-to-list 'org-src-lang-modes '("feature" . "feature"))

;;; languages to execute/edit
'((ipython . t)
(plantuml . t)
(shell . t)
(org . t)
;; other languages..
))

;;; noweb expansion only when you tangle
(cons '(:noweb . "tangle")
`