diff --git a/tests/test_course_1/_sources/activecode.rst b/tests/test_course_1/_sources/activecode.rst
new file mode 100644
index 000000000..61db40840
--- /dev/null
+++ b/tests/test_course_1/_sources/activecode.rst
@@ -0,0 +1,2829 @@
+:orphan:
+
+This is copied directly from ``index.rst`` in the Runestone Components ActiveCode tests.
+
+ActiveCode Test
+===============
+Note: an existing server-side test is named ``test_activecode_1``. So, we start numbering here at 2.
+
+.. activecode:: test_activecode_2
+
+ print("Hello World")
+
+
+.. activecode:: test_activecode_2a
+
+ This question has multiple lines of explanatory
+ text prior to the editing area or scaffolded code.
+ ~~~~
+ print("Hello World")
+
+
+.. activecode:: testprefixcode
+
+ This is a question that has some hidden prefix code.
+ ~~~~
+ for ch in "prefix":
+ print(ch)
+ hide = True
+ ^^^^
+ # Your code Here
+ print("My Code")
+ ====
+ if hide:
+ print("hidden code")
+
+
+.. datafile:: Shape.java
+ :hide:
+
+ public abstract class Shape {
+ String name;
+ public Shape(String name) {
+ this.name = name;
+ }
+
+ public abstract double getArea();
+
+ public String getName() {
+ return this.name;
+ }
+ }
+
+.. activecode:: test_activecode_3
+ :language: java
+ :datafile: Shape.java
+
+ public class Square extends Shape {
+ double width;
+ public Square(String name, double width) {
+ super(name);
+ this.width = width;
+ }
+
+ public double getArea() {
+ return width * width;
+ }
+
+ public static void main(String args[]) {
+ Shape s = new Square("Box", 5);
+ System.out.print("Width: " + s.getArea());
+ }
+ }
+
+
+.. raw:: html
+
+
+
+
+
+.. activecode:: test_activecode_4
+ :language: java
+ :datafile: turtleClasses.jar, arch.jpg
+
+ import java.awt.*;
+ import java.awt.font.*;
+ import java.awt.geom.*;
+ import java.awt.image.BufferedImage;
+ import java.text.*;
+ import java.util.*;
+ import java.util.List; // resolves problem with java.awt.List and java.util.List
+
+ /**
+ * A class that represents a picture. This class inherits from
+ * SimplePicture and allows the student to add functionality to
+ * the Picture class.
+ *
+ * @author Barbara Ericson ericson@cc.gatech.edu
+ */
+ public class Picture extends SimplePicture
+ {
+ ///////////////////// constructors //////////////////////////////////
+
+ /**
+ * Constructor that takes no arguments
+ */
+ public Picture ()
+ {
+ /* not needed but use it to show students the implicit call to super()
+ * child constructors always call a parent constructor
+ */
+ super();
+ }
+
+ /**
+ * Constructor that takes a file name and creates the picture
+ * @param fileName the name of the file to create the picture from
+ */
+ public Picture(String fileName)
+ {
+ // let the parent class handle this fileName
+ super(fileName);
+ }
+
+ /**
+ * Constructor that takes the height and width
+ * @param height the height of the desired picture
+ * @param width the width of the desired picture
+ */
+ public Picture(int height, int width)
+ {
+ // let the parent class handle this width and height
+ super(width,height);
+ }
+
+ /**
+ * Constructor that takes a picture and creates a
+ * copy of that picture
+ * @param copyPicture the picture to copy
+ */
+ public Picture(Picture copyPicture)
+ {
+ // let the parent class do the copy
+ super(copyPicture);
+ }
+
+ /**
+ * Constructor that takes a buffered image
+ * @param image the buffered image to use
+ */
+ public Picture(BufferedImage image)
+ {
+ super(image);
+ }
+ ////////////////////// methods ///////////////////////////////////////
+
+ /**
+ * Method to return a string with information about this picture.
+ * @return a string with information about the picture such as fileName,
+ * height and width.
+ */
+ public String toString()
+ {
+ String output = "Picture, filename " + getFileName() +
+ " height " + getHeight()
+ + " width " + getWidth();
+ return output;
+
+ }
+
+ public void switchColors()
+ {
+ Pixel[][] pixels = this.getPixels2D();
+ int red, green, blue = 0;
+
+ for (Pixel[] rowArray : pixels)
+ {
+ for (Pixel p: rowArray)
+ {
+ red = p.getRed();
+ green = p.getGreen();
+ blue = p.getBlue();
+ p.setRed(green);
+ p.setGreen(blue);
+ p.setBlue(red);
+
+ }
+ }
+ }
+
+ /* Main method for testing - each class in Java can have a main
+ * method
+ */
+ public static void main(String[] args)
+ {
+ Picture arch = new Picture("arch.jpg");
+ arch.show();
+ arch.switchColors();
+ arch.show();
+ }
+
+ } // this } is the end of class Picture, put all new methods before this
+
+
+Support for SQL in the browser ? Yes!
+--------------------------------------
+.. activecode:: test_activecode_6
+ :language: sql
+ :autograde: unittest
+ :dburl: /_static/test.db
+
+ select * from test;
+
+ =====
+ assert 1,1 == world
+ assert 0,1 == hello
+ assert 2,1 == 42
+
+.. :dburl: http://dev.runestoneinteractive.org:8080/_static/bikeshare.db
+
+
+.. activecode:: test_activecode_7
+ :language: sql
+ :autograde: unittest
+ :dburl: /_static/test.db
+
+ select * from test;
+
+
+.. activecode:: sql3
+ :language: sql
+
+ CREATE TABLE contacts (
+ contact_id INTEGER PRIMARY KEY,
+ first_name TEXT NOT NULL,
+ last_name TEXT NOT NULL,
+ email TEXT NOT NULL UNIQUE,
+ phone TEXT NOT NULL UNIQUE
+ );
+
+
+
+.. datafile:: turtleClasses.jar
+
+ import java.awt.Image;
+ import java.awt.image.BufferedImage;
+
+ /**
+ * Interface to describe a digital picture. A digital picture can have an
+ * associated file name. It can have a title. It has pixels
+ * associated with it and you can get and set the pixels. You
+ * can get an Image from a picture or a BufferedImage. You can load
+ * it from a file name or image. You can show a picture. You can
+ * explore a picture. You can create a new image for it.
+ *
+ * @author Barb Ericson ericson@cc.gatech.edu
+ */
+ public interface DigitalPicture
+ {
+ public String getFileName(); // get the file name that the picture came from
+ public String getTitle(); // get the title of the picture
+ public void setTitle(String title); // set the title of the picture
+ public int getWidth(); // get the width of the picture in pixels
+ public int getHeight(); // get the height of the picture in pixels
+ public Image getImage(); // get the image from the picture
+ public BufferedImage getBufferedImage(); // get the buffered image
+ public int getBasicPixel(int x, int y); // get the pixel information as an int
+ public void setBasicPixel(int x, int y, int rgb); // set the pixel information
+ public Pixel getPixel(int x, int y); // get the pixel information as an object
+ public Pixel[] getPixels(); // get all pixels in row-major order
+ public Pixel[][] getPixels2D(); // get 2-D array of pixels in row-major order
+ public void load(Image image); // load the image into the picture
+ public boolean load(String fileName); // load the picture from a file
+ public void show(); // show the picture
+ public boolean write(String fileName); // write out a file
+ }
+ import java.awt.Graphics;
+
+ /**
+ * Interface to used to communicate between a model
+ * and its display
+ *
+ * Copyright Georgia Institute of Technology 2004
+ * @author Barb Ericson ericson@cc.gatech.edu
+ */
+ public interface ModelDisplay
+ {
+ /** method to notify the thing that displays that
+ * the model has changed */
+ public void modelChanged();
+
+ /** method to add the model to the world
+ * @param model the model object to add */
+ public void addModel(Object model);
+
+ /**
+ * Method to remove the model from the world
+ * @param model the model object to remove */
+ public void remove(Object model);
+
+ /**
+ * Method that returns the graphics context
+ * for this model display
+ * @return the graphics context
+ */
+ public Graphics getGraphics();
+
+ /**
+ * Method to clear the background
+ */
+ public void clearBackground();
+
+ /** Method to get the width of the display
+ * @return the width in pixels of the display
+ */
+ public int getWidth();
+
+ /** Method to get the height of the display
+ * @return the height in pixels of the display
+ */
+ public int getHeight();
+ }
+ import java.awt.*;
+ import java.awt.geom.*;
+
+ /**
+ * This class represents a displayable path segment
+ * it has a color, width, and a Line2D object
+ * Copyright Georgia Institute of Technology 2005
+ * @author Barb Ericson ericson@cc.gatech.edu
+ */
+ @SuppressWarnings("unchecked")
+ public class PathSegment
+ {
+ //////////////// fields /////////////////////
+ private Color color;
+ private int width;
+ private Line2D.Float line;
+
+ //////////////// constructors ///////////////
+
+ /**
+ * Constructor that takes the color, width,
+ * and line
+ */
+ public PathSegment (Color theColor, int theWidth,
+ Line2D.Float theLine)
+ {
+ this.color = theColor;
+ this.width = theWidth;
+ this.line = theLine;
+ }
+
+ //////////////// methods ////////////////////
+
+ /**
+ * Method to paint this path segment
+ * @param g the graphics context
+ */
+ public void paintComponent(Graphics g)
+ {
+ Graphics2D g2 = (Graphics2D) g;
+ BasicStroke penStroke = new BasicStroke(this.width);
+ g2.setStroke(penStroke);
+ g2.setColor(this.color);
+ g2.draw(this.line);
+ }
+
+ } // end of class
+ import java.awt.*;
+ import java.awt.geom.*;
+ import javax.swing.*;
+ import java.util.List;
+ import java.util.ArrayList;
+ import java.util.Iterator;
+
+ /**
+ * Class to represent a pen which has a color, width,
+ * and a list of path segments that it should draw.
+ * A pen also knows if it is up or down
+ *
+ * Copyright Georgia Institute of Technology 2004
+ * @author Barb Ericson ericson@cc.gatech.edu
+ */
+ @SuppressWarnings("unchecked")
+ public class Pen
+ {
+ ////////////////// fields //////////////////////
+
+ /** track if up or down */
+ private boolean penDown = true;
+
+ /** color of ink */
+ private Color color = Color.green;
+
+ /** width of stroke */
+ private int width = 1;
+
+ /** list of path segment objects to draw */
+ private List pathSegmentList =
+ new ArrayList();
+
+ //////////////// constructors ///////////////////
+
+ /**
+ * Constructor that takes no arguments
+ */
+ public Pen() { }
+
+ /**
+ * Constructor that takes all the ink color, and width
+ * @param color the ink color
+ * @param width the width in pixels
+ */
+ public Pen(Color color, int width)
+ {
+ this.color = color;
+ this.width = width;
+ }
+
+ /**
+ * Constructor that takes the ink color, width, and penDown flag
+ * @param color the ink color
+ * @param width the width in pixels
+ * @param penDown the flag if the pen is down
+ */
+ public Pen(Color color, int width, boolean penDown)
+ {
+ // use the other constructor to set these
+ this(color,width);
+
+ // set the pen down flag
+ this.penDown = penDown;
+ }
+
+ ////////////////// methods ///////////////////////
+
+ /**
+ * Method to get pen down status
+ * @return true if the pen is down else false
+ */
+ public boolean isPenDown() { return penDown; }
+
+ /**
+ * Method to set the pen down value
+ * @param value the new value to use
+ */
+ public void setPenDown(boolean value) { penDown = value; }
+
+ /**
+ * Method to get the pen (ink) color
+ * @return the ink color
+ */
+ public Color getColor() { return color; }
+
+ /**
+ * Method to set the pen (ink) color
+ * @param color the color to use
+ */
+ public void setColor(Color color) { this.color = color;}
+
+ /**
+ * Method to get the width of the pen
+ * @return the width in pixels
+ */
+ public int getWidth() { return width; }
+
+ /**
+ * Method to set the width of the pen
+ * @param width the width to use in pixels
+ */
+ public void setWidth(int width) { this.width = width; }
+
+ /**
+ * Method to add a path segment if the pen is down
+ * @param x1 the first x
+ * @param y1 the first y
+ * @param x2 the second x
+ * @param y2 the second y
+ */
+ public synchronized void addMove(int x1, int y1, int x2, int y2)
+ {
+ if (penDown)
+ {
+ PathSegment pathSeg =
+ new PathSegment(this.color,this.width,
+ new Line2D.Float(x1,y1,x2,y2));
+ pathSegmentList.add(pathSeg);
+ }
+ }
+
+ /**
+ * Method to clear the path stored for this pen
+ */
+ public void clearPath()
+ {
+ pathSegmentList.clear();
+ }
+
+ /**
+ * Metod to paint the pen path
+ * @param g the graphics context
+ */
+ public synchronized void paintComponent(Graphics g)
+ {
+
+ Color oldcolor = g.getColor();
+
+ // loop through path segment list and
+ Iterator iterator = pathSegmentList.iterator();
+ PathSegment pathSeg = null;
+
+ // loop through path segments
+ while (iterator.hasNext())
+ {
+ pathSeg = (PathSegment) iterator.next();
+ pathSeg.paintComponent(g);
+ }
+
+ g.setColor(oldcolor);
+ }
+
+ } // end of class
+
+
+ import java.awt.Color;
+
+ /**
+ * Class that references a pixel in a picture. Pixel
+ * stands for picture element where picture is
+ * abbreviated pix. A pixel has a column (x) and
+ * row (y) location in a picture. A pixel knows how
+ * to get and set the red, green, blue, and alpha
+ * values in the picture. A pixel also knows how to get
+ * and set the color using a Color object.
+ *
+ * @author Barb Ericson ericson@cc.gatech.edu
+ */
+ @SuppressWarnings("unchecked")
+ public class Pixel
+ {
+
+ ////////////////////////// fields ///////////////////////////////////
+
+ /** the digital picture this pixel belongs to */
+ private DigitalPicture picture;
+
+ /** the x (column) location of this pixel in the picture; (0,0) is top left */
+ private int x;
+
+ /** the y (row) location of this pixel in the picture; (0,0) is top left */
+ private int y;
+
+ ////////////////////// constructors /////////////////////////////////
+
+ /**
+ * A constructor that takes the x and y location for the pixel and
+ * the picture the pixel is coming from
+ * @param picture the picture that the pixel is in
+ * @param x the x location of the pixel in the picture
+ * @param y the y location of the pixel in the picture
+ */
+ public Pixel(DigitalPicture picture, int x, int y)
+ {
+ // set the picture
+ this.picture = picture;
+
+ // set the x location
+ this.x = x;
+
+ // set the y location
+ this.y = y;
+
+ }
+
+ ///////////////////////// methods //////////////////////////////
+
+ /**
+ * Method to get the x location of this pixel.
+ * @return the x location of the pixel in the picture
+ */
+ public int getX() { return x; }
+
+ /**
+ * Method to get the y location of this pixel.
+ * @return the y location of the pixel in the picture
+ */
+ public int getY() { return y; }
+
+ /**
+ * Method to get the row (y value)
+ * @return the row (y value) of the pixel in the picture
+ */
+ public int getRow() { return y; }
+
+ /**
+ * Method to get the column (x value)
+ * @return the column (x value) of the pixel
+ */
+ public int getCol() { return x; }
+
+ /**
+ * Method to get the amount of alpha (transparency) at this pixel.
+ * It will be from 0-255.
+ * @return the amount of alpha (transparency)
+ */
+ public int getAlpha() {
+
+ /* get the value at the location from the picture as a 32 bit int
+ * with alpha, red, green, blue each taking 8 bits from left to right
+ */
+ int value = picture.getBasicPixel(x,y);
+
+ // get the alpha value (starts at 25 so shift right 24)
+ // then and it with all 1's for the first 8 bits to keep
+ // end up with from 0 to 255
+ int alpha = (value >> 24) & 0xff;
+
+ return alpha;
+ }
+
+ /**
+ * Method to get the amount of red at this pixel. It will be
+ * from 0-255 with 0 being no red and 255 being as much red as
+ * you can have.
+ * @return the amount of red from 0 for none to 255 for max
+ */
+ public int getRed() {
+
+ /* get the value at the location from the picture as a 32 bit int
+ * with alpha, red, green, blue each taking 8 bits from left to right
+ */
+ int value = picture.getBasicPixel(x,y);
+
+ // get the red value (starts at 17 so shift right 16)
+ // then AND it with all 1's for the first 8 bits to
+ // end up with a resulting value from 0 to 255
+ int red = (value >> 16) & 0xff;
+
+ return red;
+ }
+
+ /**
+ * Method to get the red value from a pixel represented as an int
+ * @param value the color value as an int
+ * @return the amount of red
+ */
+ public static int getRed(int value)
+ {
+ int red = (value >> 16) & 0xff;
+ return red;
+ }
+
+ /**
+ * Method to get the amount of green at this pixel. It will be
+ * from 0-255 with 0 being no green and 255 being as much green as
+ * you can have.
+ * @return the amount of green from 0 for none to 255 for max
+ */
+ public int getGreen() {
+
+ /* get the value at the location from the picture as a 32 bit int
+ * with alpha, red, green, blue each taking 8 bits from left to right
+ */
+ int value = picture.getBasicPixel(x,y);
+
+ // get the green value (starts at 9 so shift right 8)
+ int green = (value >> 8) & 0xff;
+
+ return green;
+ }
+
+ /**
+ * Method to get the green value from a pixel represented as an int
+ * @param value the color value as an int
+ * @return the amount of green
+ */
+ public static int getGreen(int value)
+ {
+ int green = (value >> 8) & 0xff;
+ return green;
+ }
+
+ /**
+ * Method to get the amount of blue at this pixel. It will be
+ * from 0-255 with 0 being no blue and 255 being as much blue as
+ * you can have.
+ * @return the amount of blue from 0 for none to 255 for max
+ */
+ public int getBlue() {
+
+ /* get the value at the location from the picture as a 32 bit int
+ * with alpha, red, green, blue each taking 8 bits from left to right
+ */
+ int value = picture.getBasicPixel(x,y);
+
+ // get the blue value (starts at 0 so no shift required)
+ int blue = value & 0xff;
+
+ return blue;
+ }
+
+ /**
+ * Method to get the blue value from a pixel represented as an int
+ * @param value the color value as an int
+ * @return the amount of blue
+ */
+ public static int getBlue(int value)
+ {
+ int blue = value & 0xff;
+ return blue;
+ }
+
+ /**
+ * Method to get a color object that represents the color at this pixel.
+ * @return a color object that represents the pixel color
+ */
+ public Color getColor()
+ {
+ /* get the value at the location from the picture as a 32 bit int
+ * with alpha, red, green, blue each taking 8 bits from left to right
+ */
+ int value = picture.getBasicPixel(x,y);
+
+ // get the red value (starts at 17 so shift right 16)
+ // then AND it with all 1's for the first 8 bits to
+ // end up with a resulting value from 0 to 255
+ int red = (value >> 16) & 0xff;
+
+ // get the green value (starts at 9 so shift right 8)
+ int green = (value >> 8) & 0xff;
+
+ // get the blue value (starts at 0 so no shift required)
+ int blue = value & 0xff;
+
+ return new Color(red,green,blue);
+ }
+
+ /**
+ * Method to set the pixel color to the passed in color object.
+ * @param newColor the new color to use
+ */
+ public void setColor(Color newColor)
+ {
+ // set the red, green, and blue values
+ int red = newColor.getRed();
+ int green = newColor.getGreen();
+ int blue = newColor.getBlue();
+
+ // update the associated picture
+ updatePicture(this.getAlpha(),red,green,blue);
+ }
+
+ /**
+ * Method to update the picture based on the passed color
+ * values for this pixel
+ * @param alpha the alpha (transparency) at this pixel
+ * @param red the red value for the color at this pixel
+ * @param green the green value for the color at this pixel
+ * @param blue the blue value for the color at this pixel
+ */
+ public void updatePicture(int alpha, int red, int green, int blue)
+ {
+ // create a 32 bit int with alpha, red, green blue from left to right
+ int value = (alpha << 24) + (red << 16) + (green << 8) + blue;
+
+ // update the picture with the int value
+ picture.setBasicPixel(x,y,value);
+ }
+
+ /**
+ * Method to correct a color value to be within 0 to 255
+ * @param the value to use
+ * @return a value within 0 to 255
+ */
+ private static int correctValue(int value)
+ {
+ if (value < 0)
+ value = 0;
+ if (value > 255)
+ value = 255;
+ return value;
+ }
+
+ /**
+ * Method to set the red to a new red value
+ * @param value the new value to use
+ */
+ public void setRed(int value)
+ {
+ // set the red value to the corrected value
+ int red = correctValue(value);
+
+ // update the pixel value in the picture
+ updatePicture(getAlpha(), red, getGreen(), getBlue());
+ }
+
+ /**
+ * Method to set the green to a new green value
+ * @param value the value to use
+ */
+ public void setGreen(int value)
+ {
+ // set the green value to the corrected value
+ int green = correctValue(value);
+
+ // update the pixel value in the picture
+ updatePicture(getAlpha(), getRed(), green, getBlue());
+ }
+
+ /**
+ * Method to set the blue to a new blue value
+ * @param value the new value to use
+ */
+ public void setBlue(int value)
+ {
+ // set the blue value to the corrected value
+ int blue = correctValue(value);
+
+ // update the pixel value in the picture
+ updatePicture(getAlpha(), getRed(), getGreen(), blue);
+ }
+
+ /**
+ * Method to set the alpha (transparency) to a new alpha value
+ * @param value the new value to use
+ */
+ public void setAlpha(int value)
+ {
+ // make sure that the alpha is from 0 to 255
+ int alpha = correctValue(value);
+
+ // update the associated picture
+ updatePicture(alpha, getRed(), getGreen(), getBlue());
+ }
+
+ /**
+ * Method to get the distance between this pixel's color and the passed color
+ * @param testColor the color to compare to
+ * @return the distance between this pixel's color and the passed color
+ */
+ public double colorDistance(Color testColor)
+ {
+ double redDistance = this.getRed() - testColor.getRed();
+ double greenDistance = this.getGreen() - testColor.getGreen();
+ double blueDistance = this.getBlue() - testColor.getBlue();
+ double distance = Math.sqrt(redDistance * redDistance +
+ greenDistance * greenDistance +
+ blueDistance * blueDistance);
+ return distance;
+ }
+
+ /**
+ * Method to compute the color distances between two color objects
+ * @param color1 a color object
+ * @param color2 a color object
+ * @return the distance between the two colors
+ */
+ public static double colorDistance(Color color1,Color color2)
+ {
+ double redDistance = color1.getRed() - color2.getRed();
+ double greenDistance = color1.getGreen() - color2.getGreen();
+ double blueDistance = color1.getBlue() - color2.getBlue();
+ double distance = Math.sqrt(redDistance * redDistance +
+ greenDistance * greenDistance +
+ blueDistance * blueDistance);
+ return distance;
+ }
+
+ /**
+ * Method to get the average of the colors of this pixel
+ * @return the average of the red, green, and blue values
+ */
+ public double getAverage()
+ {
+ double average = (getRed() + getGreen() + getBlue()) / 3.0;
+ return average;
+ }
+
+ /**
+ * Method to return a string with information about this pixel
+ * @return a string with information about this pixel
+ */
+ public String toString()
+ {
+ return "Pixel row=" + getRow() +
+ " col=" + getCol() +
+ " red=" + getRed() +
+ " green=" + getGreen() +
+ " blue=" + getBlue();
+ }
+
+ }
+ import javax.imageio.ImageIO;
+ import java.awt.image.BufferedImage;
+ import javax.swing.ImageIcon;
+ import java.awt.*;
+ import java.io.*;
+ import java.awt.geom.*;
+
+ import java.io.ByteArrayOutputStream;
+ // import javax.xml.bind.DatatypeConverter;
+ // Using java.util.Base64 instead of javax.xml.bind
+ import java.util.Base64;
+ import java.util.Scanner;
+
+ /**
+ * A class that represents a simple picture. A simple picture may have
+ * an associated file name and a title. A simple picture has pixels,
+ * width, and height. A simple picture uses a BufferedImage to
+ * hold the pixels. You can also explore a simple picture.
+ *
+ * @author Barb Ericson ericson@cc.gatech.edu
+ */
+ @SuppressWarnings("unchecked")
+ public class SimplePicture implements DigitalPicture
+ {
+
+ /////////////////////// Fields /////////////////////////
+
+ /**
+ * the file name associated with the simple picture
+ */
+ private String fileName;
+
+ /**
+ * the path name for the file
+ */
+ private String pathName;
+
+ /**
+ * the title of the simple picture
+ */
+ private String title;
+
+ /**
+ * buffered image to hold pixels for the simple picture
+ */
+ private BufferedImage bufferedImage;
+
+ /**
+ * extension for this file (jpg or bmp)
+ */
+ private String extension;
+
+
+ /////////////////////// Constructors /////////////////////////
+
+ /**
+ * A Constructor that takes no arguments. It creates a picture with
+ * a width of 200 and a height of 100 that is all white.
+ * A no-argument constructor must be given in order for a class to
+ * be able to be subclassed. By default all subclasses will implicitly
+ * call this in their parent's no-argument constructor unless a
+ * different call to super() is explicitly made as the first line
+ * of code in a constructor.
+ */
+ public SimplePicture()
+ {this(200,100);}
+
+ /**
+ * A Constructor that takes a file name and uses the file to create
+ * a picture
+ * @param fileName the file name to use in creating the picture
+ */
+ public SimplePicture(String fileName)
+ {
+
+ // load the picture into the buffered image
+ load(fileName);
+
+ }
+
+ /**
+ * A constructor that takes the width and height desired for a picture and
+ * creates a buffered image of that size. This constructor doesn't
+ * show the picture. The pixels will all be white.
+ * @param width the desired width
+ * @param height the desired height
+ */
+ public SimplePicture(int width, int height)
+ {
+ bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+ title = "None";
+ fileName = "None";
+ extension = "jpg";
+ setAllPixelsToAColor(Color.white);
+ }
+
+ /**
+ * A constructor that takes the width and height desired for a picture and
+ * creates a buffered image of that size. It also takes the
+ * color to use for the background of the picture.
+ * @param width the desired width
+ * @param height the desired height
+ * @param theColor the background color for the picture
+ */
+ public SimplePicture(int width, int height, Color theColor)
+ {
+ this(width,height);
+ setAllPixelsToAColor(theColor);
+ }
+
+ /**
+ * A Constructor that takes a picture to copy information from
+ * @param copyPicture the picture to copy from
+ */
+ public SimplePicture(SimplePicture copyPicture)
+ {
+ if (copyPicture.fileName != null)
+ {
+ this.fileName = new String(copyPicture.fileName);
+ this.extension = copyPicture.extension;
+ }
+ if (copyPicture.title != null)
+ this.title = new String(copyPicture.title);
+ if (copyPicture.bufferedImage != null)
+ {
+ this.bufferedImage = new BufferedImage(copyPicture.getWidth(),
+ copyPicture.getHeight(), BufferedImage.TYPE_INT_RGB);
+ this.copyPicture(copyPicture);
+ }
+ }
+
+ /**
+ * A constructor that takes a buffered image
+ * @param image the buffered image
+ */
+ public SimplePicture(BufferedImage image)
+ {
+ this.bufferedImage = image;
+ title = "None";
+ fileName = "None";
+ extension = "jpg";
+ }
+
+ ////////////////////////// Methods //////////////////////////////////
+
+ /**
+ * Method to get the extension for this picture
+ * @return the extension (jpg, bmp, giff, etc)
+ */
+ public String getExtension() { return extension; }
+
+ /**
+ * Method that will copy all of the passed source picture into
+ * the current picture object
+ * @param sourcePicture the picture object to copy
+ */
+ public void copyPicture(SimplePicture sourcePicture)
+ {
+ Pixel sourcePixel = null;
+ Pixel targetPixel = null;
+
+ // loop through the columns
+ for (int sourceX = 0, targetX = 0;
+ sourceX < sourcePicture.getWidth() &&
+ targetX < this.getWidth();
+ sourceX++, targetX++)
+ {
+ // loop through the rows
+ for (int sourceY = 0, targetY = 0;
+ sourceY < sourcePicture.getHeight() &&
+ targetY < this.getHeight();
+ sourceY++, targetY++)
+ {
+ sourcePixel = sourcePicture.getPixel(sourceX,sourceY);
+ targetPixel = this.getPixel(targetX,targetY);
+ targetPixel.setColor(sourcePixel.getColor());
+ }
+ }
+
+ }
+
+ /**
+ * Method to set the color in the picture to the passed color
+ * @param color the color to set to
+ */
+ public void setAllPixelsToAColor(Color color)
+ {
+ // loop through all x
+ for (int x = 0; x < this.getWidth(); x++)
+ {
+ // loop through all y
+ for (int y = 0; y < this.getHeight(); y++)
+ {
+ getPixel(x,y).setColor(color);
+ }
+ }
+ }
+
+ /**
+ * Method to get the buffered image
+ * @return the buffered image
+ */
+ public BufferedImage getBufferedImage()
+ {
+ return bufferedImage;
+ }
+
+ /**
+ * Method to get a graphics object for this picture to use to draw on
+ * @return a graphics object to use for drawing
+ */
+ public Graphics getGraphics()
+ {
+ return bufferedImage.getGraphics();
+ }
+
+ /**
+ * Method to get a Graphics2D object for this picture which can
+ * be used to do 2D drawing on the picture
+ */
+ public Graphics2D createGraphics()
+ {
+ return bufferedImage.createGraphics();
+ }
+
+ /**
+ * Method to get the file name associated with the picture
+ * @return the file name associated with the picture
+ */
+ public String getFileName() { return fileName; }
+
+ /**
+ * Method to set the file name
+ * @param name the full pathname of the file
+ */
+ public void setFileName(String name)
+ {
+ fileName = name;
+ }
+
+ /**
+ * Method to get the title of the picture
+ * @return the title of the picture
+ */
+ public String getTitle()
+ { return title; }
+
+ /**
+ * Method to set the title for the picture
+ * @param title the title to use for the picture
+ */
+ public void setTitle(String title)
+ {
+ this.title = title;
+ }
+
+ /**
+ * Method to get the width of the picture in pixels
+ * @return the width of the picture in pixels
+ */
+ public int getWidth() { return bufferedImage.getWidth(); }
+
+ /**
+ * Method to get the height of the picture in pixels
+ * @return the height of the picture in pixels
+ */
+ public int getHeight() { return bufferedImage.getHeight(); }
+
+ /**
+ * Method to get an image from the picture
+ * @return the buffered image since it is an image
+ */
+ public Image getImage()
+ {
+ return bufferedImage;
+ }
+
+ /**
+ * Method to return the pixel value as an int for the given x and y location
+ * @param x the x coordinate of the pixel
+ * @param y the y coordinate of the pixel
+ * @return the pixel value as an integer (alpha, red, green, blue)
+ */
+ public int getBasicPixel(int x, int y)
+ {
+ return bufferedImage.getRGB(x,y);
+ }
+
+ /**
+ * Method to set the value of a pixel in the picture from an int
+ * @param x the x coordinate of the pixel
+ * @param y the y coordinate of the pixel
+ * @param rgb the new rgb value of the pixel (alpha, red, green, blue)
+ */
+ public void setBasicPixel(int x, int y, int rgb)
+ {
+ bufferedImage.setRGB(x,y,rgb);
+ }
+
+ /**
+ * Method to get a pixel object for the given x and y location
+ * @param x the x location of the pixel in the picture
+ * @param y the y location of the pixel in the picture
+ * @return a Pixel object for this location
+ */
+ public Pixel getPixel(int x, int y)
+ {
+ // create the pixel object for this picture and the given x and y location
+ Pixel pixel = new Pixel(this,x,y);
+ return pixel;
+ }
+
+ /**
+ * Method to get a one-dimensional array of Pixels for this simple picture
+ * @return a one-dimensional array of Pixel objects starting with y=0
+ * to y=height-1 and x=0 to x=width-1.
+ */
+ public Pixel[] getPixels()
+ {
+ int width = getWidth();
+ int height = getHeight();
+ Pixel[] pixelArray = new Pixel[width * height];
+
+ // loop through height rows from top to bottom
+ for (int row = 0; row < height; row++)
+ for (int col = 0; col < width; col++)
+ pixelArray[row * width + col] = new Pixel(this,col,row);
+
+ return pixelArray;
+ }
+
+ /**
+ * Method to get a two-dimensional array of Pixels for this simple picture
+ * @return a two-dimensional array of Pixel objects in row-major order.
+ */
+ public Pixel[][] getPixels2D()
+ {
+ int width = getWidth();
+ int height = getHeight();
+ Pixel[][] pixelArray = new Pixel[height][width];
+
+ // loop through height rows from top to bottom
+ for (int row = 0; row < height; row++)
+ for (int col = 0; col < width; col++)
+ pixelArray[row][col] = new Pixel(this,col,row);
+
+ return pixelArray;
+ }
+
+ /**
+ * Method to load the buffered image with the passed image
+ * @param image the image to use
+ */
+ public void load(Image image)
+ {
+ // get a graphics context to use to draw on the buffered image
+ Graphics2D graphics2d = bufferedImage.createGraphics();
+
+ // draw the image on the buffered image starting at 0,0
+ graphics2d.drawImage(image,0,0,null);
+
+ // show the new image
+ show();
+ }
+
+ /**
+ * Method to show the picture in a picture frame
+ */
+ public void show()
+ {
+ try {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ ImageIO.write(this.bufferedImage, "png", output);
+ String result =
+ // DatatypeConverter.printBase64Binary(output.toByteArray());
+ // using java.util.Base64 instead of java.xml.bind.DataTypeConverter
+ Base64.getEncoder().encodeToString(output.toByteArray());
+ System.out.println("<img src=\'data:image/" + this.extension + ";base64," + result + "\'/>");
+ } catch (IOException e) {
+ System.out.println("Errors occured in image conversion");
+ }
+ }
+
+ /**
+ * Method to load the picture from the passed file name
+ * @param fileName the file name to use to load the picture from
+ * @throws IOException if the picture isn't found
+ */
+ public void loadOrFail(String fileName) throws IOException
+ {
+ // set the current picture's file name
+ this.fileName = fileName;
+
+ // set the extension
+ int posDot = fileName.lastIndexOf('.');
+ if (posDot >= 0)
+ this.extension = fileName.substring(posDot + 1);
+
+ //get file location
+ String[] paths = fileName.split("/");
+ this.pathName = "";
+ if(paths.length != 1) {
+ for(int i = 0; i < paths.length - 1; i++) {
+ this.pathName = this.pathName + paths[i] + "/";
+ }
+ }
+ // if the current title is null use the file name
+ if (title == null)
+ title = fileName;
+
+ File file = new File(this.fileName);
+
+ if (!file.canRead())
+ {
+ throw new IOException(this.fileName +
+ " could not be opened. Check that you specified the path");
+ }
+ bufferedImage = ImageIO.read(file);
+
+
+ }
+
+
+ /**
+ * Method to read the contents of the picture from a filename
+ * without throwing errors
+ * @param fileName the name of the file to write the picture to
+ * @return true if success else false
+ */
+ public boolean load(String fileName)
+ {
+ try {
+ this.loadOrFail(fileName);
+ return true;
+
+ } catch (Exception ex) {
+ System.out.println("There was an error trying to open " + fileName);
+ bufferedImage = new BufferedImage(600,200,
+ BufferedImage.TYPE_INT_RGB);
+ addMessage("Couldn't load " + fileName,5,100);
+ return false;
+ }
+
+ }
+
+ /**
+ * Method to load the picture from the passed file name
+ * this just calls load(fileName) and is for name compatibility
+ * @param fileName the file name to use to load the picture from
+ * @return true if success else false
+ */
+ public boolean loadImage(String fileName)
+ {
+ return load(fileName);
+ }
+
+ /**
+ * Method to draw a message as a string on the buffered image
+ * @param message the message to draw on the buffered image
+ * @param xPos the x coordinate of the leftmost point of the string
+ * @param yPos the y coordinate of the bottom of the string
+ */
+ public void addMessage(String message, int xPos, int yPos)
+ {
+ // get a graphics context to use to draw on the buffered image
+ Graphics2D graphics2d = bufferedImage.createGraphics();
+
+ // set the color to white
+ graphics2d.setPaint(Color.white);
+
+ // set the font to Helvetica bold style and size 16
+ graphics2d.setFont(new Font("Helvetica",Font.BOLD,16));
+
+ // draw the message
+ graphics2d.drawString(message,xPos,yPos);
+
+ }
+
+ /**
+ * Method to draw a string at the given location on the picture
+ * @param text the text to draw
+ * @param xPos the left x for the text
+ * @param yPos the top y for the text
+ */
+ public void drawString(String text, int xPos, int yPos)
+ {
+ addMessage(text,xPos,yPos);
+ }
+
+ /**
+ * Method to create a new picture by scaling the current
+ * picture by the given x and y factors
+ * @param xFactor the amount to scale in x
+ * @param yFactor the amount to scale in y
+ * @return the resulting picture
+ */
+ public Picture scale(double xFactor, double yFactor)
+ {
+ // set up the scale transform
+ AffineTransform scaleTransform = new AffineTransform();
+ scaleTransform.scale(xFactor,yFactor);
+
+ // create a new picture object that is the right size
+ Picture result = new Picture((int) (getHeight() * yFactor),
+ (int) (getWidth() * xFactor));
+
+ // get the graphics 2d object to draw on the result
+ Graphics graphics = result.getGraphics();
+ Graphics2D g2 = (Graphics2D) graphics;
+
+ // draw the current image onto the result image scaled
+ g2.drawImage(this.getImage(),scaleTransform,null);
+
+ return result;
+ }
+
+ /**
+ * Method to create a new picture of the passed width.
+ * The aspect ratio of the width and height will stay
+ * the same.
+ * @param width the desired width
+ * @return the resulting picture
+ */
+ public Picture getPictureWithWidth(int width)
+ {
+ // set up the scale transform
+ double xFactor = (double) width / this.getWidth();
+ Picture result = scale(xFactor,xFactor);
+ return result;
+ }
+
+ /**
+ * Method to create a new picture of the passed height.
+ * The aspect ratio of the width and height will stay
+ * the same.
+ * @param height the desired height
+ * @return the resulting picture
+ */
+ public Picture getPictureWithHeight(int height)
+ {
+ // set up the scale transform
+ double yFactor = (double) height / this.getHeight();
+ Picture result = scale(yFactor,yFactor);
+ return result;
+ }
+
+ /**
+ * Method to load a picture from a file name and show it in a picture frame
+ * @param fileName the file name to load the picture from
+ * @return true if success else false
+ */
+ public boolean loadPictureAndShowIt(String fileName)
+ {
+ boolean result = true; // the default is that it worked
+
+ // try to load the picture into the buffered image from the file name
+ result = load(fileName);
+
+ // show the picture in a picture frame
+ show();
+
+ return result;
+ }
+
+ /**
+ * Method to write the contents of the picture to a file with
+ * the passed name
+ * @param fileName the name of the file to write the picture to
+ */
+ public void writeOrFail(String fileName) throws IOException
+ {
+ String extension = this.extension; // the default is current
+
+ // create the file object
+ File file = new File(fileName);
+
+ // get the extension
+ int posDot = fileName.indexOf('.');
+ if (posDot >= 0)
+ extension = fileName.substring(posDot + 1);
+
+ // write the contents of the buffered image to the file
+ ImageIO.write(bufferedImage, extension, file);
+
+ }
+
+ /**
+ * Method to write the contents of the picture to a file with
+ * the passed name without throwing errors
+ * @param fileName the name of the file to write the picture to
+ * @return true if success else false
+ */
+ public boolean write(String fileName)
+ {
+ try {
+ this.writeOrFail(fileName);
+ return true;
+ } catch (Exception ex) {
+ System.out.println("There was an error trying to write " + fileName);
+ ex.printStackTrace();
+ return false;
+ }
+
+ }
+
+ /**
+ * Method to get the coordinates of the enclosing rectangle after this
+ * transformation is applied to the current picture
+ * @return the enclosing rectangle
+ */
+ public Rectangle2D getTransformEnclosingRect(AffineTransform trans)
+ {
+ int width = getWidth();
+ int height = getHeight();
+ double maxX = width - 1;
+ double maxY = height - 1;
+ double minX, minY;
+ Point2D.Double p1 = new Point2D.Double(0,0);
+ Point2D.Double p2 = new Point2D.Double(maxX,0);
+ Point2D.Double p3 = new Point2D.Double(maxX,maxY);
+ Point2D.Double p4 = new Point2D.Double(0,maxY);
+ Point2D.Double result = new Point2D.Double(0,0);
+ Rectangle2D.Double rect = null;
+
+ // get the new points and min x and y and max x and y
+ trans.deltaTransform(p1,result);
+ minX = result.getX();
+ maxX = result.getX();
+ minY = result.getY();
+ maxY = result.getY();
+ trans.deltaTransform(p2,result);
+ minX = Math.min(minX,result.getX());
+ maxX = Math.max(maxX,result.getX());
+ minY = Math.min(minY,result.getY());
+ maxY = Math.max(maxY,result.getY());
+ trans.deltaTransform(p3,result);
+ minX = Math.min(minX,result.getX());
+ maxX = Math.max(maxX,result.getX());
+ minY = Math.min(minY,result.getY());
+ maxY = Math.max(maxY,result.getY());
+ trans.deltaTransform(p4,result);
+ minX = Math.min(minX,result.getX());
+ maxX = Math.max(maxX,result.getX());
+ minY = Math.min(minY,result.getY());
+ maxY = Math.max(maxY,result.getY());
+
+ // create the bounding rectangle to return
+ rect = new Rectangle2D.Double(minX,minY,maxX - minX + 1, maxY - minY + 1);
+ return rect;
+ }
+
+ /**
+ * Method to get the coordinates of the enclosing rectangle after this
+ * transformation is applied to the current picture
+ * @return the enclosing rectangle
+ */
+ public Rectangle2D getTranslationEnclosingRect(AffineTransform trans)
+ {
+ return getTransformEnclosingRect(trans);
+ }
+
+ /**
+ * Method to return a string with information about this picture
+ * @return a string with information about the picture
+ */
+ public String toString()
+ {
+ String output = "Simple Picture, filename " + fileName +
+ " height " + getHeight() + " width " + getWidth();
+ return output;
+ }
+
+ } // end of SimplePicture class
+ import javax.swing.*;
+ import java.awt.*;
+ import java.awt.font.*;
+ import java.awt.geom.*;
+ import java.util.Observer;
+ import java.util.Random;
+
+ /**
+ * Class that represents a Logo-style turtle. The turtle
+ * starts off facing north.
+ * A turtle can have a name, has a starting x and y position,
+ * has a heading, has a width, has a height, has a visible
+ * flag, has a body color, can have a shell color, and has a pen.
+ * The turtle will not go beyond the model display or picture
+ * boundaries.
+ *
+ * You can display this turtle in either a picture or in
+ * a class that implements ModelDisplay.
+ *
+ * Copyright Georgia Institute of Technology 2004
+ * @author Barb Ericson ericson@cc.gatech.edu
+ */
+ @SuppressWarnings("unchecked")
+ public class SimpleTurtle
+ {
+ ///////////////// fields ////////////////////////
+
+ /** count of the number of turtles created */
+ private static int numTurtles = 0;
+
+ /** array of colors to use for the turtles */
+ private static Color[] colorArray = { Color.green, Color.cyan, new Color(204,0,204), Color.gray};
+
+ /** who to notify about changes to this turtle */
+ private ModelDisplay modelDisplay = null;
+
+ /** picture to draw this turtle on */
+ private Picture picture = null;
+
+ /** width of turtle in pixels */
+ private int width = 15;
+
+ /** height of turtle in pixels */
+ private int height = 18;
+
+ /** current location in x (center) */
+ private int xPos = 0;
+
+ /** current location in y (center) */
+ private int yPos = 0;
+
+ /** heading angle */
+ private double heading = 0; // default is facing north
+
+ /** pen to use for this turtle */
+ private Pen pen = new Pen();
+
+ /** color to draw the body in */
+ private Color bodyColor = null;
+
+ /** color to draw the shell in */
+ private Color shellColor = null;
+
+ /** color of information string */
+ private Color infoColor = Color.black;
+
+ /** flag to say if this turtle is visible */
+ private boolean visible = true;
+
+ /** flag to say if should show turtle info */
+ private boolean showInfo = false;
+
+ /** the name of this turtle */
+ private String name = "No name";
+
+ ////////////////// constructors ///////////////////
+
+ /**
+ * Constructor that takes the x and y position for the
+ * turtle
+ * @param x the x pos
+ * @param y the y pos
+ */
+ public SimpleTurtle(int x, int y)
+ {
+ xPos = x;
+ yPos = y;
+ bodyColor = colorArray[numTurtles % colorArray.length];
+ setPenColor(bodyColor);
+ numTurtles++;
+ }
+
+ /**
+ * Constructor that takes the x and y position and the
+ * model displayer
+ * @param x the x pos
+ * @param y the y pos
+ * @param display the model display
+ */
+ public SimpleTurtle(int x, int y, ModelDisplay display)
+ {
+ this(x,y); // invoke constructor that takes x and y
+ modelDisplay = display;
+ display.addModel(this);
+ }
+
+ /**
+ * Constructor that takes a model display and adds
+ * a turtle in the middle of it
+ * @param display the model display
+ */
+ public SimpleTurtle(ModelDisplay display)
+ {
+ // invoke constructor that takes x and y
+ this((int) (display.getWidth() / 2),
+ (int) (display.getHeight() / 2));
+ modelDisplay = display;
+ display.addModel(this);
+
+ }
+
+ /**
+ * Constructor that takes the x and y position and the
+ * picture to draw on
+ * @param x the x pos
+ * @param y the y pos
+ * @param picture the picture to draw on
+ */
+ public SimpleTurtle(int x, int y, Picture picture)
+ {
+ this(x,y); // invoke constructor that takes x and y
+ this.picture = picture;
+ this.visible = false; // default is not to see the turtle
+ }
+
+ /**
+ * Constructor that takes the
+ * picture to draw on and will appear in the middle
+ * @param picture the picture to draw on
+ */
+ public SimpleTurtle(Picture picture)
+ {
+ // invoke constructor that takes x and y
+ this((int) (picture.getWidth() / 2),
+ (int) (picture.getHeight() / 2));
+ this.picture = picture;
+ this.visible = false; // default is not to see the turtle
+ }
+
+ //////////////////// methods /////////////////////////
+
+ /**
+ * Get the distance from the passed x and y location
+ * @param x the x location
+ * @param y the y location
+ */
+ public double getDistance(int x, int y)
+ {
+ int xDiff = x - xPos;
+ int yDiff = y - yPos;
+ return (Math.sqrt((xDiff * xDiff) + (yDiff * yDiff)));
+ }
+
+ /**
+ * Method to turn to face another simple turtle
+ */
+ public void turnToFace(SimpleTurtle turtle)
+ {
+ turnToFace(turtle.xPos,turtle.yPos);
+ }
+
+ /**
+ * Method to turn towards the given x and y
+ * @param x the x to turn towards
+ * @param y the y to turn towards
+ */
+ public void turnToFace(int x, int y)
+ {
+ double dx = x - this.xPos;
+ double dy = y - this.yPos;
+ double arcTan = 0.0;
+ double angle = 0.0;
+
+ // avoid a divide by 0
+ if (dx == 0)
+ {
+ // if below the current turtle
+ if (dy > 0)
+ heading = 180;
+
+ // if above the current turtle
+ else if (dy < 0)
+ heading = 0;
+ }
+ // dx isn't 0 so can divide by it
+ else
+ {
+ arcTan = Math.toDegrees(Math.atan(dy / dx));
+ if (dx < 0)
+ heading = arcTan - 90;
+ else
+ heading = arcTan + 90;
+ }
+
+ // notify the display that we need to repaint
+ updateDisplay();
+ }
+
+ /**
+ * Method to get the picture for this simple turtle
+ * @return the picture for this turtle (may be null)
+ */
+ public Picture getPicture() { return this.picture; }
+
+ /**
+ * Method to set the picture for this simple turtle
+ * @param pict the picture to use
+ */
+ public void setPicture(Picture pict) { this.picture = pict; }
+
+ /**
+ * Method to get the model display for this simple turtle
+ * @return the model display if there is one else null
+ */
+ public ModelDisplay getModelDisplay() { return this.modelDisplay; }
+
+ /**
+ * Method to set the model display for this simple turtle
+ * @param theModelDisplay the model display to use
+ */
+ public void setModelDisplay(ModelDisplay theModelDisplay)
+ { this.modelDisplay = theModelDisplay; }
+
+ /**
+ * Method to get value of show info
+ * @return true if should show info, else false
+ */
+ public boolean getShowInfo() { return this.showInfo; }
+
+ /**
+ * Method to show the turtle information string
+ * @param value the value to set showInfo to
+ */
+ public void setShowInfo(boolean value) { this.showInfo = value; }
+
+ /**
+ * Method to get the shell color
+ * @return the shell color
+ */
+ public Color getShellColor()
+ {
+ Color color = null;
+ if (this.shellColor == null && this.bodyColor != null)
+ color = bodyColor.darker();
+ else color = this.shellColor;
+ return color;
+ }
+
+ /**
+ * Method to set the shell color
+ * @param color the color to use
+ */
+ public void setShellColor(Color color) { this.shellColor = color; }
+
+ /**
+ * Method to get the body color
+ * @return the body color
+ */
+ public Color getBodyColor() { return this.bodyColor; }
+
+ /**
+ * Method to set the body color which
+ * will also set the pen color
+ * @param color the color to use
+ */
+ public void setBodyColor(Color color)
+ {
+ this.bodyColor = color;
+ setPenColor(this.bodyColor);
+ }
+
+ /**
+ * Method to set the color of the turtle.
+ * This will set the body color
+ * @param color the color to use
+ */
+ public void setColor(Color color) { this.setBodyColor(color); }
+
+ /**
+ * Method to get the information color
+ * @return the color of the information string
+ */
+ public Color getInfoColor() { return this.infoColor; }
+
+ /**
+ * Method to set the information color
+ * @param color the new color to use
+ */
+ public void setInfoColor(Color color) { this.infoColor = color; }
+
+ /**
+ * Method to return the width of this object
+ * @return the width in pixels
+ */
+ public int getWidth() { return this.width; }
+
+ /**
+ * Method to return the height of this object
+ * @return the height in pixels
+ */
+ public int getHeight() { return this.height; }
+
+ /**
+ * Method to set the width of this object
+ * @param theWidth in width in pixels
+ */
+ public void setWidth(int theWidth) { this.width = theWidth; }
+
+ /**
+ * Method to set the height of this object
+ * @param theHeight the height in pixels
+ */
+ public void setHeight(int theHeight) { this.height = theHeight; }
+
+ /**
+ * Method to get the current x position
+ * @return the x position (in pixels)
+ */
+ public int getXPos() { return this.xPos; }
+
+ /**
+ * Method to get the current y position
+ * @return the y position (in pixels)
+ */
+ public int getYPos() { return this.yPos; }
+
+ /**
+ * Method to get the pen
+ * @return the pen
+ */
+ public Pen getPen() { return this.pen; }
+
+ /**
+ * Method to set the pen
+ * @param thePen the new pen to use
+ */
+ public void setPen(Pen thePen) { this.pen = thePen; }
+
+ /**
+ * Method to check if the pen is down
+ * @return true if down else false
+ */
+ public boolean isPenDown() { return this.pen.isPenDown(); }
+
+ /**
+ * Method to set the pen down boolean variable
+ * @param value the value to set it to
+ */
+ public void setPenDown(boolean value) { this.pen.setPenDown(value); }
+
+ /**
+ * Method to lift the pen up
+ */
+ public void penUp() { this.pen.setPenDown(false);}
+
+ /**
+ * Method to set the pen down
+ */
+ public void penDown() { this.pen.setPenDown(true);}
+
+ /**
+ * Method to get the pen color
+ * @return the pen color
+ */
+ public Color getPenColor() { return this.pen.getColor(); }
+
+ /**
+ * Method to set the pen color
+ * @param color the color for the pen ink
+ */
+ public void setPenColor(Color color) { this.pen.setColor(color); }
+
+ /**
+ * Method to set the pen width
+ * @param width the width to use in pixels
+ */
+ public void setPenWidth(int width) { this.pen.setWidth(width); }
+
+ /**
+ * Method to get the pen width
+ * @return the width of the pen in pixels
+ */
+ public int getPenWidth() { return this.pen.getWidth(); }
+
+ /**
+ * Method to clear the path (history of
+ * where the turtle has been)
+ */
+ public void clearPath()
+ {
+ this.pen.clearPath();
+ }
+
+ /**
+ * Method to get the current heading
+ * @return the heading in degrees
+ */
+ public double getHeading() { return this.heading; }
+
+ /**
+ * Method to set the heading
+ * @param heading the new heading to use
+ */
+ public void setHeading(double heading)
+ {
+ this.heading = heading;
+ }
+
+ /**
+ * Method to get the name of the turtle
+ * @return the name of this turtle
+ */
+ public String getName() { return this.name; }
+
+ /**
+ * Method to set the name of the turtle
+ * @param theName the new name to use
+ */
+ public void setName(String theName)
+ {
+ this.name = theName;
+ }
+
+ /**
+ * Method to get the value of the visible flag
+ * @return true if visible else false
+ */
+ public boolean isVisible() { return this.visible;}
+
+ /**
+ * Method to hide the turtle (stop showing it)
+ * This doesn't affect the pen status
+ */
+ public void hide() { this.setVisible(false); }
+
+ /**
+ * Method to show the turtle (doesn't affect
+ * the pen status
+ */
+ public void show() { this.setVisible(true); }
+
+ /**
+ * Method to set the visible flag
+ * @param value the value to set it to
+ */
+ public void setVisible(boolean value)
+ {
+ // if the turtle wasn't visible and now is
+ if (visible == false && value == true)
+ {
+ // update the display
+ this.updateDisplay();
+ }
+
+ // set the visibile flag to the passed value
+ this.visible = value;
+ }
+
+ /**
+ * Method to update the display of this turtle and
+ * also check that the turtle is in the bounds
+ */
+ public synchronized void updateDisplay()
+ {
+ // check that x and y are at least 0
+ if (xPos < 0)
+ xPos = 0;
+ if (yPos < 0)
+ yPos = 0;
+
+ // if picture
+ if (picture != null)
+ {
+ if (xPos >= picture.getWidth())
+ xPos = picture.getWidth() - 1;
+ if (yPos >= picture.getHeight())
+ yPos = picture.getHeight() - 1;
+ Graphics g = picture.getGraphics();
+ paintComponent(g);
+ }
+ else if (modelDisplay != null)
+ {
+ if (xPos >= modelDisplay.getWidth())
+ xPos = modelDisplay.getWidth() - 1;
+ if (yPos >= modelDisplay.getHeight())
+ yPos = modelDisplay.getHeight() - 1;
+ modelDisplay.modelChanged();
+ }
+ }
+
+ /**
+ * Method to move the turtle foward 100 pixels
+ */
+ public void forward() { forward(100); }
+
+ /**
+ * Method to move the turtle forward the given number of pixels
+ * @param pixels the number of pixels to walk forward in the heading direction
+ */
+ public void forward(int pixels)
+ {
+ int oldX = xPos;
+ int oldY = yPos;
+
+ // change the current position
+ xPos = oldX + (int) (pixels * Math.sin(Math.toRadians(heading)));
+ yPos = oldY + (int) (pixels * -Math.cos(Math.toRadians(heading)));
+
+ // add a move from the old position to the new position to the pen
+ pen.addMove(oldX,oldY,xPos,yPos);
+
+ // update the display to show the new line
+ updateDisplay();
+ }
+
+ /**
+ * Method to go backward by 100 pixels
+ */
+ public void backward()
+ {
+ backward(100);
+ }
+
+ /**
+ * Method to go backward a given number of pixels
+ * @param pixels the number of pixels to walk backward
+ */
+ public void backward(int pixels)
+ {
+ forward(-pixels);
+ }
+
+ /**
+ * Method to move to turtle to the given x and y location
+ * @param x the x value to move to
+ * @param y the y value to move to
+ */
+ public void moveTo(int x, int y)
+ {
+ this.pen.addMove(xPos,yPos,x,y);
+ this.xPos = x;
+ this.yPos = y;
+ this.updateDisplay();
+ }
+
+ /**
+ * Method to turn left
+ */
+ public void turnLeft()
+ {
+ this.turn(-90);
+ }
+
+ /**
+ * Method to turn right
+ */
+ public void turnRight()
+ {
+ this.turn(90);
+ }
+
+ /**
+ * Method to turn the turtle the passed degrees
+ * use negative to turn left and pos to turn right
+ * @param degrees the amount to turn in degrees
+ */
+ public void turn(double degrees)
+ {
+ this.heading = (heading + degrees) % 360;
+ this.updateDisplay();
+ }
+
+ /**
+ * Method to draw a passed picture at the current turtle
+ * location and rotation in a picture or model display
+ * @param dropPicture the picture to drop
+ */
+ public synchronized void drop(Picture dropPicture)
+ {
+ Graphics2D g2 = null;
+
+ // only do this if drawing on a picture
+ if (picture != null)
+ g2 = (Graphics2D) picture.getGraphics();
+ else if (modelDisplay != null)
+ g2 = (Graphics2D) modelDisplay.getGraphics();
+
+ // if g2 isn't null
+ if (g2 != null)
+ {
+
+ // save the current tranform
+ AffineTransform oldTransform = g2.getTransform();
+
+ // rotate to turtle heading and translate to xPos and yPos
+ g2.rotate(Math.toRadians(heading),xPos,yPos);
+
+ // draw the passed picture
+ g2.drawImage(dropPicture.getImage(),xPos,yPos,null);
+
+ // reset the tranformation matrix
+ g2.setTransform(oldTransform);
+
+ // draw the pen
+ pen.paintComponent(g2);
+ }
+ }
+
+ /**
+ * Method to paint the turtle
+ * @param g the graphics context to paint on
+ */
+ public synchronized void paintComponent(Graphics g)
+ {
+ // cast to 2d object
+ Graphics2D g2 = (Graphics2D) g;
+
+ // if the turtle is visible
+ if (visible)
+ {
+ // save the current tranform
+ AffineTransform oldTransform = g2.getTransform();
+
+ // rotate the turtle and translate to xPos and yPos
+ g2.rotate(Math.toRadians(heading),xPos,yPos);
+
+ // determine the half width and height of the shell
+ int halfWidth = (int) (width/2); // of shell
+ int halfHeight = (int) (height/2); // of shell
+ int quarterWidth = (int) (width/4); // of shell
+ int thirdHeight = (int) (height/3); // of shell
+ int thirdWidth = (int) (width/3); // of shell
+
+ // draw the body parts (head)
+ g2.setColor(bodyColor);
+ g2.fillOval(xPos - quarterWidth,
+ yPos - halfHeight - (int) (height/3),
+ halfWidth, thirdHeight);
+ g2.fillOval(xPos - (2 * thirdWidth),
+ yPos - thirdHeight,
+ thirdWidth,thirdHeight);
+ g2.fillOval(xPos - (int) (1.6 * thirdWidth),
+ yPos + thirdHeight,
+ thirdWidth,thirdHeight);
+ g2.fillOval(xPos + (int) (1.3 * thirdWidth),
+ yPos - thirdHeight,
+ thirdWidth,thirdHeight);
+ g2.fillOval(xPos + (int) (0.9 * thirdWidth),
+ yPos + thirdHeight,
+ thirdWidth,thirdHeight);
+
+
+ // draw the shell
+ g2.setColor(getShellColor());
+ g2.fillOval(xPos - halfWidth,
+ yPos - halfHeight, width, height);
+
+ // draw the info string if the flag is true
+ if (showInfo)
+ drawInfoString(g2);
+
+ // reset the tranformation matrix
+ g2.setTransform(oldTransform);
+ }
+
+ // draw the pen
+ pen.paintComponent(g);
+ }
+
+ /**
+ * Method to draw the information string
+ * @param g the graphics context
+ */
+ public synchronized void drawInfoString(Graphics g)
+ {
+ g.setColor(infoColor);
+ g.drawString(this.toString(),xPos + (int) (width/2),yPos);
+ }
+
+ /**
+ * Method to return a string with informaiton
+ * about this turtle
+ * @return a string with information about this object
+ */
+ public String toString()
+ {
+ return this.name + " turtle at " + this.xPos + ", " +
+ this.yPos + " heading " + this.heading + ".";
+ }
+
+ } // end of class
+ import java.util.*;
+ import java.awt.*;
+
+ /**
+ * Class that represents a turtle which is similar to a Logo turtle.
+ * This class inherts from SimpleTurtle and is for students
+ * to add methods to.
+ *
+ * Copyright Georgia Institute of Technology 2004
+ * @author Barb Ericson ericson@cc.gatech.edu
+ */
+ @SuppressWarnings("unchecked")
+ public class Turtle extends SimpleTurtle
+ {
+ ////////////////// constructors ///////////////////////
+
+ /** Constructor that takes the x and y and a picture to
+ * draw on
+ * @param x the starting x position
+ * @param y the starting y position
+ * @param picture the picture to draw on
+ */
+ public Turtle (int x, int y, Picture picture)
+ {
+ // let the parent constructor handle it
+ super(x,y,picture);
+ }
+
+ /** Constructor that takes the x and y and a model
+ * display to draw it on
+ * @param x the starting x position
+ * @param y the starting y position
+ * @param modelDisplayer the thing that displays the model
+ */
+ public Turtle (int x, int y,
+ ModelDisplay modelDisplayer)
+ {
+ // let the parent constructor handle it
+ super(x,y,modelDisplayer);
+ }
+
+ /** Constructor that takes the model display
+ * @param modelDisplay the thing that displays the model
+ */
+ public Turtle (ModelDisplay modelDisplay)
+ {
+ // let the parent constructor handle it
+ super(modelDisplay);
+ }
+
+ /**
+ * Constructor that takes a picture to draw on
+ * @param p the picture to draw on
+ */
+ public Turtle (Picture p)
+ {
+ // let the parent constructor handle it
+ super(p);
+ }
+
+ /////////////////// methods ///////////////////////
+
+
+ public static void main(String[] args)
+ {
+ World earth = new World();
+ Turtle t1 = new Turtle(earth);
+ t1.forward();
+ }
+
+ } // this is the end of class Turtle, put all new methods before this
+ /**
+ * https://github.com/ha-shine/Giffer
+ */
+ import java.awt.Graphics2D;
+ import java.awt.Image;
+ import java.awt.image.BufferedImage;
+ import java.io.File;
+ import java.io.IOException;
+ import java.util.Iterator;
+
+ import javax.imageio.IIOException;
+ import javax.imageio.IIOImage;
+ import javax.imageio.ImageIO;
+ import javax.imageio.ImageTypeSpecifier;
+ import javax.imageio.ImageWriter;
+ import javax.imageio.metadata.IIOInvalidTreeException;
+ import javax.imageio.metadata.IIOMetadata;
+ import javax.imageio.metadata.IIOMetadataNode;
+ import javax.imageio.stream.ImageOutputStream;
+
+ /*
+ * Giffer is a simple java class to make my life easier in creating gif images.
+ *
+ * Usage :
+ * There are two methods for creating gif images
+ * To generate from files, just pass the array of filename Strings to this method
+ * Giffer.generateFromFiles(String[] filenames, String output, int delay, boolean loop)
+ *
+ * Or as an alternative you can use this method which accepts an array of BufferedImage
+ * Giffer.generateFromBI(BufferedImage[] images, String output, int delay, boolean loop)
+ *
+ * output is the name of the output file
+ * delay is time between frames, accepts hundredth of a time. Yeah it's weird, blame Oracle
+ * loop is the boolean for whether you want to make the image loopable.
+ */
+
+ public abstract class Giffer {
+
+ // Generate gif from an array of filenames
+ // Make the gif loopable if loop is true
+ // Set the delay for each frame according to the delay (ms)
+ // Use the name given in String output for output file
+ public static void generateFromFiles(String[] filenames, String output, int delay, boolean loop)
+ throws IIOException, IOException
+ {
+ int length = filenames.length;
+ BufferedImage[] img_list = new BufferedImage[length];
+
+ for (int i = 0; i < length; i++)
+ {
+ BufferedImage img = ImageIO.read(new File(filenames[i]));
+ img_list[i] = img;
+ }
+
+ generateFromBI(img_list, output, delay, loop);
+ }
+
+ // Generate gif from BufferedImage array
+ // Make the gif loopable if loop is true
+ // Set the delay for each frame according to the delay, 100 = 1s
+ // Use the name given in String output for output file
+ public static void generateFromBI(BufferedImage[] images, String output, int delay, boolean loop)
+ throws IIOException, IOException
+ {
+ int maxWidth = 0;
+ int maxHeight = 0;
+ ImageWriter gifWriter = getWriter();
+ ImageOutputStream ios = getImageOutputStream(output);
+ IIOMetadata metadata = getMetadata(gifWriter, delay, loop);
+
+ //Get bigger Width and Height
+ for (BufferedImage img: images)
+ {
+ if(img.getHeight() > maxHeight){
+ maxHeight = img.getHeight();
+ }
+ if(img.getWidth() > maxWidth){
+ maxWidth = img.getWidth();
+ }
+ }
+
+ gifWriter.setOutput(ios);
+ gifWriter.prepareWriteSequence(null);
+ for (BufferedImage img: images)
+ {
+ BufferedImage dimg = new BufferedImage(maxWidth, maxHeight, BufferedImage.TYPE_INT_ARGB);
+ Image tmp = img.getScaledInstance(img.getWidth(), img.getHeight(), Image.SCALE_DEFAULT);
+ Graphics2D g2d = dimg.createGraphics();
+ int centerWidth = (maxWidth / 2) - (img.getWidth()/2) ;
+ g2d.drawImage(tmp, centerWidth, 0, null);
+ g2d.dispose();
+
+ IIOImage temp = new IIOImage(dimg, null, metadata);
+ gifWriter.writeToSequence(temp, null);
+ }
+
+ gifWriter.endWriteSequence();
+ }
+
+ // Retrieve gif writer
+ private static ImageWriter getWriter() throws IIOException
+ {
+ Iterator itr = ImageIO.getImageWritersByFormatName("gif");
+ if(itr.hasNext())
+ return (ImageWriter)itr.next();
+
+ throw new IIOException("GIF writer doesn't exist on this JVM!");
+ }
+
+ // Retrieve output stream from the given file name
+ private static ImageOutputStream getImageOutputStream(String output) throws IOException
+ {
+ File outfile = new File(output);
+ return ImageIO.createImageOutputStream(outfile);
+ }
+
+ // Prepare metadata from the user input, add the delays and make it loopable
+ // based on the method parameters
+ private static IIOMetadata getMetadata(ImageWriter writer, int delay, boolean loop)
+ throws IIOInvalidTreeException
+ {
+ // Get the whole metadata tree node, the name is javax_imageio_gif_image_1.0
+ // Not sure why I need the ImageTypeSpecifier, but it doesn't work without it
+ ImageTypeSpecifier img_type = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB);
+ IIOMetadata metadata = writer.getDefaultImageMetadata(img_type, null);
+ String native_format = metadata.getNativeMetadataFormatName();
+ IIOMetadataNode node_tree = (IIOMetadataNode)metadata.getAsTree(native_format);
+
+ // Set the delay time you can see the format specification on this page
+ // https://docs.oracle.com/javase/7/docs/api/javax/imageio/metadata/doc-files/gif_metadata.html
+ IIOMetadataNode graphics_node = getNode("GraphicControlExtension", node_tree);
+ graphics_node.setAttribute("delayTime", String.valueOf(delay));
+ graphics_node.setAttribute("disposalMethod", "none");
+ graphics_node.setAttribute("userInputFlag", "FALSE");
+
+ if(loop)
+ makeLoopy(node_tree);
+
+ metadata.setFromTree(native_format, node_tree);
+
+ return metadata;
+ }
+
+ // Add an extra Application Extension node if the user wants it to be loopable
+ // I am not sure about this part, got the code from StackOverflow
+ // TODO: Study about this
+ private static void makeLoopy(IIOMetadataNode root)
+ {
+ IIOMetadataNode app_extensions = getNode("ApplicationExtensions", root);
+ IIOMetadataNode app_node = getNode("ApplicationExtension", app_extensions);
+
+ app_node.setAttribute("applicationID", "NETSCAPE");
+ app_node.setAttribute("authenticationCode", "2.0");
+ app_node.setUserObject(new byte[]{ 0x1, (byte) (0 & 0xFF), (byte) ((0 >> 8) & 0xFF)});
+
+ app_extensions.appendChild(app_node);
+ root.appendChild(app_extensions);
+ }
+
+ // Retrieve the node with the name from the parent root node
+ // Append the node if the node with the given name doesn't exist
+ private static IIOMetadataNode getNode(String node_name, IIOMetadataNode root)
+ {
+ IIOMetadataNode node = null;
+
+ for (int i = 0; i < root.getLength(); i++)
+ {
+ if(root.item(i).getNodeName().compareToIgnoreCase(node_name) == 0)
+ {
+ node = (IIOMetadataNode) root.item(i);
+ return node;
+ }
+ }
+
+ // Append the node with the given name if it doesn't exist
+ node = new IIOMetadataNode(node_name);
+ root.appendChild(node);
+
+ return node;
+ }
+ }
+ import javax.swing.*;
+ import java.util.List;
+ import java.util.ArrayList;
+ import java.util.Iterator;
+ import java.util.Observer;
+ import java.awt.*;
+
+ import java.net.*;
+ import java.io.*;
+ // import javax.xml.bind.DatatypeConverter;
+ // Using java.util.Base64 instead of javax.xml.bind
+ import java.util.Base64;
+ import javax.imageio.*;
+ import java.awt.image.*;
+ import javax.imageio.stream.*;
+
+
+ /**
+ * Class to represent a 2d world that can hold turtles and
+ * display them
+ *
+ * Copyright Georgia Institute of Technology 2004
+ * @author Barb Ericson ericson@cc.gatech.edu
+ */
+ @SuppressWarnings("unchecked")
+ public class World implements ModelDisplay
+ {
+ ////////////////// fields ///////////////////////
+
+ /** should automatically repaint when model changed */
+ private boolean autoRepaint = true;
+
+ /** the background color for the world */
+ private Color background = Color.white;
+
+ /** the width of the world */
+ private int width = 640;
+
+ /** the height of the world */
+ private int height = 480;
+
+ /** the list of turtles in the world */
+ private List turtleList = new ArrayList();
+
+ /** background picture */
+ private Picture picture = null;
+
+ /* All world changes*/
+ private List worldHistory = new ArrayList();
+
+
+ ////////////////// the constructors ///////////////
+
+ /**
+ * Constructor that takes no arguments
+ */
+ public World()
+ {
+ // set up the world and make it visible
+ initWorld(true);
+ }
+
+ /**
+ * Constructor that takes a boolean to
+ * say if this world should be visible
+ * or not
+ * @param visibleFlag if true will be visible
+ * else if false will not be visible
+ */
+ public World(boolean visibleFlag)
+ {
+ initWorld(visibleFlag);
+ }
+
+ /**
+ * Constructor that takes a width and height for this
+ * world
+ * @param w the width for the world
+ * @param h the height for the world
+ */
+ public World(int w, int h)
+ {
+ width = w;
+ height = h;
+
+ // set up the world and make it visible
+ initWorld(true);
+ }
+
+ ///////////////// methods ///////////////////////////
+
+ /**
+ * Method to initialize the world
+ * @param visibleFlag the flag to make the world
+ * visible or not
+ */
+ private void initWorld(boolean visibleFlag)
+ {
+ // create the background picture
+ picture = new Picture(width,height);
+ this.modelChanged();
+ }
+
+ /**
+ * Method to get the graphics context for drawing on
+ * @return the graphics context of the background picture
+ */
+ public Graphics getGraphics() { return picture.getGraphics(); }
+
+ /**
+ * Method to clear the background picture
+ */
+ public void clearBackground() { picture = new Picture(width,height); }
+
+ /**
+ * Method to get the background picture
+ * @return the background picture
+ */
+ public Picture getPicture() { return picture; }
+
+ /**
+ * Method to set the background picture
+ * @param pict the background picture to use
+ */
+ public void setPicture(Picture pict) { picture = pict; }
+
+ /**
+ * Method to paint this component
+ * @param g the graphics context
+ */
+ public synchronized void paintComponent(Graphics g)
+ {
+ Turtle turtle = null;
+
+ // draw the background image
+ g.drawImage(picture.getImage(),0,0,null);
+
+ // loop drawing each turtle on the background image
+ Iterator iterator = turtleList.iterator();
+ while (iterator.hasNext())
+ {
+ turtle = (Turtle) iterator.next();
+ turtle.paintComponent(g);
+ }
+ }
+
+ /**
+ * Metod to get the last turtle in this world
+ * @return the last turtle added to this world
+ */
+ public Turtle getLastTurtle()
+ {
+ return (Turtle) turtleList.get(turtleList.size() - 1);
+ }
+
+
+ /**
+ * Method to add a model to this model displayer
+ * @param model the model object to add
+ */
+ public void addModel(Object model)
+ {
+ turtleList.add((Turtle) model);
+ }
+
+ /**
+ * Method to check if this world contains the passed
+ * turtle
+ * @return true if there else false
+ */
+ public boolean containsTurtle(Turtle turtle)
+ {
+ return (turtleList.contains(turtle));
+ }
+
+ /**
+ * Method to remove the passed object from the world
+ * @param model the model object to remove
+ */
+ public void remove(Object model)
+ {
+ turtleList.remove(model);
+ }
+
+ /**
+ * Method to get the width in pixels
+ * @return the width in pixels
+ */
+ public int getWidth() { return width; }
+
+ /**
+ * Method to get the height in pixels
+ * @return the height in pixels
+ */
+ public int getHeight() { return height; }
+
+ /**
+ * Method that allows the model to notify the display
+ */
+ public void modelChanged()
+ {
+ Picture p = new Picture(this.width, this.height);
+ this.paintComponent(p.getGraphics());
+ this.worldHistory.add(p);
+ }
+
+ /**
+ * Method to set the automatically repaint flag
+ * @param value if true will auto repaint
+ */
+ public void setAutoRepaint(boolean value) { autoRepaint = value; }
+
+ /**
+ * Method to show the frame
+ */
+ public void show()
+ {
+ this.show(false);
+ }
+
+ public void show(boolean showHistory) {
+ this.paintComponent(this.picture.getGraphics());
+ if(showHistory) {
+ try {
+ BufferedImage[] images = new BufferedImage[this.worldHistory.size()];
+ for(int i = 0; i < this.worldHistory.size(); i++) {
+ images[i] = ((Picture) this.worldHistory.get(i)).getBufferedImage();
+ }
+ Giffer.generateFromBI(images, "history.gif", 100, false);
+
+ File history = new File("history.gif");
+
+ URL url = history.toURI().toURL();
+
+ byte[] imageBytes = downloadUrl(url);
+ String result =
+ //DatatypeConverter.printBase64Binary(imageBytes);
+ //BH: using java.util.Base64 instead of javax.xml.bind.DataTypeConverter
+ Base64.getEncoder().encodeToString(imageBytes);
+
+ System.gc();
+ history.delete();
+ double rand = Math.random();
+ System.out.println("<img src=\'data:image/gif;base64," + result + "\'/>");
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ } else {
+ this.picture.show();
+ }
+ }
+
+ private byte[] downloadUrl(URL toDownload) {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+
+ try {
+ byte[] chunk = new byte[4096];
+ int bytesRead;
+ InputStream stream = toDownload.openStream();
+
+ while ((bytesRead = stream.read(chunk)) > 0) {
+ outputStream.write(chunk, 0, bytesRead);
+ }
+ //toDownload.close();
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+
+ return outputStream.toByteArray();
+ }
+
+ /**
+ * Method to get the list of turtles in the world
+ * @return a list of turtles in the world
+ */
+ public List getTurtleList()
+ { return turtleList;}
+
+ /**
+ * Method to get an iterator on the list of turtles
+ * @return an iterator for the list of turtles
+ */
+ public Iterator getTurtleIterator()
+ { return turtleList.iterator();}
+
+ /**
+ * Method that returns information about this world
+ * in the form of a string
+ * @return a string of information about this world
+ */
+ public String toString()
+ {
+ return "A " + getWidth() + " by " + getHeight() +
+ " world with " + turtleList.size() + " turtles in it.";
+ }
+
+ } // end of World class
diff --git a/tests/test_course_1/_sources/index.rst b/tests/test_course_1/_sources/index.rst
index 0c8d55dc8..73d20ff12 100644
--- a/tests/test_course_1/_sources/index.rst
+++ b/tests/test_course_1/_sources/index.rst
@@ -11,6 +11,7 @@ This book generates data for use with the test suite.
lp_demo.py
lp_demo-test.py
selectquestion
+ activecode
ActiveCode
@@ -26,27 +27,6 @@ ActiveCode
print(total)
-.. activecode:: test_activecode_2
- :nocodelens:
- :autograde: unittest
-
- Fix the following code so that it always correctly adds two numbers.
- ~~~~
- def add(a,b):
- return 4
-
- ====
- from unittest.gui import TestCaseGui
-
- class myTests(TestCaseGui):
-
- def testOne(self):
- self.assertEqual(add(2,2),4,"A feedback string when the test fails")
- self.assertAlmostEqual(add(2.0,3.0), 5.0, 5, "Try adding your parameters")
-
- myTests().main()
-
-
Clickable Area
==============
.. clickablearea:: test_clickablearea_1
diff --git a/tests/test_course_1/_sources/selectquestion.rst b/tests/test_course_1/_sources/selectquestion.rst
index 98dd729d1..9ced88f17 100644
--- a/tests/test_course_1/_sources/selectquestion.rst
+++ b/tests/test_course_1/_sources/selectquestion.rst
@@ -58,5 +58,9 @@ The following spreadsheet ``selectquestion`` components are commented out, since
:fromid: test_dnd_1
+.. selectquestion:: select_question_15
+ :fromid: test_activecode_2
+
+
.. selectquestion:: select_question_20
:fromid: test_short_answer_1
diff --git a/tests/test_runestone_components.py b/tests/test_runestone_components.py
index 4a760590c..b31bdfe3c 100644
--- a/tests/test_runestone_components.py
+++ b/tests/test_runestone_components.py
@@ -17,6 +17,7 @@
# -------------------
from polling2 import poll
import pytest
+from runestone.activecode.test import test_activecode
from runestone.clickableArea.test import test_clickableArea
from runestone.dragndrop.test import test_dragndrop
from runestone.fitb.test import test_fitb
@@ -88,9 +89,40 @@ def selenium_utils_user_2(selenium_utils_user):
return selenium_utils_user
+# A fixture for active code server-side testing.
+@pytest.fixture
+def selenium_utils_user_ac(selenium_utils_user):
+ selenium_utils_user.get_book_url("activecode.html")
+ return selenium_utils_user
+
+
# Tests
# =====
#
+# Active code
+# -----------
+def test_activecode_1(selenium_utils_user_ac, runestone_db):
+ db = runestone_db
+
+ def ac_check_fields(index, div_id):
+ row = get_answer(db, db.code.acid == div_id, index + 1)[index]
+ assert row.timestamp - datetime.datetime.now() < datetime.timedelta(seconds=5)
+ assert row.acid == div_id
+ assert row.sid == selenium_utils_user_ac.user.username
+ assert row.course_id == selenium_utils_user_ac.user.course.course_id
+ return row
+
+ test_activecode.test_history(selenium_utils_user_ac)
+ row = ac_check_fields(0, "test_activecode_2")
+ assert row.emessage == "success"
+ assert row.code == "print('Goodbye')"
+ assert row.grade == None
+ assert row.comment == None
+ assert row.language == "python"
+
+ # TODO: There are a lot more activecode tests that could be easily ported!
+
+
# ClickableArea
# -------------
def test_clickable_area_1(selenium_utils_user_1, runestone_db):
@@ -356,6 +388,10 @@ def test_selectquestion_7(selenium_utils_user_2, runestone_db):
test_dnd_1(selenium_utils_user_2, runestone_db)
+def test_selectquestion_8(selenium_utils_user_2, runestone_db):
+ test_activecode_1(selenium_utils_user_2, runestone_db)
+
+
def test_selectquestion_20(selenium_utils_user_2, runestone_db):
test_short_answer_1(selenium_utils_user_2, runestone_db)