diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab05/.classpath b/completedwork/core_programming/02_classbased_design/Workspace/Lab05/.classpath
new file mode 100644
index 0000000..e446dbd
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab05/.classpath
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab05/.project b/completedwork/core_programming/02_classbased_design/Workspace/Lab05/.project
new file mode 100644
index 0000000..7b26ae4
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab05/.project
@@ -0,0 +1,17 @@
+
+
+ Lab05
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab05/.settings/org.eclipse.core.resources.prefs b/completedwork/core_programming/02_classbased_design/Workspace/Lab05/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..99f26c0
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab05/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/=UTF-8
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab05/.settings/org.eclipse.jdt.core.prefs b/completedwork/core_programming/02_classbased_design/Workspace/Lab05/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..e71285a
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab05/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
+org.eclipse.jdt.core.compiler.release=enabled
+org.eclipse.jdt.core.compiler.source=11
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab05/src/SimpleGame.java b/completedwork/core_programming/02_classbased_design/Workspace/Lab05/src/SimpleGame.java
new file mode 100644
index 0000000..c593613
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab05/src/SimpleGame.java
@@ -0,0 +1,329 @@
+import tester.*; // The tester library
+import javalib.worldimages.*; // images, like RectangleImage or OverlayImages
+import javalib.funworld.*; // the abstract World class and the big-bang library
+import java.awt.Color; // general colors (as triples of red,green,blue values)
+// and predefined colors (Color.RED, Color.GRAY, etc.)
+import java.util.Random;
+
+class MyPosn extends Posn {
+ // standard constructor
+ MyPosn(int x, int y) {
+ super(x, y);
+ }
+ // constructor to convert from a Posn to a MyPosn
+ MyPosn(Posn p) {
+ this(p.x, p.y);
+ }
+
+ MyPosn add(MyPosn that) {
+ // return a Posn with the x and y values of this and that Posn added together
+ return new MyPosn(this.x + that.x, this.y + that.y);
+ }
+ boolean isOffscreen(int width, int height) {
+ // returns true if this Posn is outside the provided screen dimensions
+ return this.x <= 0 ||
+ this.x >= width ||
+ this.y <= 0 ||
+ this.y >= height;
+ }
+ int getX() {
+ return this.x;
+ }
+ int getY() {
+ return this.y;
+ }
+}
+
+class Circle {
+ int radius;
+ MyPosn position; // in pixels
+ MyPosn velocity; // in pixels/tick
+ String fill;
+ Color color;
+ String DEFAULTFILL = "solid";
+ Color DEFAULTCOLOR = Color.BLACK;
+
+ Circle(int radius, MyPosn position, MyPosn velocity, String fill, Color color) {
+ this.radius = radius;
+ this.position = position;
+ this.velocity = velocity;
+ this.fill = fill;
+ this.color = color;
+ }
+ Circle(int radius, MyPosn position, MyPosn velocity) {
+ this.radius = radius;
+ this.position = position;
+ this.velocity = velocity;
+ this.fill = this.DEFAULTFILL;
+ this.color = this.DEFAULTCOLOR;
+ }
+
+ Circle move() {
+ // returns a circle after being moved one tick
+ return new Circle(this.radius, this.position.add(velocity), velocity);
+ }
+ boolean isOffscreen(int width, int height) {
+ // returns true if this is outside the provided screen dimensions
+ return this.position.isOffscreen(width, height);
+ }
+ WorldImage draw() {
+ // returns an CircleImage of this
+ return new CircleImage(this.radius, this.fill, this.color);
+ }
+ WorldScene place(WorldScene scene) {
+ // returns a worldscene with a drawing of the circle at the appropriate position.
+ return scene.placeImageXY(this.draw(), this.position.getX(), this.position.getY());
+ }
+}
+
+interface ILoCircle {
+ // returns list of moved circles
+ ILoCircle moveAll();
+ // returns a count of all offscreen circles
+ int countOffscreen(int width, int height);
+ int countOffscreenHelper(int width, int height, int cnt);
+ // returns list of circles with offscreen items removed
+ ILoCircle removeOffscreen(int width, int height);
+ // returns a scene with all circles drawn and placed
+ WorldScene placeAll(WorldScene scene);
+ // returns true if this list is empty
+ boolean isEmpty();
+}
+
+class MtLoCircle implements ILoCircle {
+ MtLoCircle() {}
+ public ILoCircle moveAll() {
+ return this;
+ }
+ public int countOffscreen(int width, int height) {
+ return 0;
+ }
+ public int countOffscreenHelper(int width, int height, int cnt) {
+ return cnt;
+ }
+ public ILoCircle removeOffscreen(int width, int height) {
+ return this;
+ }
+ public WorldScene placeAll(WorldScene scene) {
+ return scene;
+ }
+ public boolean isEmpty() {
+ return true;
+ }
+}
+
+class ConsLoCircle implements ILoCircle {
+ Circle first;
+ ILoCircle rest;
+ ConsLoCircle(Circle first, ILoCircle rest) {
+ this.first = first;
+ this.rest = rest;
+ }
+
+ public ILoCircle moveAll() {
+ return new ConsLoCircle(this.first.move(), this.rest.moveAll());
+ }
+ public int countOffscreen(int width, int height) {
+ return this.countOffscreenHelper(width, height, 0);
+ }
+ public int countOffscreenHelper(int width, int height, int cnt) {
+ if (this.first.isOffscreen(width, height)) {
+ return this.rest.countOffscreenHelper(width, height, cnt + 1);
+ } else {
+ return this.rest.countOffscreenHelper(width, height, cnt);
+ }
+ }
+ public ILoCircle removeOffscreen(int width, int height) {
+ if (this.first.isOffscreen(width, height)) {
+ return this.rest.removeOffscreen(width, height);
+ } else {
+ return new ConsLoCircle(this.first, this.rest.removeOffscreen(width, height));
+ }
+ }
+ public WorldScene placeAll(WorldScene scene) {
+ return this.rest.placeAll(this.first.place(scene));
+ }
+ public boolean isEmpty() {
+ return false;
+ }
+}
+
+class MyGame extends World {
+ double TICKRATE = 1.0 / 28.0;
+ int VELOMAG = 10;
+ int width;
+ int height;
+ int circlesRemoved;
+ int gameOver;
+ ILoCircle loCircles;
+ Random rand;
+ MyGame(int width, int height, int circlesRemoved, int gameOver, ILoCircle loCircles,
+ Random rand) {
+ this.width = width;
+ this.height = height;
+ this.circlesRemoved = circlesRemoved;
+ this.gameOver = gameOver;
+ this.loCircles = loCircles;
+ this.rand = rand;
+ }
+ MyGame(int gameOver, int seed) {
+ this.width = 500;
+ this.height = 300;
+ this.circlesRemoved = 0;
+ this.gameOver = gameOver;
+ this.loCircles = new MtLoCircle();
+ this.rand = new Random(seed);
+ }
+ MyGame(int gameOver) {
+ this.width = 500;
+ this.height = 300;
+ this.circlesRemoved = 0;
+ this.gameOver = gameOver;
+ this.loCircles = new MtLoCircle();
+ this.rand = new Random();
+ }
+ public boolean start() {
+ return this.bigBang(this.width, this.height, this.TICKRATE);
+ }
+ @Override
+ public WorldScene makeScene() {
+ WorldScene scene = new WorldScene(this.width, this.height);
+ return this.loCircles.placeAll(scene);
+ }
+ @Override
+ public MyGame onTick() {
+ return this.moveCircles().removeCircles();
+ }
+ public MyGame removeCircles() {
+ return new MyGame(this.width,
+ this.height,
+ this.circlesRemoved + this.loCircles.countOffscreen(this.width, this.height),
+ this.gameOver,
+ this.loCircles.removeOffscreen(this.width, this.height),
+ this.rand);
+ }
+ public MyGame moveCircles() {
+ return new MyGame(this.width,
+ this.height,
+ this.circlesRemoved,
+ this.gameOver,
+ this.loCircles.moveAll(),
+ this.rand);
+ }
+ @Override
+ public MyGame onMouseClicked(Posn pos) {
+ return new MyGame(this.width,
+ this.height,
+ this.circlesRemoved,
+ this.gameOver,
+ new ConsLoCircle(new Circle(10, new MyPosn(pos), this.randomVelo()),
+ this.loCircles),
+ this.rand);
+ }
+ public MyPosn randomVelo() {
+ switch (this.rand.nextInt(4)) {
+ case 0:
+ return new MyPosn(this.VELOMAG, 0);
+ case 1:
+ return new MyPosn(0, this.VELOMAG);
+ case 2:
+ return new MyPosn(this.VELOMAG * -1, 0);
+ case 3:
+ return new MyPosn(0, this.VELOMAG * -1);
+ default:
+ return new MyPosn(this.VELOMAG, 0); // should never happen
+ }
+
+ }
+ @Override
+ public WorldEnd worldEnds() {
+ if (this.gameOver <= this.circlesRemoved) {
+ return new WorldEnd(true, this.makeEndScene());
+ } else {
+ return new WorldEnd(false, this.makeEndScene());
+ }
+ }
+ public WorldScene makeEndScene() {
+ WorldScene endScene = new WorldScene(this.width, this.height);
+ return endScene.placeImageXY(new TextImage("Game Over", Color.red), 250, 250);
+
+ }
+}
+
+class Examples {
+ MyPosn pn0 = new MyPosn(0, 0);
+ MyPosn pn1 = new MyPosn(100, 100);
+ MyPosn pn2 = new MyPosn(200, 200);
+ MyPosn pn3_offscreen = new MyPosn(-100, 200);
+ MyPosn pn4_offscreen = new MyPosn(200, -200);
+ MyPosn pn5_offscreen = new MyPosn(600, 200);
+ MyPosn pn6_offscreen = new MyPosn(200, 500);
+
+ boolean testAdd(Tester t) {
+ return t.checkExpect(pn0.add(pn0), pn0) &&
+ t.checkExpect(pn1.add(pn0), pn1) &&
+ t.checkExpect(pn1.add(pn1), pn2) &&
+ t.checkExpect(pn1.add(pn2), new MyPosn(300, 300));
+ }
+ boolean testPosnOffscreen(Tester t) {
+ return t.checkExpect(pn1.isOffscreen(500, 300), false) &&
+ t.checkExpect(pn3_offscreen.isOffscreen(500, 300), true) &&
+ t.checkExpect(pn4_offscreen.isOffscreen(500, 300), true) &&
+ t.checkExpect(pn5_offscreen.isOffscreen(500, 300), true) &&
+ t.checkExpect(pn6_offscreen.isOffscreen(500, 300), true);
+ }
+
+ Circle c1 = new Circle(1, pn1, pn0);
+ Circle c2 = new Circle(1, pn1, pn1);
+ Circle c3 = new Circle(1, pn2, pn1);
+ Circle c4_offscreen = new Circle(1, pn4_offscreen, pn1);
+ Circle c5_offscreen = new Circle(1, pn5_offscreen, pn1);
+ WorldScene scene0 = new WorldScene(500, 300);
+ boolean testMove(Tester t) {
+ return t.checkExpect(c1.move(), c1) &&
+ t.checkExpect(c2.move(), c3);
+ }
+ boolean testIsOffscreen(Tester t) {
+ return t.checkExpect(c1.isOffscreen(500, 300), false) &&
+ t.checkExpect(c2.isOffscreen(500, 300), false) &&
+ t.checkExpect(c3.isOffscreen(500, 300), false) &&
+ t.checkExpect(c4_offscreen.isOffscreen(500, 300), true) &&
+ t.checkExpect(c5_offscreen.isOffscreen(500, 300), true);
+ }
+ boolean testDraw(Tester t) {
+ return t.checkExpect(c1.draw(), new CircleImage(1, OutlineMode.SOLID, Color.BLACK));
+ }
+ boolean testPlace(Tester t) {
+ return t.checkExpect(c1.place(scene0),
+ scene0.placeImageXY(new CircleImage(1, OutlineMode.SOLID, Color.BLACK), 100, 100));
+ }
+
+ ILoCircle loc0 = new MtLoCircle();
+ ILoCircle loc1 = new ConsLoCircle(c1, loc0);
+ ILoCircle loc2 = new ConsLoCircle(c2, loc1);
+ ILoCircle loc3 = new ConsLoCircle(c3, loc1);
+ ILoCircle loc2_moved = new ConsLoCircle(c1, new ConsLoCircle(c3, loc0));
+ ILoCircle loc2_withOffscreen = new ConsLoCircle(c4_offscreen,
+ new ConsLoCircle(c5_offscreen, loc2));
+ WorldScene scene1 = scene0.placeImageXY(c1.draw(), 100, 100);
+ WorldScene scene2 = scene1.placeImageXY(c3.draw(), 200, 200);
+ boolean testMoveAll(Tester t) {
+ return t.checkExpect(this.loc0.moveAll(), this.loc0) &&
+ t.checkExpect(this.loc1.moveAll(), this.loc1) &&
+ t.checkExpect(this.loc2.moveAll(), this.loc2_moved);
+ }
+ boolean testRemoveAll(Tester t) {
+ return t.checkExpect(this.loc0.removeOffscreen(500, 300), this.loc0) &&
+ t.checkExpect(this.loc2.removeOffscreen(500, 300), this.loc2) &&
+ t.checkExpect(this.loc2_withOffscreen.removeOffscreen(500, 300), this.loc2);
+ }
+ boolean testPlaceAll(Tester t) {
+ return t.checkExpect(this.loc0.placeAll(scene0), scene0) &&
+ t.checkExpect(this.loc1.placeAll(scene0), scene1) &&
+ t.checkExpect(this.loc3.placeAll(scene0), scene2);
+ }
+ boolean testBigBang(Tester t) {
+ MyGame world = new MyGame(10);
+ return world.start();
+ }
+}
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/.classpath b/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/.classpath
new file mode 100644
index 0000000..e446dbd
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/.classpath
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/.project b/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/.project
new file mode 100644
index 0000000..250ab10
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/.project
@@ -0,0 +1,17 @@
+
+
+ Lab06_VisitorsAndGenerics
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/.settings/org.eclipse.core.resources.prefs b/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..99f26c0
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/=UTF-8
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/.settings/org.eclipse.jdt.core.prefs b/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..e71285a
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
+org.eclipse.jdt.core.compiler.release=enabled
+org.eclipse.jdt.core.compiler.source=11
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/src/Examples.java b/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/src/Examples.java
new file mode 100644
index 0000000..259dce2
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/src/Examples.java
@@ -0,0 +1,63 @@
+import tester.Tester;
+
+class Examples {
+ IList list_int = new ConsList(1,
+ new ConsList(2, new ConsList(3, new MtList())));
+
+ boolean testFoldr(Tester t) {
+ return t.checkExpect(this.list_int.foldr(new SumInteger(), 0), 6);
+ }
+
+ IList list_json1 = new ConsList(new JSONBlank(),
+ new ConsList(new JSONNumber(1), new ConsList(new JSONBool(false),
+ new ConsList(new JSONString("A"), new MtList()))));
+ IList list_j2n1 = new ConsList(0,
+ new ConsList(1, new ConsList(0,
+ new ConsList(1, new MtList()))));
+ JSONList jList = new JSONList(list_json1);
+ IList list_json2 = new ConsList(jList, new MtList());
+ IList list_j2n2 = new ConsList(2, new MtList());
+ IList list_json3 = new ConsList(new JSONBlank(),
+ new ConsList(new JSONNumber(-1), new ConsList(new JSONBool(false),
+ new ConsList(new JSONString(""), new MtList()))));
+
+ boolean testJSONMap(Tester t) {
+ return t.checkExpect(this.list_json1.map(new JSONToNumber()), list_j2n1) &&
+ t.checkExpect(this.list_json2.map(new JSONToNumber()), list_j2n2);
+ }
+
+ boolean testFilter(Tester t) {
+ return t.checkExpect(this.list_j2n1.filter(new IsIntPositive()),
+ new ConsList(1, new ConsList(1, new MtList())));
+ }
+ boolean testFindSolution(Tester t) {
+ return t.checkExpect(
+ this.list_json1.findSolutionOrElse(new JSONToNumber(), new IsIntPositive(), 0), 1) &&
+ t.checkExpect(
+ this.list_json3.findSolutionOrElse(new JSONToNumber(), new IsIntPositive(), 0), 0);
+ }
+
+ Pair p0 = new Pair("A", new JSONBlank());
+ Pair p1 = new Pair("B", new JSONNumber(1));
+ Pair p2 = new Pair("C", new JSONBool(false));
+ Pair p3 = new Pair("D", new JSONString("D"));
+
+ JSONObject jObj1 = new JSONObject(new ConsList>(p0,
+ new ConsList>(p1,
+ new ConsList>(p2,
+ new ConsList>(p3,
+ new MtList>())))));
+
+ IList list_json4 = new ConsList(jObj1, new MtList());
+
+ boolean testJObjVisitor(Tester t) {
+ return t.checkExpect(this.list_json4.map(new JSONToNumber()), this.list_j2n2);
+ }
+
+ boolean testJsonFind(Tester t) {
+ return t.checkExpect(this.list_json4.map(new JSONFind("B")),
+ new ConsList(new JSONNumber(1), new MtList())) &&
+ t.checkExpect(this.list_json4.map(new JSONFind("E")),
+ new ConsList(new JSONBlank(), new MtList()));
+ }
+}
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/src/Generics.java b/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/src/Generics.java
new file mode 100644
index 0000000..1fba079
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/src/Generics.java
@@ -0,0 +1,82 @@
+// Represents functions of signature A -> R, for some argument type A and
+// result type R
+interface IFunc {
+ R apply(A input);
+}
+
+interface IFunc2 {
+ R apply(A1 arg1, A2 arg2);
+}
+
+interface IPred {
+ boolean apply(T t);
+}
+
+// generic list
+interface IList {
+ T getFirst(T t);
+ IList filter(IPred pred);
+ // map over a list, and produce a new list with a (possibly different)
+ // element type
+ IList map(IFunc f);
+ U foldr(IFunc2 func, U base);
+ U findSolutionOrElse(IFunc convert, IPred pred, U backup);
+ T getFirstOrBackup(T backup);
+}
+
+// empty generic list
+class MtList implements IList {
+ public T getFirst(T t) {
+ return t;
+ }
+ public IList filter(IPred pred) {
+ return this;
+ }
+ public IList map(IFunc f) {
+ return new MtList();
+ }
+ public U foldr(IFunc2 func, U base) {
+ return base;
+ }
+ public U findSolutionOrElse(IFunc convert, IPred pred, U backup) {
+ return backup;
+ }
+ public T getFirstOrBackup(T backup) {
+ return backup;
+ }
+}
+
+// non-empty generic list
+class ConsList implements IList {
+ T first;
+ IList rest;
+
+ ConsList(T first, IList rest) {
+ this.first = first;
+ this.rest = rest;
+ }
+ public T getFirst(T t) {
+ return this.first;
+ }
+ public IList filter(IPred pred) {
+ if (pred.apply(this.first)) {
+ return new ConsList(this.first, this.rest.filter(pred));
+ } else {
+ return this.rest.filter(pred);
+ }
+ }
+ public IList map(IFunc f) {
+ return new ConsList(f.apply(this.first), this.rest.map(f));
+ }
+ public U foldr(IFunc2 func, U base) {
+ return func.apply(this.first, this.rest.foldr(func, base));
+ }
+ public U findSolutionOrElse(IFunc convert, IPred pred, U backup) {
+ return this.map(convert) // List -> List
+ .filter(pred) // List -> List (filtered where pred == true)
+ .getFirstOrBackup(backup); // List -> U (first value of list where pred == true)
+ }
+ public T getFirstOrBackup(T backup) {
+ return this.first;
+ }
+}
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/src/JSON.java b/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/src/JSON.java
new file mode 100644
index 0000000..0ff0aa0
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/src/JSON.java
@@ -0,0 +1,86 @@
+// a json value
+interface JSON {
+ R accept(IJsonVisitor visitor);
+}
+
+// no value
+class JSONBlank implements JSON {
+ public R accept(IJsonVisitor visitor) {
+ return visitor.visitBlank(this);
+ }
+}
+
+// a number
+class JSONNumber implements JSON {
+ int number;
+
+ JSONNumber(int number) {
+ this.number = number;
+ }
+ public R accept(IJsonVisitor visitor) {
+ return visitor.visitNumber(this);
+ }
+}
+
+// a boolean
+class JSONBool implements JSON {
+ boolean bool;
+
+ JSONBool(boolean bool) {
+ this.bool = bool;
+ }
+ public R accept(IJsonVisitor visitor) {
+ return visitor.visitBool(this);
+ }
+}
+
+// a string
+class JSONString implements JSON {
+ String str;
+
+ JSONString(String str) {
+ this.str = str;
+ }
+ public R accept(IJsonVisitor visitor) {
+ return visitor.visitString(this);
+ }
+}
+
+//a list of JSON values
+class JSONList implements JSON {
+ IList values;
+
+ JSONList(IList values) {
+ this.values = values;
+ }
+ public R accept(IJsonVisitor visitor) {
+ return visitor.visitList(this);
+ }
+}
+
+//a list of JSON pairs
+class JSONObject implements JSON {
+ IList> pairs;
+
+ JSONObject(IList> pairs) {
+ this.pairs = pairs;
+ }
+ public R accept(IJsonVisitor visitor) {
+ return visitor.visitObject(this);
+ }
+
+ // public String find(IPairsVisitor visitor) {
+ // return
+ // }
+}
+
+//generic pairs
+class Pair {
+ X x;
+ Y y;
+
+ Pair(X x, Y y) {
+ this.x = x;
+ this.y = y;
+ }
+}
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/src/Visitor.java b/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/src/Visitor.java
new file mode 100644
index 0000000..6ab4877
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab06_VisitorsAndGenerics/src/Visitor.java
@@ -0,0 +1,121 @@
+class IsIntPositive implements IPred {
+ public boolean apply(Integer i) {
+ return i > 0;
+ }
+}
+
+class FindKey implements IPred> {
+ String find;
+ FindKey(String find) {
+ this.find = find;
+ }
+ public boolean apply(Pair p) {
+ return find.compareTo(p.x) == 0;
+ }
+}
+
+class MatchString implements IPred {
+ String find;
+ MatchString(String find) {
+ this.find = find;
+ }
+ public boolean apply(String str) {
+ return find.compareTo(str) == 0;
+ }
+}
+
+class PairsToKey implements IFunc, String> {
+ public String apply(Pair p) {
+ return p.x;
+ }
+}
+
+class PairsToJSON implements IFunc, JSON> {
+ public JSON apply(Pair p) {
+ return p.y;
+ }
+}
+
+class SumInteger implements IFunc2 {
+ public Integer apply(Integer i, Integer sum) {
+ return i + sum;
+ }
+}
+
+interface IJsonVisitor extends IFunc {
+ R visitBlank(JSONBlank blank);
+ R visitNumber(JSONNumber number);
+ R visitBool(JSONBool bool);
+ R visitString(JSONString str);
+ R visitList(JSONList list);
+ R visitObject(JSONObject obj);
+}
+
+class JSONToNumber implements IJsonVisitor {
+ public Integer apply(JSON j) {
+ return j.accept(this);
+ }
+ public Integer visitBlank(JSONBlank blank) {
+ return 0;
+ }
+ public Integer visitNumber(JSONNumber number) {
+ return number.number;
+ }
+ public Integer visitBool(JSONBool bool) {
+ if (bool.bool) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ public Integer visitString(JSONString str) {
+ return str.str.length();
+ }
+ public Integer visitList(JSONList list) {
+ return list.values.map(new JSONToNumber()).foldr(new SumInteger(), 0);
+ }
+ public Integer visitObject(JSONObject obj) {
+ return obj.pairs.map(new PairsToJSON()) // List -> JSONList
+ .map(new JSONToNumber()) // JSONList -> List
+ .foldr(new SumInteger(), 0); // List -> Integer
+ }
+}
+
+interface IPairsVisitor extends IFunc {}
+
+class JSONFind implements IJsonVisitor {
+ String find;
+ JSONFind(String find) {
+ this.find = find;
+ }
+ public JSON apply(JSON j) {
+ return j.accept(this);
+ }
+ public JSON visitBlank(JSONBlank blank) {
+ return new JSONBlank();
+ }
+ public JSON visitNumber(JSONNumber number) {
+ return new JSONBlank();
+ }
+ public JSON visitBool(JSONBool bool) {
+ return new JSONBlank();
+ }
+ public JSON visitString(JSONString str) {
+ if (this.find.compareTo(str.str) == 0) {
+ return str;
+ } else {
+ return new JSONBlank();
+ }
+ }
+ public JSON visitList(JSONList list) {
+ return list.values //JSONList -> List
+ .map(new JSONFind(find)) //List -> List (containing JSONBlank and value == find)
+ .getFirstOrBackup(new JSONBlank()); //List -> JSON (first value of List)
+ }
+ public JSON visitObject(JSONObject obj) {
+ return obj.pairs // JSONObject -> List
+ .filter(new FindKey(find)) // List> -> List> (where key == find)
+ .map(new PairsToJSON()) // List> -> List
+ .getFirstOrBackup(new JSONBlank()); // List -> JSON (first value of List
+ }
+}
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/.classpath b/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/.classpath
new file mode 100644
index 0000000..8e3d409
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/.classpath
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/.project b/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/.project
new file mode 100644
index 0000000..4c34331
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/.project
@@ -0,0 +1,17 @@
+
+
+ Lab07_Buddies
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/.settings/org.eclipse.core.resources.prefs b/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..99f26c0
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/=UTF-8
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/.settings/org.eclipse.jdt.core.prefs b/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..e71285a
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
+org.eclipse.jdt.core.compiler.release=enabled
+org.eclipse.jdt.core.compiler.source=11
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/src/ConsLoBuddy.java b/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/src/ConsLoBuddy.java
new file mode 100644
index 0000000..c75b020
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/src/ConsLoBuddy.java
@@ -0,0 +1,65 @@
+// represents a list of Person's buddies
+class ConsLoBuddy implements ILoBuddy {
+
+ Person first;
+ ILoBuddy rest;
+
+ ConsLoBuddy(Person first, ILoBuddy rest) {
+ this.first = first;
+ this.rest = rest;
+ }
+ // returns ILoBuddy which includes this and that
+ public ILoBuddy combine(ILoBuddy that) {
+ if (!that.isIncluded(this.first)) {
+ return new ConsLoBuddy(this.first, this.rest.combine(that));
+ } else {
+ return this.rest.combine(that);
+ }
+ }
+ // returns true if that person is included in buddy list
+ public boolean isIncluded(Person that) {
+ if (this.first.equals(that)) {
+ return true;
+ } else {
+ return this.rest.isIncluded(that);
+ }
+ }
+ // returns the count of common persons in buddy list
+ public int countCommon(ILoBuddy those) {
+ return this.countCommonHelper(those, 0);
+ }
+ public int countCommonHelper(ILoBuddy those, int csf) {
+ if (those.isIncluded(this.first)) {
+ return this.rest.countCommonHelper(those, csf + 1);
+ } else {
+ return this.rest.countCommonHelper(those, csf);
+ }
+ }
+ // returns true if that person is included this extended buddy list
+ public boolean hasExtendedBuddy(Person that) {
+ return this.hasExtendedBuddyHelper(that, new MTLoBuddy());
+ }
+ public boolean hasExtendedBuddyHelper(Person that, ILoBuddy wasChecked) {
+ if (wasChecked.isIncluded(this.first)) {
+ // if the first person was already checked move on
+ return this.rest.hasExtendedBuddyHelper(that, wasChecked);
+ } else if (this.first.equals(that)) {
+ // if the first person is the person person we are looking for return true
+ return true;
+ } else {
+ return this.rest.combine(this.first.buddies) // add first's buddies to work list accumulator (this.rest)
+ .hasExtendedBuddyHelper(that, // recursive call search
+ new ConsLoBuddy(this.first, wasChecked)); // add first to wasChecked so we dont look at them again
+ }
+ }
+ public int partyCount(int csf, ILoBuddy wasChecked) {
+ if (wasChecked.isIncluded(this.first)) {
+ // if the first person was already checked move on
+ return this.rest.partyCount(csf, wasChecked);
+ } else {
+ return this.rest.combine(this.first.buddies)
+ .partyCount(csf + 1,
+ new ConsLoBuddy(this.first, wasChecked));
+ }
+ }
+}
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/src/ExamplesBuddies.java b/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/src/ExamplesBuddies.java
new file mode 100644
index 0000000..bff81fc
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/src/ExamplesBuddies.java
@@ -0,0 +1,121 @@
+import tester.Tester;
+//Ann's buddies are Bob and Cole
+//Bob's buddies are Ann and Ed and Hank
+//Cole's buddy is Dan
+//Dan's buddy is Cole
+//Ed's buddy is Fay
+//Fay's buddies are Ed and Gabi
+//Gabi's buddies are Ed and Fay
+//Hank does not have any buddies
+//Jan's buddies are Kim and Len
+//Kim's buddies are Jan and Len
+//Len's buddies are Jan and Kim
+
+public class ExamplesBuddies {
+ Person ann;
+ Person bob;
+ Person cole;
+ Person dan;
+ Person ed;
+ Person fay;
+ Person gabi;
+ Person hank;
+ Person jan;
+ Person kim;
+ Person len;
+
+ Person lotsa;
+
+ void initTestConditions() {
+ this.ann = new Person("ann");
+ this.bob = new Person("bob");
+ this.cole = new Person("cole");
+ this.dan = new Person("dan");
+ this.ed = new Person("ed");
+ this.fay = new Person("fay");
+ this.gabi = new Person("gabi");
+ this.hank = new Person("hank");
+ this.jan = new Person("jan");
+ this.kim = new Person("kim");
+ this.len = new Person("len");
+
+ this.ann.addBuddy(bob);
+ this.ann.addBuddy(cole);
+ this.bob.addBuddy(ann);
+ this.bob.addBuddy(ed);
+ this.bob.addBuddy(hank);
+ this.cole.addBuddy(dan);
+ this.dan.addBuddy(cole);
+ this.ed.addBuddy(fay);
+ this.fay.addBuddy(ed);
+ this.fay.addBuddy(gabi);
+ this.gabi.addBuddy(ed);
+ this.gabi.addBuddy(fay);
+ this.jan.addBuddy(kim);
+ this.jan.addBuddy(len);
+ this.kim.addBuddy(jan);
+ this.kim.addBuddy(len);
+ this.len.addBuddy(jan);
+ this.len.addBuddy(kim);
+ }
+
+ void testInit(Tester t) {
+ initTestConditions();
+ t.checkExpect(this.ann.buddies,
+ new ConsLoBuddy(this.cole, new ConsLoBuddy(this.bob, new MTLoBuddy())));
+ t.checkExpect(this.hank.buddies, new MTLoBuddy());
+ }
+ void testCombine(Tester t) {
+ initTestConditions();
+ ILoBuddy mtList = new MTLoBuddy();
+ ILoBuddy list1 = new ConsLoBuddy(this.ann, new ConsLoBuddy(this.bob, mtList));
+ ILoBuddy list2 = new ConsLoBuddy(this.cole, new ConsLoBuddy(this.dan, mtList));
+ ILoBuddy list_combo = new ConsLoBuddy(this.ann, new ConsLoBuddy(this.bob,
+ new ConsLoBuddy(this.cole, new ConsLoBuddy(this.dan, mtList))));
+ t.checkExpect(list1.combine(list2), list_combo);
+ }
+
+ void testHadBuddy(Tester t) {
+ initTestConditions();
+ t.checkExpect(this.ann.hasDirectBuddy(bob), true);
+ t.checkExpect(this.ann.hasDirectBuddy(cole), true);
+ t.checkExpect(this.ann.hasDirectBuddy(dan), false);
+ t.checkExpect(this.cole.hasDirectBuddy(ann), false);
+ }
+ void testCountCommonBuddies(Tester t) {
+ initTestConditions();
+ this.lotsa = new Person("Lotsa");
+ this.lotsa.addBuddy(ann);
+ this.lotsa.addBuddy(bob);
+ this.lotsa.addBuddy(cole);
+ this.lotsa.addBuddy(dan);
+ this.lotsa.addBuddy(ed);
+ this.lotsa.addBuddy(fay);
+ this.lotsa.addBuddy(gabi);
+ this.lotsa.addBuddy(hank);
+ this.lotsa.addBuddy(jan);
+ this.lotsa.addBuddy(kim);
+ this.lotsa.addBuddy(len);
+
+ t.checkExpect(this.ann.countCommonBuddies(bob), 0);
+ t.checkExpect(this.bob.countCommonBuddies(ann), 0);
+ t.checkExpect(this.ann.countCommonBuddies(dan), 1);
+ t.checkExpect(this.len.countCommonBuddies(kim), 1);
+ t.checkExpect(this.lotsa.countCommonBuddies(bob), 3);
+ t.checkExpect(this.bob.countCommonBuddies(lotsa), 3);
+ }
+ void testHasExtendedBuddy(Tester t) {
+ initTestConditions();
+ t.checkExpect(this.ann.hasExtendedBuddy(bob), true);
+ t.checkExpect(this.ann.hasExtendedBuddy(ed), true);
+ t.checkExpect(this.ann.hasExtendedBuddy(fay), true);
+ t.checkExpect(this.ann.hasExtendedBuddy(gabi), true);
+ t.checkExpect(this.ann.hasExtendedBuddy(jan), false);
+ }
+ void testPartyCount(Tester t) {
+ t.checkExpect(this.len.partyCount(), 2);
+ t.checkExpect(this.kim.partyCount(), 2);
+ t.checkExpect(this.hank.partyCount(), 0);
+ t.checkExpect(this.ann.partyCount(), 7);
+ }
+}
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/src/ILoBuddy.java b/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/src/ILoBuddy.java
new file mode 100644
index 0000000..14106e0
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/src/ILoBuddy.java
@@ -0,0 +1,15 @@
+
+// represents a list of Person's buddies
+interface ILoBuddy {
+ // returns ILoBuddy which includes this and that
+ ILoBuddy combine(ILoBuddy that);
+ // returns true if that person is included in buddy list
+ boolean isIncluded(Person that);
+ // returns the count of common persons in buddy list
+ int countCommon(ILoBuddy those);
+ int countCommonHelper(ILoBuddy those, int csf);
+ // returns true if that person is included this extended buddylist
+ boolean hasExtendedBuddy(Person that);
+ boolean hasExtendedBuddyHelper(Person that, ILoBuddy wasChecked);
+ int partyCount(int csf, ILoBuddy wasChecked);
+}
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/src/MTLoBuddy.java b/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/src/MTLoBuddy.java
new file mode 100644
index 0000000..54bd1f8
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/src/MTLoBuddy.java
@@ -0,0 +1,31 @@
+
+// represents an empty list of Person's buddies
+class MTLoBuddy implements ILoBuddy {
+ MTLoBuddy() {}
+
+ // returns ILoBuddy which includes this and that
+ public ILoBuddy combine(ILoBuddy that) {
+ return that;
+ }
+ // returns true if that person is included in buddy list
+ public boolean isIncluded(Person that) {
+ return false;
+ }
+ // returns the count of common persons in buddy list
+ public int countCommon(ILoBuddy those) {
+ return 0;
+ }
+ public int countCommonHelper(ILoBuddy those, int csf) {
+ return csf;
+ }
+ // returns true if that person is included this extended buddylist
+ public boolean hasExtendedBuddy(Person that) {
+ return false;
+ }
+ public boolean hasExtendedBuddyHelper(Person that, ILoBuddy wasChecked) {
+ return false;
+ }
+ public int partyCount(int csf, ILoBuddy wasChecked) {
+ return csf;
+ }
+}
diff --git a/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/src/Person.java b/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/src/Person.java
new file mode 100644
index 0000000..6f8f0ae
--- /dev/null
+++ b/completedwork/core_programming/02_classbased_design/Workspace/Lab07_Buddies/src/Person.java
@@ -0,0 +1,45 @@
+
+// represents a Person with a user name and a list of buddies
+class Person {
+
+ String username;
+ ILoBuddy buddies;
+
+ Person(String username) {
+ this.username = username;
+ this.buddies = new MTLoBuddy();
+ }
+
+ // add p to this person's buddy list
+ void addBuddy(Person p) {
+ this.buddies = new ConsLoBuddy(p, this.buddies);
+ }
+
+ // returns true if this Person has that as a direct buddy
+ boolean hasDirectBuddy(Person that) {
+ return this.buddies.isIncluded(that);
+ }
+
+ // returns the number of people that are direct buddies
+ // of both this and that person
+ int countCommonBuddies(Person that) {
+ return this.buddies.countCommon(that.buddies);
+ }
+
+ // will that person be invited to a party
+ // organized by this person?
+ boolean hasExtendedBuddy(Person that) {
+ return this.buddies.hasExtendedBuddy(that);
+ }
+ // renamed hasExtendedBuddy
+ boolean isInvited(Person that) {
+ return this.hasExtendedBuddy(that);
+ }
+
+ // returns the number of people who will show up at the party
+ // given by this person (not including inviter (this))
+ int partyCount() {
+ return this.buddies.partyCount(0, // initialize count
+ new ConsLoBuddy(this, new MTLoBuddy())); // add this person to wasChecked to avoid off by one
+ }
+}