Chp 10 Classes

Instructions

To begin, fork this project. Notice it's structure. main.py contains the unit test, and each class described below has its own file. You won't write code into main.py; instead you'll write into the class files. If the unit test cannot create the objects it wishes to create, or it does not find the methods it wishes to call, it will raise an exception and quit. In this case no report will be generated.

Before the actual unit test are a number of lines of code that have been commented out. These will provide feedback as you work towards the point where the unit test will actually generate a report.

I won't unit test the Duck and Army classes. Thus your grade won't be determined by the unit test alone. But I will play a bit with your Duck and Army classes and give them full credit if they seem ballpark right. Let's say five points each.

Domestic Duck Class

Create a DomesticDuck class. The constructor for that class should set two attributes: breed and sex, both given as strings. The class should have these methods: the getBreed method, the getSex method, the says method, the walk method, the fly method and the court method. The last of these should take as argument a second duck that is courted by the duck on which the method is called. Also override the __repr__ method so that when we print a particular duck, we get a sentence that reports the breed and sex. (If you forget what that means, look back over the Human class we created.)

Add these lines to main:

Mallory = duck.DomesticDuck('Abacot Ranger', 'female')

Millard = duck.DomesticDuck('Buff Duck', 'male')

print(Mallory)

print(Millard)

print(Mallory.getBreed(), Mallory.getSex())

print(Mallory.says())

print(Mallory.walk())

print(Mallory.fly())

print(Mallory.court(Millard))

print(Millard.getBreed(), Millard.getSex())

print(Millard.says())

print(Millard.walk())

print(Millard.fly())

print(Millard.court(Mallory))

The output should be (something very much like):

A female duck of breed Abacot Ranger.

A male duck of breed Buff Duck.

Abacot Ranger female

A quack with a hint of sarcasm.

Waddle with a bit of sway.

I don't take orders!

Ducklings on the way!

Buff Duck male

A slightly befuddled quack.

Waddle with a bit of swagger.

Too lazy to get feathered butt off couch.

Rebuffed!

Feel free to insert your own jokes (but do keep it clean).

Army Class

Create an Army class. The constructor for that class should set nine attributes: number of infantry (an int), number of archers (an int), number of cavalry (an int), food reserves (an int), stamina (a float between 0 and 1), army name (a str), army color (a str), a bool that answers the question, 'Does this army have a dragon?' and finally a bool that answers the question 'Has this army been defeated?' (You should be able to infer the intended names of these attributes from the code below.) The class should have these methods: makeCamp, march, pillage and attack. The makeCamp method should accept a positive integer that represents the number of days to make camp; it should increase stamina and decrease food reserves. The march method should accept a positive integer that represents the number of days to march; it should decrease both stamina and food reserves. The pillage method should accept a positive integer that represents the number of villages to pillage; it should increase food reserves and decrease stamina. A call to the attack method should specify a second army that will fight the army on which the method is called. I'll let you decide on a formula to determine which army wins. Also override the __repr__ method so that when we print an army, we get a clear, nicely formatted paragraph that gives its attributes.

Add these lines to main:

Targaryen = army.Army(1000, 100, 200, 10000, 0.8, 'Targaryen', 'silver', True, False)

Stark = army.Army(2000, 200, 300, 8000, 0.7, 'Stark', 'red', False, False)

print(Targaryen.name, Targaryen.color)

print(Targaryen.numInf, Targaryen.numArch, Targaryen.numCav)

print(Targaryen.food, Targaryen.stamina)

print(Targaryen.hasDragon, Targaryen.isDefeated)

print()

print(Stark.name, Stark.color)

print(Stark.numInf, Stark.numArch, Stark.numCav)

print(Stark.food, Stark.stamina)

print(Stark.hasDragon, Stark.isDefeated)

print()

Targaryen.makeCamp(2)

print(Targaryen.food, Targaryen.stamina)

Stark.march(12)

print(Stark.food, Stark.stamina)

Stark.pillage(3)

print(Stark.food, Stark.stamina)

Targaryen.attack(Stark)

print(Targaryen.isDefeated, Stark.isDefeated)

The output should look like this (though some details might differ):

Targaryen silver

1000 100 200

10000 0.8

True False


Stark red

2000 200 300

8000 0.7

False False


9000 0.9

6000 0.6

11000 0.5

False True

Point Class

Create a Point class. The constructor for that class should set two attributes: the x-coordinate of the point and the y-coordinate of the point. Call these xCor and yCor. The class should have these methods: getX, getY, distance, slope, and direction

Method directions:

Also override the __repr__ method so that we get the usual representation of a point . Like this: (-12, 15)

Add these lines to main:

p1 = point.Point(1, 1)

p2 = point.Point(4, 0)

p3 = point.Point(2, 2)

print(p1, p2, p3)

print(p2.getX(), p3.getY())

print(p1.distance(p2))

print(p1.slope(p3))

print(p2.direction(p3))

The output should look (something very) like:

(1, 1) (4, 0) (2, 2)

4 2

3.16227766017

1.0

-0.785398163397

Line Class

Create a Line class. The constructor should set three attributes: slope, yInt and equation. The first two of these are floats. The third is a function. What function? A function that takes an x and returns the y such that (x, y) is a point on the line. How do you create such a function? Look back to our work with higher order functions.

Note that the  equation will not be sent to the class constructor. For instance, in the line of code (see below) L1 = line.Line(1, 0), we send only the slope 1 and the y-intercept 0. Where does the equation come from then? You create it in the constructor! That's perfectly cool. You can create a value in the constructor and make it the initial value of some attribute.

The class should have these methods: isParallel, isPerp, intAt, and getY.

Method directions:

Also override the __repr__ method so that we get the usual representation of a line. Like this: y = -12x + 15.

Add these lines to main:

L1 = line.Line(1, 0)

L2 = line.Line(-1, 0)

L3 = line.Line(3, -9)

L4 = line.Line(3, 6)

print(L1)

print(L3)

print(L1.getY(2), L2.getY(-3), L3.getY(4), L4.getY(-5))

print(L1.isParallel(L2), L1.isPerp(L2))

print(L3.isParallel(L4), L3.isPerp(L4))

L5 = line.Line(4, 8)

L6 = line.Line(-4, -4)

print(L5.intAt(L6))

The output should be:

y = 1x + 0

y = 3x + -9

2 3 3 -9

False True

True False

(-1.5, 2.0)

Triangle Class

Create a Triangle class. The constructor for that class should set three attributes: location of first vertex, location of second vertex and location of final vertex. Call them v1, v2 and v3. Those locations will be given as points. Yes, I mean points as defined in the Point class. Thus to create a triangle, you first create three points; and then you make those three points attributes of a triangle. The class should have these methods: getVertices, perimeter, area, isCongruent, slide and contains

Method directions:

The class should also override the __repr__ method so that when we print a triangle, we get a tuple of its vertices.

A word of advice: don't test two floats for equality. Given that Python approximates when it does its computations, it might be that two floats which should be equal come out as not equal if we test for equality. So then, if our two floats are f1 and f2, don’t do this:

if f1 == f2:

Do this instead:

if abs(f1 - f2) < 0.000001:

This means that we will count f1 and f2 as equal if they are close enough.

Add these lines to main:

T1 = triangle.Triangle(p1, p2, p3)

print(T1)

print(T1.perimeter())

print(T1. area())

p4 = point.Point(3, 3)

p5 = point.Point(6, 2)

p6 = point.Point(4, 4)

p7 = point.Point(1, 3)

p8 = point.Point(1, 7)

p9 = point.Point(5, 11)

T2 = triangle.Triangle(p4, p5, p6)

T3 = triangle.Triangle(p7, p8, p9)

print(T1.isCongruent(T2))

print(T1.isCongruent(T3))

p10 = point.Point(3, 2)

print(T1.contains(p10))

p11 = point.Point(2, 1)

print(T1.contains(p11))

p12 = point.Point(-3, 4)

p13 = point.Point(6, -9)

p14 = point.Point(0, 12)

T4 = triangle.Triangle(p12, p13, p14)

T5 = T4.slide(2, -1)

print(T5)

My output was:

(1, 1) (4, 0) (2, 2)

7.404918347287666

2.0000000000000013

True

False

False

True

(-1, 3) (8, -10) (2, 11)