Assignment 1: Shapes

In this assignment, you will build a Haskell program that uses the CodeWorld API to draw colourful shapes on the screen, including lines, polygons, rectangles, circles, and ellipses.

This assignment is worth 10% of your final grade.


Indicative marks and feedback for Part A will be returned at the end of week 5.

Required Knowledge

If you have finished the week 3 lab, you should be able to complete Part A.

If you have finished the week 4 lab, you should be able to complete the majority of the assignment. Some parts require recursion over lists, which is covered in the week 5 lab.

Overview of Tasks

You will be required to complete different tasks depending on your enrolled course:

  COMP1100 COMP1130
Task 1: Helper Functions 20 marks 10 Marks
Task 2: Rendering Shapes 35 marks 30 Marks
Task 3: Handling Events 30 marks 25 Marks
1130 Extensions   30 Marks
Technical Report 15 marks 25 Marks

Part A of the assignment requires you to complete Task 1. Part B of the assignment requires you to complete all assigned tasks. As you complete each task (or even each function within a task), you should commit and push your work with a sensible commit message.

The purpose of Part A is to give you an opportunity to collect feedback on your code and your progress in the course, and for us to give you an indicative mark for your work so far. This will be returned to you before the census date. Part A will be re-marked alongside your Part B submission, giving you a final mark for the assignment.

Getting Started

Fork the assignment repository and create a project for it in IntelliJ IDEA, following the same steps as in Lab 2. The assignment repository is at https://gitlab.cecs.anu.edu.au/comp1100/comp1100-assignment1.

Overview of the Repository

Most of your code will be written to Haskell files in the src/ directory. We are using the model-view-controller pattern to structure this assignment. Each file is called a module, and we use modules to group related code together and separate unrelated code.

Model.hs

The model is a data type that describes the state of the running program. The program will move to new states (new values of type Model) in response to user actions, as defined by the controller.

View.hs

The view turns the model into something that can be shown on the screen; in this project, that is the CodeWorld Picture type.

Controller.hs

The controller considers user input (and other events), along with the current model, and uses that to decide what the new model should be.

Other Files

  • tests/ShapesTest.hs contains some unit tests - simple checks that verify small parts of your program are working correctly. You are not required to write tests for this assignment, but you might find it useful to do so.

  • tests/Testing.hs is a small testing library used by tests/ShapesTest.hs. You are not required to understand it for this assignment.

  • app/Main.hs ties your functions together into the final program that runs. You are not required to understand it.

  • comp1100-assignment1.cabal tells the cabal build tool how to build your assignment. You are not required to understand this file, and we will discuss how to use cabal below.

  • Setup.hs tells cabal that this is a normal package with no unusual build steps. Some complex packages (that we won’t see in this course) need to put more complex code here. You are not required to understand it.

Overview of Cabal

cabal is the build tool for Haskell programs and libraries. It provides several useful commands:

  • cabal build: Compile your assignment.

  • cabal run shapes: Build your assignment (if necessary), and run the shapes program.

  • cabal repl comp1100-assignment1: Run the GHCi interpreter over your project. This gives you the same ghci environment you use in labs, but with the assignment code loaded. (Aside: REPL is the name for interactive sessions like GHCi - it stands for read-eval-print loop. Many modern languages have REPLs.)

  • cabal test: Build and run the tests. Tests will abort on the first failure, or the first call to a function that is still undefined.

You should execute these cabal commands in the top-level directory of your project: ~/comp1100/assignment1 (i.e., the directory you are in when you launch the IntelliJ Terminal tool for your project).

Overview of the Program

You use a web browser to interact with the shapes program that you launched with cabal run shapes. Once you have completed the assignment, it will respond to the following actions:

Action Effect
Esc (key) Clear the canvas
M (key) Display a mystery image
C (key) Cycle colour (of shape to draw)
T (key) Cycle tool (type of shape to draw)
Backspace/Delete(key) Remove the last added shape
D (key) Print the current Model to the terminal (useful for testing)
Click-drag-release (mouse) When not drawing polygons, draw a shape between the click-point and release-point
Click (mouse) When drawing polygons, add a point to the polygon
Spacebar (key) Finish drawing a polygon, adding it to the canvas.

Task 1: Helper Functions (COMP1100: 20 marks; COMP1130: 10 marks)

The easiest way to solve a large problem is often to break it apart into smaller, easier problems. Programming is the same. In this task you will write some helper functions that will make future tasks easier. You can test your implementations by running cabal test.

The functions you need to write for this task are:

  • toolLabel in src/View.hs. This function should return instructions for the user on how to use each Tool, according to the following table:
Tool Label
LineTool "Line... click-drag-release"
PolygonTool "Polygon... click 3 or more times then spacebar"
RectangleTool "Rectangle... click-drag-release"
CircleTool "Circle... click-drag-release"
EllipseTool "Ellipse... click-drag-release"

Note: At the time this assignment is released, the course will have only briefly covered lists. You do not need to manipulate lists to write toolLabel; you can use a blank pattern (_) to ignore them.

  • nextColour in src/Controller.hs. This function should return the next colour in our set of ColourNames:
Argument Result
Black Red
Red Orange
Orange Yellow
Yellow Green
Green Blue
Blue Violet
Violet Black
  • nextTool in src/Controller.hs. This function implements tool-switching, but should not change Toolif the user is halfway through an operation:

    • If the tool is not holding a point (that is, a non-PolygonTool tool holding Nothing or a PolygonTool holding the empty list []), select the next tool in the following sequence: Line ->Polygon -> Rectangle -> Circle -> Ellipse -> Line -> ....

    • If there is a Point stored in the given tool (because it’s holding a Just value or the list in PolygonTool is non-empty), return the argument unchanged.

    • If this is unclear, study the nextToolTests in test/ShapesTest.hs.

Note: At the time this assignment is released, the course will have only briefly covered lists. You can write the PolygonTool case for nextTool without using list recursion. Use [] to match an empty list. In a subsequent case, give the entire list a name like points to match any nonempty list. Alternatively, you might use the Prelude function null, which returns True if a list is empty and False if it is not.


Part A ends here.


Submitting Part A

Yo