diff --git a/mooc-java-programming-i/part05-Part05_01.OneMinute/.tmcproject.yml b/mooc-java-programming-i/part05-Part05_01.OneMinute/.tmcproject.yml new file mode 100644 index 0000000..d2446da --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_01.OneMinute/.tmcproject.yml @@ -0,0 +1 @@ +force_new_sandbox: true diff --git a/mooc-java-programming-i/part05-Part05_01.OneMinute/pom.xml b/mooc-java-programming-i/part05-Part05_01.OneMinute/pom.xml new file mode 100644 index 0000000..759c313 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_01.OneMinute/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + tkt + Part05_01.OneMinute + Part05_01.OneMinute + 1.0-SNAPSHOT + jar + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + fi.helsinki.cs.tmc + edu-test-utils + 0.4.2 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + diff --git a/mooc-java-programming-i/part05-Part05_01.OneMinute/src/main/java/ClockHand.java b/mooc-java-programming-i/part05-Part05_01.OneMinute/src/main/java/ClockHand.java new file mode 100644 index 0000000..92b3e4c --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_01.OneMinute/src/main/java/ClockHand.java @@ -0,0 +1,31 @@ + +public class ClockHand { + + private int value; + private int limit; + + public ClockHand(int limit) { + this.limit = limit; + this.value = 0; + } + + public void advance() { + this.value = this.value + 1; + + if (this.value >= this.limit) { + this.value = 0; + } + } + + public int value() { + return this.value; + } + + public String toString() { + if (this.value < 10) { + return "0" + this.value; + } + + return "" + this.value; + } +} diff --git a/mooc-java-programming-i/part05-Part05_01.OneMinute/src/main/java/Program.java b/mooc-java-programming-i/part05-Part05_01.OneMinute/src/main/java/Program.java new file mode 100644 index 0000000..7dc1139 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_01.OneMinute/src/main/java/Program.java @@ -0,0 +1,11 @@ + +import java.util.Scanner; + +public class Program { + + public static void main(String[] args) { + // You can test your program here + + + } +} diff --git a/mooc-java-programming-i/part05-Part05_01.OneMinute/src/test/java/TimerTest.java b/mooc-java-programming-i/part05-Part05_01.OneMinute/src/test/java/TimerTest.java new file mode 100644 index 0000000..4c5a6a4 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_01.OneMinute/src/test/java/TimerTest.java @@ -0,0 +1,144 @@ + +import fi.helsinki.cs.tmc.edutestutils.MockStdio; +import fi.helsinki.cs.tmc.edutestutils.Points; +import fi.helsinki.cs.tmc.edutestutils.Reflex; +import java.util.Random; +import org.junit.*; +import static org.junit.Assert.*; + +@Points("05-01") +public class TimerTest { + + @Rule + public MockStdio io = new MockStdio(); + + @Test + public void classAndConstructor() { + createTimer(); + } + + @Test + public void toStringInTheBeginning() { + Object timer = createTimer(); + + String toStringFromTimer = callToString(timer); + + assertEquals("Printing the result of toString of a newly created timer should result in \"00:00\". Now the output was " + toStringFromTimer + "\nTry it out yourself:\n" + + "Timer t = new Timer();\n" + + "System.out.println(t);", "00:00", toStringFromTimer); + } + + @Test + public void advanceMethodExists() { + Object timer = createTimer(); + Reflex.reflect("Timer").method("advance").returningVoid().takingNoParams().requirePublic(); + + try { + Reflex.reflect("Timer").method("advance").returningVoid().takingNoParams().invokeOn(timer); + } catch (Throwable t) { + fail("An error occurred when calling the method 'advance'. The error was: " + t.getMessage() + "\nTry it out:\n" + + "Timer t = new Timer();\n" + + "t.advance();"); + } + + String toStringFromTimer = callToString(timer); + + assertEquals("After a timer has advanced once, the result of toString should be \"00:01\". Now it was " + toStringFromTimer + "Try it out yourself:\n" + + "Timer t = new Timer();\n" + + "t.advance();\n" + + "System.out.println(t);", "00:01", toStringFromTimer); + } + + @Test + public void advanceFar() { + Object timer = createTimer(); + + int randomAdvancementTime = new Random().nextInt(1000) + 1000; + for (int i = 1; i <= randomAdvancementTime; i++) { + try { + Reflex.reflect("Timer").method("advance").returningVoid().takingNoParams().invokeOn(timer); + } catch (Throwable t) { + fail("An error occurred when calling the 'advance' method. The error was: " + t.getMessage() + "\nTry calling the advance method " + (i) + " times."); + } + } + + int seconds = ((randomAdvancementTime / 100) % 60); + int hundredths = (randomAdvancementTime % 100); + + String s = seconds < 10 ? "0" + seconds : "" + seconds; + String hos = hundredths < 10 ? "0" + hundredths : "" + hundredths; + + String toStringFromTimer = callToString(timer); + String expectedPrint = "" + s + ":" + hos; + + assertEquals("When the advance method is called " + randomAdvancementTime + " times, the print should be \"" + expectedPrint + "\".\nNow it was " + toStringFromTimer + "\nTry it out:\n" + + "Timer t = new Timer();\n" + + "int i = 0;\n" + + "while (i < " + randomAdvancementTime + ") {\n" + + " t.advance();\n" + + "}" + + "System.out.println(t);", expectedPrint, toStringFromTimer); + } + + @Test + public void advanceVeryFar() { + Object timer = createTimer(); + + int randomAdvancementTime = new Random().nextInt(10000) + 360000; + for (int i = 1; i <= randomAdvancementTime; i++) { + try { + Reflex.reflect("Timer").method("advance").returningVoid().takingNoParams().invokeOn(timer); + } catch (Throwable t) { + fail("An error occurred when calling the 'advance' method. The error was: " + t.getMessage() + "\nTry calling the advance method " + (i) + " times."); + } + } + + int seconds = ((randomAdvancementTime / 100) % 60); + int hundredths = (randomAdvancementTime % 100); + + String s = seconds < 10 ? "0" + seconds : "" + seconds; + String hos = hundredths < 10 ? "0" + hundredths : "" + hundredths; + + String toStringFromTimer = callToString(timer); + String expectedPrint = "" + s + ":" + hos; + + assertEquals("When the advance method is called " + randomAdvancementTime + " times, the print should be \"" + expectedPrint + "\".\nNow it was " + toStringFromTimer + "\nTry it out:\n" + + "Timer t = new Timer();\n" + + "int i = 0;\n" + + "while (i < " + randomAdvancementTime + ") {\n" + + " t.advance();\n" + + "}" + + "System.out.println(t);", expectedPrint, toStringFromTimer); + } + + private String callToString(Object timer) { + String out = io.getSysOut(); + + String toStringFromTimer = null; + + try { + toStringFromTimer = timer.toString(); + } catch (Throwable e) { + fail("Error when calling the toString method of the timer. Try:\n" + + "Timer timer = new Timer();\n" + + "timer.toString();\n" + + "The error that occurred: " + e.getMessage()); + } + + assertEquals("Calling the method toString shouldn't print anything. It is only to return a string.", out, io.getSysOut()); + + return toStringFromTimer; + } + + private Object createTimer() { + Reflex.reflect("Timer").ctor().takingNoParams().requirePublic(); + try { + return Reflex.reflect("Timer").ctor().takingNoParams().invoke(); + } catch (Throwable ex) { + fail("An error occured while testing the program. Try:\nTimer timer = new Timer();\nError: " + ex.getMessage()); + } + return null; + } + + +} diff --git a/mooc-java-programming-i/part05-Part05_02.Book/.tmcproject.yml b/mooc-java-programming-i/part05-Part05_02.Book/.tmcproject.yml new file mode 100644 index 0000000..d2446da --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_02.Book/.tmcproject.yml @@ -0,0 +1 @@ +force_new_sandbox: true diff --git a/mooc-java-programming-i/part05-Part05_02.Book/pom.xml b/mooc-java-programming-i/part05-Part05_02.Book/pom.xml new file mode 100644 index 0000000..0014a72 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_02.Book/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + tkt + Part05_02.Book + Part05_02.Book + 1.0-SNAPSHOT + jar + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + fi.helsinki.cs.tmc + edu-test-utils + 0.4.2 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + diff --git a/mooc-java-programming-i/part05-Part05_02.Book/src/main/java/Program.java b/mooc-java-programming-i/part05-Part05_02.Book/src/main/java/Program.java new file mode 100644 index 0000000..421d74b --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_02.Book/src/main/java/Program.java @@ -0,0 +1,14 @@ + +public class Program { + + public static void main(String[] args) { + // This is simply an empty main method where you are + // free to experiment with your Book class. + // An example that you can use for testing: + + +// Book b = new Book("J. K. Rowling", "Harry Potter and the Sorcerer's Stone", 223); +// System.out.println(b); + + } +} diff --git a/mooc-java-programming-i/part05-Part05_02.Book/src/test/java/BookTest.java b/mooc-java-programming-i/part05-Part05_02.Book/src/test/java/BookTest.java new file mode 100644 index 0000000..4e0b79a --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_02.Book/src/test/java/BookTest.java @@ -0,0 +1,257 @@ + +import fi.helsinki.cs.tmc.edutestutils.Points; +import fi.helsinki.cs.tmc.edutestutils.ReflectionUtils; +import fi.helsinki.cs.tmc.edutestutils.MockInOut; +import fi.helsinki.cs.tmc.edutestutils.Reflex; +import java.lang.reflect.Field; +import org.junit.Test; +import org.junit.Before; +import static org.junit.Assert.*; + +@Points("05-02") +public class BookTest { + + Reflex.ClassRef klass; + String klassName = "Book"; + + @Before + public void fetchClass() { + klass = Reflex.reflect(klassName); + } + + @Test + public void classIsPublic() { + assertTrue("The class " + klassName + " must be public, so it has to be defined as\npublic class " + klassName + " {...\n}", klass.isPublic()); + } + + @Test + public void testConstructor() throws Throwable { + Reflex.MethodRef3 cc = klass.constructor().taking(String.class, String.class, int.class).withNiceError(); + assertTrue("Define for the class " + klassName + " a public constructor: public " + klassName + "(String author, String name, int pages)", cc.isPublic()); + cc.invoke("Marie Kondo", "KonMari", 222); + } + + @Test + public void noExtraVariables() { + sanityCheck(); + } + + @Test + public void methodsExist() throws Throwable { + Reflex.MethodRef3 bookClass = klass.constructor().taking(String.class, String.class, int.class).withNiceError(); + Object book = bookClass.invoke("Marie Kondo", "KonMari", 222); + + try { + klass.method(book, "getAuthor") + .returning(String.class) + .takingNoParams().invoke(); + } catch (AssertionError ae) { + fail("Error: " + ae + "\n so give the class " + klassName + " the method public String getAuthor()"); + } + + assertTrue("The getAuthor method must be public, i.e. defined as public void getAuthor()", klass.method(book, "getAuthor") + .returning(String.class) + .takingNoParams().isPublic()); + + try { + klass.method(book, "getName") + .returning(String.class) + .takingNoParams().invoke(); + } catch (AssertionError ae) { + fail("Error: " + ae + "\n so give the class " + klassName + " the method public String getName()"); + } + + assertTrue("The getName method must be public, i.e. defined as public void getPages()", klass.method(book, "getName") + .returning(String.class) + .takingNoParams().isPublic()); + + try { + klass.method(book, "getPages") + .returning(int.class) + .takingNoParams().invoke(); + } catch (AssertionError ae) { + fail("Error: " + ae + "\n so give the class " + klassName + " the method public String getPages()"); + } + + assertTrue("The getPages method must be public, i.e. defined as public void getPages()", klass.method(book, "getPages") + .returning(int.class) + .takingNoParams().isPublic()); + } + + @Test + public void testReturningAuthor() throws Throwable { + MockInOut mio = new MockInOut(""); + Reflex.MethodRef3 bookClass = klass.constructor().taking(String.class, String.class, int.class).withNiceError(); + Object book = bookClass.invoke("Marie Kondo", "KonMari", 222); + + String author = klass.method(book, "getAuthor") + .returning(String.class) + .takingNoParams().invoke(); + + assertEquals("When executing the commands\n Book b = new Book(\"Marie Kondo\", \"KonMari\", 222);\nString s = b.getAuthor();\nThe variable s should store the value \"Marie Kondo\".", "Marie Kondo", author); + + String out = mio.getOutput(); + + mio.close(); + + assertTrue("The constructor and the getAuthor methods should print nothing.", out.trim().isEmpty()); + } + + @Test + public void testReturningAuthor2() throws Throwable { + MockInOut mio = new MockInOut(""); + Reflex.MethodRef3 bookClass = klass.constructor().taking(String.class, String.class, int.class).withNiceError(); + Object kirja = bookClass.invoke("Karie Mondo", "MonKari", 222); + + String author = klass.method(kirja, "getAuthor") + .returning(String.class) + .takingNoParams().invoke(); + + assertEquals("When executing the commands\n Book b = new Book(\"Karie Mondo\", \"MonKari\", 222);\nString s = b.getAuthor();\nThe variable s should store the value \"Karie Mondo\".", "Karie Mondo", author); + + String out = mio.getOutput(); + + mio.close(); + + assertTrue("The constructor and the getAuthor methods should print nothing.", out.trim().isEmpty()); + } + + @Test + public void testReturningName() throws Throwable { + MockInOut mio = new MockInOut(""); + Reflex.MethodRef3 bookClass = klass.constructor().taking(String.class, String.class, int.class).withNiceError(); + Object kirja = bookClass.invoke("Marie Kondo", "KonMari", 222); + + String name = klass.method(kirja, "getName") + .returning(String.class) + .takingNoParams().invoke(); + + assertEquals("When executing the commands\n Book b = new Book(\"Marie Kondo\", \"KonMari\", 222);\nString s = b.getName();\nThe variable s should store the value \"KonMari\".", "KonMari", name); + + + String out = mio.getOutput(); + + mio.close(); + + assertTrue("The constructor and the getName methods should print nothing.", out.trim().isEmpty()); + } + + @Test + public void testReturningName2() throws Throwable { + MockInOut mio = new MockInOut(""); + Reflex.MethodRef3 bookClass = klass.constructor().taking(String.class, String.class, int.class).withNiceError(); + Object book = bookClass.invoke("Karie Mondo", "MonKari", 222); + + String name = klass.method(book, "getName") + .returning(String.class) + .takingNoParams().invoke(); + + assertEquals("When executing the commands\n Book b = new Book(\"Karie Mondo\", \"MonKari\", 222);\nString s = b.getName();\nThe variable s should store the value \"MonKari\".", "MonKari", name); + + + String out = mio.getOutput(); + + mio.close(); + + assertTrue("The constructor and the getName methods should print nothing.", out.trim().isEmpty()); + } + + @Test + public void testReturningPages() throws Throwable { + MockInOut mio = new MockInOut(""); + Reflex.MethodRef3 bookClass = klass.constructor().taking(String.class, String.class, int.class).withNiceError(); + Object kirja = bookClass.invoke("Marie Kondo", "KonMari", 222); + + int pages = klass.method(kirja, "getPages") + .returning(int.class) + .takingNoParams().invoke(); + + assertEquals("When executing the commands\n Book b = new Book(\"Marie Kondo\", \"KonMari\", 222);\nint s = b.getPages();\nThe variable s should store the value 222.", 222, pages); + + + String out = mio.getOutput(); + + mio.close(); + + assertTrue("The constructor and the getPages methods should print nothing.", out.trim().isEmpty()); + } + + @Test + public void testReturningPages2() throws Throwable { + MockInOut mio = new MockInOut(""); + Reflex.MethodRef3 bookClass = klass.constructor().taking(String.class, String.class, int.class).withNiceError(); + Object kirja = bookClass.invoke("Marie Kondo", "KonMari", 2222); + + int pages = klass.method(kirja, "getPages") + .returning(int.class) + .takingNoParams().invoke(); + + assertEquals("When executing the commands\n Book b = new Book(\"Marie Kondo\", \"KonMari\", 2222);\nint s = b.getPages();\nThe variable s should store the value 2222.", 2222, pages); + + + String out = mio.getOutput(); + + mio.close(); + + assertTrue("The constructor and the getPages methods should print nothing.", out.trim().isEmpty()); + } + + @Test + public void testToString() throws Throwable { + MockInOut mio = new MockInOut(""); + Reflex.MethodRef3 bookClass = klass.constructor().taking(String.class, String.class, int.class).withNiceError(); + Object book = bookClass.invoke("Marie Kondo", "KonMari", 222); + + String toString = book.toString(); + + assertEquals("When executing the commands\n Book b = new Book(\"Marie Kondo\", \"KonMari\", 222);\nString s = b.toString();\nThe variable s should store the value \"Marie Kondo, KonMari, 222 pages\".", "Marie Kondo, KonMari, 222 pages", toString); + + + String out = mio.getOutput(); + + mio.close(); + + assertTrue("The constructor and the toString methods should print nothing.", out.trim().isEmpty()); + + } + + @Test + public void testToString2() throws Throwable { + MockInOut mio = new MockInOut(""); + Reflex.MethodRef3 bookClass = klass.constructor().taking(String.class, String.class, int.class).withNiceError(); + Object book = bookClass.invoke("Karie Mondo", "MonKari", 2222); + + String toString = book.toString(); + + assertEquals("When executing the commands\n Book b = new Book(\"Karie Mondo\", \"MonKari\", 2222);\nString s = b.toString();\nThe variable s should store the value \"Karie Mondo, MonKari, 2222 pages\".", "Karie Mondo, MonKari, 2222 pages", toString); + + String out = mio.getOutput(); + + mio.close(); + + assertTrue("The constructor and the toString methods should print nothing.", out.trim().isEmpty()); + } + + private void sanityCheck() throws SecurityException { + Field[] fields = ReflectionUtils.findClass(klassName).getDeclaredFields(); + + for (Field field : fields) { + assertFalse("you don't need \"static variables\", delete " + field(field.toString()), field.toString().contains("static") && !field.toString().contains("final")); + assertTrue("the visibility of all the object variables must be private, change " + field(field.toString()), field.toString().contains("private")); + } + + if (fields.length > 1) { + int var = 0; + for (Field field : fields) { + if (!field.toString().contains("final")) { + var++; + } + } + assertTrue("The class " + klassName + " needs only three object variables, delete the extras", var < 4); + } + } + + private String field(String toString) { + return toString.replace(klassName + ".", ""); + } +} diff --git a/mooc-java-programming-i/part05-Part05_03.Cube/.tmcproject.yml b/mooc-java-programming-i/part05-Part05_03.Cube/.tmcproject.yml new file mode 100644 index 0000000..d2446da --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_03.Cube/.tmcproject.yml @@ -0,0 +1 @@ +force_new_sandbox: true diff --git a/mooc-java-programming-i/part05-Part05_03.Cube/pom.xml b/mooc-java-programming-i/part05-Part05_03.Cube/pom.xml new file mode 100644 index 0000000..b446c77 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_03.Cube/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + tkt + Part05_03.Cube + Part05_03.Cube + 1.0-SNAPSHOT + jar + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + fi.helsinki.cs.tmc + edu-test-utils + 0.4.2 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + diff --git a/mooc-java-programming-i/part05-Part05_03.Cube/src/main/java/Program.java b/mooc-java-programming-i/part05-Part05_03.Cube/src/main/java/Program.java new file mode 100644 index 0000000..8b3c5db --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_03.Cube/src/main/java/Program.java @@ -0,0 +1,11 @@ + +import java.util.Scanner; + +public class Program { + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + + // Experiment with your program here + } +} diff --git a/mooc-java-programming-i/part05-Part05_03.Cube/src/test/java/CubeTest.java b/mooc-java-programming-i/part05-Part05_03.Cube/src/test/java/CubeTest.java new file mode 100644 index 0000000..78cf488 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_03.Cube/src/test/java/CubeTest.java @@ -0,0 +1,101 @@ + +import fi.helsinki.cs.tmc.edutestutils.MockStdio; +import fi.helsinki.cs.tmc.edutestutils.Points; +import fi.helsinki.cs.tmc.edutestutils.Reflex; +import org.junit.*; +import static org.junit.Assert.*; + +@Points("05-03") +public class CubeTest { + + @Rule + public MockStdio io = new MockStdio(); + + @Test + public void classAndConstructor() { + createCube(5); + } + + @Test + public void volumeMethod() { + Object c = createCube(5); + + assertEquals("With edge length 5, the volume of the cube should be 125. Test:\n" + + "Cube c = new Cube(5);\n" + + "System.out.println(c.volume());", 125, callVolume(c, 5)); + } + + @Test + public void volumeMethod2() { + Object c = createCube(7); + + assertEquals("With edge length 7, the volume of the cube should be 343. Test:\n" + + "Cube c = new Cube(7);\n" + + "System.out.println(c.volume());", 343, callVolume(c, 7)); + } + + @Test + public void toStringMethod() { + Object c = createCube(7); + String out = io.getSysOut(); + String toStringFromCube = c.toString(); + assertTrue("toString should print nothing. Test:\n" + + "Cube c = new Cube(7);\n" + + "c.toString();\n" + + "The program should print nothing.", out.equals(io.getSysOut())); + + assertTrue("Try it out:\n" + + "Cube c = new Cube(7);\n" + + "System.out.println(c.toString());\n" + + "The output of the program should be:\n" + + "\"The length of the edge is 7 and the volume 343\"", toStringFromCube.contains("edge") && toStringFromCube.contains("7") && toStringFromCube.contains("343")); + } + + @Test + public void toStringMethod2() { + Object c = createCube(3); + String out = io.getSysOut(); + String toStringFromCube = c.toString(); + + assertTrue("toString should print nothing. Test:\n" + + "Cube c = new Cube(3);\n" + + "c.toString();\n" + + "The program should print nothing.", out.equals(io.getSysOut())); + + + assertTrue("Try it out:\n" + + "Cube c = new Cube(3);\n" + + "System.out.println(c.toString());\n" + + "The output of the program should be:\n" + + "\"The length of the edge is 3 and the volume 27\"", toStringFromCube.contains("edge") && toStringFromCube.contains("3") && toStringFromCube.contains("27")); + + + assertFalse("Try it out:\n" + + "Cube c = new Cube(3);\n" + + "System.out.println(c.toString());\n" + + "The output of the program should be:\n" + + "\"The length of the edge is 3 and the volume 27\"", toStringFromCube.contains("34") || toStringFromCube.contains("43")); + } + + private Object createCube(int edgeLength) { + Reflex.reflect("Cube").ctor().taking(int.class).requirePublic(); + try { + return Reflex.reflect("Cube").ctor().taking(int.class).invoke(edgeLength); + } catch (Throwable ex) { + fail("Creating a cube led to an error. Try:\nCube cube = new Cube(" + edgeLength + ");"); + } + + return null; + } + + private int callVolume(Object cube, int edgeLength) { + Reflex.reflect("Cube").method("volume").returning(int.class).takingNoParams().requirePublic(); + try { + return Reflex.reflect("Cube").method("volume").returning(int.class).takingNoParams().invokeOn(cube); + } catch (Throwable ex) { + fail("An error occurred when calling a cube's volume method. Try it out:\nCube cube = new Cube(" + edgeLength + ");\nSystem.out.println(cube.volume());"); + } + + return -1; + } +} diff --git a/mooc-java-programming-i/part05-Part05_04.FitByte/.tmcproject.yml b/mooc-java-programming-i/part05-Part05_04.FitByte/.tmcproject.yml new file mode 100644 index 0000000..d2446da --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_04.FitByte/.tmcproject.yml @@ -0,0 +1 @@ +force_new_sandbox: true diff --git a/mooc-java-programming-i/part05-Part05_04.FitByte/pom.xml b/mooc-java-programming-i/part05-Part05_04.FitByte/pom.xml new file mode 100644 index 0000000..24a6a0c --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_04.FitByte/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + tkt + Part05_04.Fitbyte + Part05_04.Fitbyte + 1.0-SNAPSHOT + jar + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + fi.helsinki.cs.tmc + edu-test-utils + 0.4.2 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + diff --git a/mooc-java-programming-i/part05-Part05_04.FitByte/src/main/java/Program.java b/mooc-java-programming-i/part05-Part05_04.FitByte/src/main/java/Program.java new file mode 100644 index 0000000..7adde33 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_04.FitByte/src/main/java/Program.java @@ -0,0 +1,19 @@ + +public class Program { + + public static void main(String[] args) { + // This is an empty main method where you can experiment + // with your Fitbyte class + +// Fitbyte fitbyte = new Fitbyte(30, 60); +// +// double percentage = 0.5; +// +// while (percentage < 1.0) { +// double target = fitbyte.targetHeartRate(percentage); +// System.out.println("Target " + (percentage * 100) + "% of maximum: " + target); +// percentage += 0.1; +// } + + } +} diff --git a/mooc-java-programming-i/part05-Part05_04.FitByte/src/test/java/FitbyteTest.java b/mooc-java-programming-i/part05-Part05_04.FitByte/src/test/java/FitbyteTest.java new file mode 100644 index 0000000..f8afbee --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_04.FitByte/src/test/java/FitbyteTest.java @@ -0,0 +1,102 @@ + +import fi.helsinki.cs.tmc.edutestutils.Points; +import fi.helsinki.cs.tmc.edutestutils.ReflectionUtils; +import fi.helsinki.cs.tmc.edutestutils.Reflex; +import java.lang.reflect.Field; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import org.junit.Before; +import org.junit.Test; + +@Points("05-04") +public class FitbyteTest { + + Reflex.ClassRef klass; + String klassName = "Fitbyte"; + + @Before + public void fetchClass() { + klass = Reflex.reflect(klassName); + } + + @Test + public void classIsPublic() { + assertTrue("The class " + klassName + " must be public, so it should be defined as\npublic class " + klassName + " {...\n}", klass.isPublic()); + } + + @Test + public void testConstructor() throws Throwable { + Reflex.MethodRef2 cc = klass.constructor().taking(int.class, int.class).withNiceError(); + assertTrue("Give the class " + klassName + " a public constructor: public " + klassName + "(int age, int restingHeartRate)", cc.isPublic()); + cc.invoke(2, 5); + } + + @Test + public void testTargetHeartRate() throws Throwable { + assertTrue("The class " + klass + " should have the method public double targetHeartRate(double percentageOfMaximum). Now the method was not found.", klass.method("targetHeartRate").returning(double.class).taking(double.class).exists()); + } + + @Test + public void testTargetHeartRate1() throws Throwable { + testConstructor(); + testTargetHeartRate(); + + Reflex.MethodRef2 cc = klass.constructor().taking(int.class, int.class).withNiceError(); + assertTrue("Give the class " + klassName + " a public constructor: public " + klassName + "(int age, int restingHeartRate)", cc.isPublic()); + Object helper = cc.invoke(30, 60); + double target = klass.method("targetHeartRate").returning(double.class).taking(double.class).invokeOn(helper, 0.5); + + assertEquals("With age 30 and resting heart rate 60, the target heart rate should be about 122.485 when the target percentage is half of maximum.", 122.485, target, 0.1); + + target = klass.method("targetHeartRate").returning(double.class).taking(double.class).invokeOn(helper, 0.7); + assertEquals("With age 30 and resting heart rate 60, the target heart rate should be about 147.479 when the target percentage is 70% of maximum.", 147.479, target, 0.1); + } + + @Test + public void testTargetHeartRate2() throws Throwable { + testConstructor(); + testTargetHeartRate(); + + Reflex.MethodRef2 cc = klass.constructor().taking(int.class, int.class).withNiceError(); + assertTrue("Give the class " + klassName + " a public constructor: public " + klassName + "(int age, int restingHeartRate)", cc.isPublic()); + Object helper = cc.invoke(60, 70); + double targt = klass.method("targetHeartRate").returning(double.class).taking(double.class).invokeOn(helper, 0.6); + + + assertEquals("With age 60 and resting heart rate 70, the target heart rate should be about 126.184 when the target percentage is 60% of maximum.", 126.184, targt, 0.1); + + targt = klass.method("targetHeartRate").returning(double.class).taking(double.class).invokeOn(helper, 0.8); + + assertEquals("With age 60 and resting heart rate 70, the target heart rate should be about 144.912 when the target percentage is 80% of maximum.", 144.912, targt, 0.1); + } + + @Test + public void noExtraVariables() { + sanityCheck(); + } + + private void sanityCheck() throws SecurityException { + Field[] fields = ReflectionUtils.findClass(klassName).getDeclaredFields(); + + for (Field field : fields) { + assertFalse("you don't need \"static variables\", delete " + field(field.toString()), field.toString().contains("static") && !field.toString().contains("final")); + assertTrue("the visibility of all the object variables should be private, change " + field(field.toString()), field.toString().contains("private")); + } + + if (fields.length > 1) { + int var = 0; + for (Field field : fields) { + if (!field.toString().contains("final")) { + var++; + } + } + + assertTrue("the class " + klassName + " only needs object variables for age and resting heart rate. Delete the other variables", var < 3); + } + } + + private String field(String toString) { + return toString.replace(klassName + ".", ""); + } +} diff --git a/mooc-java-programming-i/part05-Part05_05.ConstructorOverload/.tmcproject.yml b/mooc-java-programming-i/part05-Part05_05.ConstructorOverload/.tmcproject.yml new file mode 100644 index 0000000..d2446da --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_05.ConstructorOverload/.tmcproject.yml @@ -0,0 +1 @@ +force_new_sandbox: true diff --git a/mooc-java-programming-i/part05-Part05_05.ConstructorOverload/pom.xml b/mooc-java-programming-i/part05-Part05_05.ConstructorOverload/pom.xml new file mode 100644 index 0000000..10837bd --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_05.ConstructorOverload/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + tkt + Part05_05.ConstructorOverload + Part05_05.ConstructorOverload + 1.0-SNAPSHOT + jar + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + fi.helsinki.cs.tmc + edu-test-utils + 0.4.2 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + diff --git a/mooc-java-programming-i/part05-Part05_05.ConstructorOverload/src/main/java/MainProgram.java b/mooc-java-programming-i/part05-Part05_05.ConstructorOverload/src/main/java/MainProgram.java new file mode 100644 index 0000000..6334a62 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_05.ConstructorOverload/src/main/java/MainProgram.java @@ -0,0 +1,7 @@ + +public class MainProgram { + + public static void main(String[] args) { + // Test your class here + } +} diff --git a/mooc-java-programming-i/part05-Part05_05.ConstructorOverload/src/main/java/Product.java b/mooc-java-programming-i/part05-Part05_05.ConstructorOverload/src/main/java/Product.java new file mode 100644 index 0000000..b27be14 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_05.ConstructorOverload/src/main/java/Product.java @@ -0,0 +1,31 @@ + +public class Product { + + private String name; + private String location; + private int weight; + + public Product(String name, String location, int weight) { + this.name = name; + this.location = location; + this.weight = weight; + } + + + public String getName() { + return name; + } + + public int getWeight() { + return weight; + } + + public String getLocation() { + return location; + } + + @Override + public String toString() { + return this.name + " (" + this.weight + " kg) can be found from the " + this.location; + } +} diff --git a/mooc-java-programming-i/part05-Part05_05.ConstructorOverload/src/test/java/ConstructorOverloadTest.java b/mooc-java-programming-i/part05-Part05_05.ConstructorOverload/src/test/java/ConstructorOverloadTest.java new file mode 100644 index 0000000..4379ba9 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_05.ConstructorOverload/src/test/java/ConstructorOverloadTest.java @@ -0,0 +1,59 @@ + +import fi.helsinki.cs.tmc.edutestutils.Points; +import fi.helsinki.cs.tmc.edutestutils.Reflex; +import static org.junit.Assert.*; +import org.junit.Test; + +@Points("05-05") +public class ConstructorOverloadTest { + + @Test + public void constructorWithName() throws Throwable { + Reflex.reflect(Product.class).ctor().taking(String.class).requirePublic(); + + Product e = Reflex.reflect(Product.class).ctor().taking(String.class).invoke("sausage"); + String errorMessage = "was not right. Try:\n" + + "Product p = new Product(\"sausage\");\n" + + "System.out.println(e.getName());\n" + + "System.out.println(e.getLocation());\n" + + "System.out.println(e.getWeight());"; + + assertEquals("Name " + errorMessage, "sausage", e.getName()); + assertEquals("Location " + errorMessage, "shelf", e.getLocation()); + assertEquals("Weight " + errorMessage, 1, e.getWeight()); + } + + @Test + public void constructorWithNameAndLocation() throws Throwable { + Reflex.reflect(Product.class).ctor().taking(String.class, String.class).requirePublic(); + + Product p = Reflex.reflect(Product.class).ctor().taking(String.class, String.class).invoke("sheep", "field"); + String errorMessage = "not correct. Try:\n" + + "Product p = new Product(\"sheep\", \"field\");\n" + + "System.out.println(p.getName());\n" + + "System.out.println(p.getLocation());\n" + + "System.out.println(p.getWeight());"; + + assertEquals("Name " + errorMessage, "sheep", p.getName()); + assertEquals("Location " + errorMessage, "field", p.getLocation()); + assertEquals("Weight " + errorMessage, 1, p.getWeight()); + } + + @Test + public void constructorWithNameAndWeight() throws Throwable { + Reflex.reflect(Product.class).ctor().taking(String.class, int.class).requirePublic(); + + Product e = Reflex.reflect(Product.class).ctor().taking(String.class, int.class).invoke("whale", 1000); + String errorMessage = "not correct. Try:\n" + + "Product p = new Product(\"whale\", 1000);\n" + + "System.out.println(p.getName());\n" + + "System.out.println(p.getLocation());\n" + + "System.out.println(p.getWeight());"; + + + assertEquals("Name " + errorMessage, "whale", e.getName()); + assertEquals("Location " + errorMessage, "shelf", e.getLocation()); + assertEquals("Weight " + errorMessage, 1000, e.getWeight()); + } + +} diff --git a/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/.tmcproject.yml b/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/.tmcproject.yml new file mode 100644 index 0000000..d2446da --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/.tmcproject.yml @@ -0,0 +1 @@ +force_new_sandbox: true diff --git a/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/pom.xml b/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/pom.xml new file mode 100644 index 0000000..a27377c --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + tkt + Part05_06.OverloadedCounter + Part05_06.OverloadedCounter + 1.0-SNAPSHOT + jar + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + fi.helsinki.cs.tmc + edu-test-utils + 0.4.2 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + diff --git a/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/src/main/java/MainProgram.java b/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/src/main/java/MainProgram.java new file mode 100644 index 0000000..5306e9e --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/src/main/java/MainProgram.java @@ -0,0 +1,7 @@ + +public class MainProgram { + + public static void main(String[] args) { + // Test your counter here + } +} diff --git a/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/src/test/java/ConstructorSignature.java b/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/src/test/java/ConstructorSignature.java new file mode 100644 index 0000000..d4a000f --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/src/test/java/ConstructorSignature.java @@ -0,0 +1,52 @@ + +import java.lang.reflect.Constructor; +import fi.helsinki.cs.tmc.edutestutils.ReflectionUtils; +import static org.junit.Assert.*; + +public class ConstructorSignature { + + public Class[] args; + + public ConstructorSignature(Class... args) { + this.args = args; + } + + public Constructor findIn(Class cl) { + try { + return ReflectionUtils.requireConstructor(cl, args); + } catch (AssertionError e) { + fail("Onhan luokalla " + cl.getSimpleName() + " konstruktori public " + toSignature(cl.getSimpleName()) + "?"); + return null; + } + } + + public String toSignature(String className) { + StringBuilder b = new StringBuilder(); + b.append(className).append("("); + for (Class c : args) { + b.append(c.getSimpleName()).append(", "); + } + if (args.length > 0) { + b.delete(b.length() - 2, b.length()); + } + b.append(")"); + return b.toString(); + } + + public Object invokeIn(Class cl, Object... args) { + + Constructor c = findIn(cl); + + try { + return ReflectionUtils.invokeConstructor(c, args); + } catch (AssertionError e) { + throw e; + } catch (Throwable t) { + throw new Error("Jokin meni pieleen kun kutsuttiin konstruktoria " + + toSignature(cl.getSimpleName()) + ":\n", + t); + } + + } + +} diff --git a/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/src/test/java/CounterTest.java b/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/src/test/java/CounterTest.java new file mode 100644 index 0000000..7ed49f2 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/src/test/java/CounterTest.java @@ -0,0 +1,189 @@ + +import fi.helsinki.cs.tmc.edutestutils.Points; +import static org.junit.Assert.*; +import org.junit.Before; +import org.junit.Test; + +public class CounterTest { + + String name = "Counter"; + + Class l; + + MethodSignature value = new MethodSignature(Integer.TYPE, "value"); + MethodSignature increase = new MethodSignature(Void.TYPE, "increase"); + MethodSignature decrease = new MethodSignature(Void.TYPE, "decrease"); + + MethodSignature increase2 = new MethodSignature(Void.TYPE, "increase", Integer.TYPE); + MethodSignature decrease2 = new MethodSignature(Void.TYPE, "decrease", Integer.TYPE); + + ConstructorSignature ci = new ConstructorSignature(Integer.TYPE); + ConstructorSignature c = new ConstructorSignature(); + + @Before + public void findClass() { + l = Utils.getClass(name); + } + + @Points("05-06.1") + @Test + public void testConstructors() { + ci.invokeIn(l, 10); + ci.invokeIn(l, 2); + } + + @Points("05-06.1") + @Test + public void testValue() { + + Object o = ci.invokeIn(l, 10); + Integer i = -9000; + i = (Integer) value.invokeIn(l, o); + assertEquals("Wrong value returned. Try:\nCounter c = new Counter(10);\nSystem.out.println(c.value());\n", + 10, (int) i); + + o = ci.invokeIn(l, 2); + i = (Integer) value.invokeIn(l, o); + assertEquals("Wrong value returned. Try:\nCounter c = new Counter(2);\nSystem.out.println(c.value());\n", + 2, (int) i); + + } + + @Points("05-06.1") + @Test + public void testIncrease() { + + Object o = ci.invokeIn(l, 5); + increase.invokeIn(l, o); + int i = (Integer) value.invokeIn(l, o); + assertEquals("Wrong value returned. Try:\nCounter c = new Counter(5);\nc.increase();\nSystem.out.println(c.value());\n", + 6, (int) i); + + increase.invokeIn(l, o); + i = (Integer) value.invokeIn(l, o); + assertEquals("Wrong value returned. Try:\nCounter c = new Counter(5);\nc.increase();\nc.increase();\nSystem.out.println(c.value());\n", + 7, (int) i); + + } + + @Points("05-06.1") + @Test + public void testDecrease() { + + Object o = ci.invokeIn(l, 900); + decrease.invokeIn(l, o); + int i = (Integer) value.invokeIn(l, o); + assertEquals("Wrong value returned. Try:\nCounter c = new Counter(900);\nc.decrease();\nSystem.out.println(c.value());\n", + 899, (int) i); + + decrease.invokeIn(l, o); + i = (Integer) value.invokeIn(l, o); + assertEquals("Wrong value returned. Try:\nCounter c = new Counter(900);\nc.decrease();\nc.decrease();\nSystem.out.println(c.value());\n", + 898, (int) i); + } + + @Points("05-06.1") + @Test + public void testDecreaseNoChecks() { + Object o = ci.invokeIn(l, 2); + decrease.invokeIn(l, o); + int i = (Integer) value.invokeIn(l, o); + assertEquals("Wrong value returned. Try:\nCounter c = new Counter(2);\nc.decrease();\nSystem.out.println(c.value());\n", + 1, (int) i); + + decrease.invokeIn(l, o); + i = (Integer) value.invokeIn(l, o); + assertEquals("Wrong value returned. Try:\nCounter c = new Counter(2);\nc.decrease();\nc.decrease();\nSystem.out.println(c.value());\n", + 0, (int) i); + + decrease.invokeIn(l, o); + i = (Integer) value.invokeIn(l, o); + assertEquals("Wrong value returned. Try:\nCounter c = new Counter(2);\nc.decrease();\nc.decrease();\nc.decrease();\nSystem.out.println(c.value());\n", + -1, (int) i); + + } + + @Points("05-06.1") + @Test + public void testConstructor() { + + Object o = ci.invokeIn(l, 11); + int i = (Integer) value.invokeIn(l, o); + assertEquals("Wrong value returned. Try:\nCounter c = new Counter(11);\nSystem.out.println(c.value());\n", + 11, i); + + o = c.invokeIn(l); + i = (Integer) value.invokeIn(l, o); + assertEquals("Wrong value returned. Try:\nCounter c = new Counter();\nSystem.out.println(c.value());\n", + 0, i); + + } + + @Points("05-06.2") + @Test + public void testIncreaseWithParameters() { + + Object o = ci.invokeIn(l, 5); + increase2.invokeIn(l, o, 2); + int i = (Integer) value.invokeIn(l, o); + assertEquals("Wrong value returned. Try:\nCounter c = new Counter(5);\nc.increase(2);\nSystem.out.println(c.value());\n", + 7, (int) i); + + increase2.invokeIn(l, o, 4); + i = (Integer) value.invokeIn(l, o); + assertEquals("Wrong value returned. Try:\n" + + "Counter c = new Counter(5);\nc.increase(2);\nc.increase(4);\nSystem.out.println(c.value());\n", + 11, (int) i); + } + + @Points("05-06.2") + @Test + public void testIncreaseWithNegativeParameter() { + + Object o = ci.invokeIn(l, 5); + increase2.invokeIn(l, o, -2); + int i = (Integer) value.invokeIn(l, o); + assertEquals("Increase method with a negative parameter should not change the value of the counter " + + "Try:\nCounter c = new Counter(5);\nc.increase(-2);\nSystem.out.println(c.value());\n", + 5, (int) i); + } + + @Points("05-06.2") + @Test + public void testDecreaseWithParameter() { + + Object o = ci.invokeIn(l, 900); + decrease2.invokeIn(l, o, 7); + int i = (Integer) value.invokeIn(l, o); + assertEquals("Wrong value returned. Try:\nCounter c = new Counter(900);\nc.decrease(7);\nSystem.out.println(c.value());\n", + 893, (int) i); + + decrease2.invokeIn(l, o, 3); + i = (Integer) value.invokeIn(l, o); + assertEquals("Wrong value returned. Try:\nCounter c = new Counter(900);\nc.decrease(7);\nc.decrease(3);\nSystem.out.println(c.value());\n", + 890, (int) i); + } + + @Points("05-06.2") + @Test + public void testDecreaseWithNegativeParameter() { + + Object o = ci.invokeIn(l, 900); + decrease2.invokeIn(l, o, -55); + int i = (Integer) value.invokeIn(l, o); + assertEquals("Decrease method with a negative parameter should not change the value of the counter " + + " Try:\nCounter c = new Counter(900);\nc.decrease(-55);\nSystem.out.println(c.value());\n", + 900, (int) i); + + } + + @Points("05-06.2") + @Test + public void testDecreaseWithParameterNoCheck() { + Object o = ci.invokeIn(l, 2); + decrease2.invokeIn(l, o, 5); + int i = (Integer) value.invokeIn(l, o); + assertEquals("Wrong value returned. Try:\nCounter c = new Counter(2);\nc.decrease(5);\nSystem.out.println(c.value());\n", + -3, (int) i); + } +} diff --git a/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/src/test/java/MethodSignature.java b/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/src/test/java/MethodSignature.java new file mode 100644 index 0000000..4ebccbe --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/src/test/java/MethodSignature.java @@ -0,0 +1,59 @@ + +import java.lang.reflect.Method; +import fi.helsinki.cs.tmc.edutestutils.ReflectionUtils; +import static org.junit.Assert.*; + +public class MethodSignature { + + public String name; + public Class retType; + public Class[] args; + + public MethodSignature(Class retType, String name, Class... args) { + this.retType = retType; + this.name = name; + this.args = args; + } + + public Method findIn(Class cl) { + Method m; + try { + m = ReflectionUtils.requireMethod(cl, name, args); + } catch (AssertionError e) { + fail("Does the class " + cl.getSimpleName() + " have the method public " + toSignature() + "?"); + return null; + } + + assertEquals("Make sure that class " + cl.getSimpleName() + " method " + + toSignature() + " return value is correct!", retType, m.getReturnType()); + return m; + + } + + public String toSignature() { + StringBuilder b = new StringBuilder(); + b.append(retType.getSimpleName()).append(" ").append(name).append("("); + for (Class c : args) { + b.append(c.getSimpleName()).append(", "); + } + if (args.length > 0) { + b.delete(b.length() - 2, b.length()); + } + b.append(")"); + return b.toString(); + } + + public Object invokeIn(Class cl, Object o, Object... args) { + Method m = findIn(cl); + + try { + return ReflectionUtils.invokeMethod(retType, m, o, args); + } catch (AssertionError e) { + throw e; + } catch (Throwable t) { + throw new Error("Something went wrong when calling the method " + toSignature() + ":", t); + } + + } + +} diff --git a/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/src/test/java/Utils.java b/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/src/test/java/Utils.java new file mode 100644 index 0000000..9098948 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_06.OverloadedCounter/src/test/java/Utils.java @@ -0,0 +1,15 @@ + +import static org.junit.Assert.*; +import fi.helsinki.cs.tmc.edutestutils.ReflectionUtils; + +public class Utils { + + public static Class getClass(String name) { + try { + return ReflectionUtils.findClass(name); + } catch (AssertionError e) { + fail("Have you created the class " + name + "?"); + return null; + } + } +} diff --git a/mooc-java-programming-i/part05-Part05_07.NullPointerException/.tmcproject.yml b/mooc-java-programming-i/part05-Part05_07.NullPointerException/.tmcproject.yml new file mode 100644 index 0000000..d2446da --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_07.NullPointerException/.tmcproject.yml @@ -0,0 +1 @@ +force_new_sandbox: true diff --git a/mooc-java-programming-i/part05-Part05_07.NullPointerException/pom.xml b/mooc-java-programming-i/part05-Part05_07.NullPointerException/pom.xml new file mode 100644 index 0000000..f6ae8f8 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_07.NullPointerException/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + tkt + Part05_07.NullPointerException + Part05_07.NullPointerException + 1.0-SNAPSHOT + jar + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + fi.helsinki.cs.tmc + edu-test-utils + 0.4.2 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + diff --git a/mooc-java-programming-i/part05-Part05_07.NullPointerException/src/main/java/NullPointerExceptionProgram.java b/mooc-java-programming-i/part05-Part05_07.NullPointerException/src/main/java/NullPointerExceptionProgram.java new file mode 100644 index 0000000..beb4c94 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_07.NullPointerException/src/main/java/NullPointerExceptionProgram.java @@ -0,0 +1,25 @@ + +import java.util.ArrayList; + +public class NullPointerExceptionProgram { + + public static void main(String[] args) { + // Implement a program, or modify a program so, that it causes + // the NullPointerException -error + + ArrayList lines = new ArrayList<>(); + lines.add("Never has a man influenced physics so profoundly as Niels Bohr in the early 1900's"); + lines.add("Going back to this time period, little was known about atomic structure; Bohr set out"); + lines.add("to end the obscurity of physics. However, things didn't come easy for Bohr. He had to"); + lines.add("give up most of his life for physics and research of many hypothesis. But, this is why"); + lines.add("you and I have even heard of the quantum theory and atomic structures. Bohr came"); + lines.add("up with his quantum theory while studying..."); + + int index = 0; + while (index < lines.size()) { + System.out.println(lines.get(index)); + index++; + } + + } +} diff --git a/mooc-java-programming-i/part05-Part05_07.NullPointerException/src/test/java/NPEErrorTest.java b/mooc-java-programming-i/part05-Part05_07.NullPointerException/src/test/java/NPEErrorTest.java new file mode 100644 index 0000000..c43262f --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_07.NullPointerException/src/test/java/NPEErrorTest.java @@ -0,0 +1,19 @@ + +import fi.helsinki.cs.tmc.edutestutils.Points; +import static org.junit.Assert.*; +import org.junit.Test; + +@Points("05-07") +public class NPEErrorTest { + + @Test + public void causesANullPointerExceptionError() { + try { + NullPointerExceptionProgram.main(new String[]{}); + } catch (NullPointerException e) { + return; + } + + fail("The program is supposed to cause a NullPointerException error, now it did not."); + } +} diff --git a/mooc-java-programming-i/part05-Part05_08.BiggestPetShop/.tmcproject.yml b/mooc-java-programming-i/part05-Part05_08.BiggestPetShop/.tmcproject.yml new file mode 100644 index 0000000..d2446da --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_08.BiggestPetShop/.tmcproject.yml @@ -0,0 +1 @@ +force_new_sandbox: true diff --git a/mooc-java-programming-i/part05-Part05_08.BiggestPetShop/pom.xml b/mooc-java-programming-i/part05-Part05_08.BiggestPetShop/pom.xml new file mode 100644 index 0000000..44da1a2 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_08.BiggestPetShop/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + tkt + Part05_08.BiggestPetShop + Part05_08.BiggestPetShop + 1.0-SNAPSHOT + jar + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + fi.helsinki.cs.tmc + edu-test-utils + 0.4.2 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + diff --git a/mooc-java-programming-i/part05-Part05_08.BiggestPetShop/src/main/java/MainProgram.java b/mooc-java-programming-i/part05-Part05_08.BiggestPetShop/src/main/java/MainProgram.java new file mode 100644 index 0000000..11f9b00 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_08.BiggestPetShop/src/main/java/MainProgram.java @@ -0,0 +1,14 @@ + +import java.util.Scanner; + +public class MainProgram { + + public static void main(String[] args) { + Scanner scan = new Scanner(System.in); + + Pet hulda = new Pet("Hulda", "Golden retriever"); + Person leo = new Person("Leo", hulda); + + System.out.println(leo); + } +} diff --git a/mooc-java-programming-i/part05-Part05_08.BiggestPetShop/src/main/java/Person.java b/mooc-java-programming-i/part05-Part05_08.BiggestPetShop/src/main/java/Person.java new file mode 100644 index 0000000..363cb2f --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_08.BiggestPetShop/src/main/java/Person.java @@ -0,0 +1,25 @@ + +public class Person { + + private String name; + private Pet pet; + + public Person(String name, Pet pet) { + this.name = name; + this.pet = pet; + } + + public Person(String name) { + this(name, new Pet("Toothless", "dragon")); + } + + public Person() { + this("Lilo", new Pet("Stitch", "blue alien")); + } + + @Override + public String toString() { + return this.nimi; + } + +} diff --git a/mooc-java-programming-i/part05-Part05_08.BiggestPetShop/src/main/java/Pet.java b/mooc-java-programming-i/part05-Part05_08.BiggestPetShop/src/main/java/Pet.java new file mode 100644 index 0000000..78a0fc6 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_08.BiggestPetShop/src/main/java/Pet.java @@ -0,0 +1,20 @@ + +public class Pet { + + private String name; + private String breed; + + public Pet(String name, String breed) { + this.name = name; + this.breed = breed; + } + + public String getName() { + return name; + } + + public String getBreed() { + return breed; + } + +} diff --git a/mooc-java-programming-i/part05-Part05_08.BiggestPetShop/src/test/java/TheBiggestPetShopTest.java b/mooc-java-programming-i/part05-Part05_08.BiggestPetShop/src/test/java/TheBiggestPetShopTest.java new file mode 100644 index 0000000..b757247 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_08.BiggestPetShop/src/test/java/TheBiggestPetShopTest.java @@ -0,0 +1,56 @@ + +import fi.helsinki.cs.tmc.edutestutils.MockStdio; +import fi.helsinki.cs.tmc.edutestutils.Points; +import fi.helsinki.cs.tmc.edutestutils.ReflectionUtils; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; +import org.junit.*; +import static org.junit.Assert.*; + +@Points("05-08") +public class TheBiggestPetShopTest { + + @Rule + public MockStdio io = new MockStdio(); + + @Test + public void test() { + Pet hulda = new Pet("Hulda", "chihuahua"); + Person leo = new Person("Leo", hulda); + + String out = io.getSysOut(); + String returnValueFromLeoToString = leo.toString(); + assertTrue("toString method should not print a string!", out.equals(io.getSysOut())); + + String errorMessage = "String returned by toString() should contain the name of the person, name of their pet and the breed of their pet.\n" + + "Try:\n" + + "Pet hulda = new Pet(\"Hulda\", \"chihuahua\");\n" + + "Person leo = new Person(\"Leo\", hulda);\n" + + "System.out.println(leo.toString());"; + assertTrue(errorMessage, returnValueFromLeoToString.contains("Leo")); + assertTrue(errorMessage, returnValueFromLeoToString.contains("Hulda")); + assertTrue(errorMessage, returnValueFromLeoToString.contains("chihuahua")); + } + + @Test + public void test2() { + Pet flounder = new Pet("Flounder", "fish"); + Person ariel = new Person("Ariel", flounder); + + String out = io.getSysOut(); + String arielToString = ariel.toString(); + assertTrue("toString method should not print a string!", out.equals(io.getSysOut())); + + String errorMessage = "String returned by toString() should contain the name of the person, name of their pet and the breed of their pet.\n" + + "Try:\n" + + "Pet flounder = new Pet(\"Flounder\", \"fish\");\n" + + "Person ariel = new Person(\"Ariel\", flounder);\n" + + "System.out.println(ariel.toString());"; + assertTrue(errorMessage, arielToString.contains("Ariel")); + assertTrue(errorMessage, arielToString.contains("Flounder")); + assertTrue(errorMessage, arielToString.contains("fish")); + } + +} diff --git a/mooc-java-programming-i/part05-Part05_09.HealthStation/.tmcproject.yml b/mooc-java-programming-i/part05-Part05_09.HealthStation/.tmcproject.yml new file mode 100644 index 0000000..d2446da --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_09.HealthStation/.tmcproject.yml @@ -0,0 +1 @@ +force_new_sandbox: true diff --git a/mooc-java-programming-i/part05-Part05_09.HealthStation/pom.xml b/mooc-java-programming-i/part05-Part05_09.HealthStation/pom.xml new file mode 100644 index 0000000..d02562a --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_09.HealthStation/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + tkt + Part05_09.HealthStation + Part05_09.HealthStation + 1.0-SNAPSHOT + jar + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + fi.helsinki.cs.tmc + edu-test-utils + 0.4.2 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + diff --git a/mooc-java-programming-i/part05-Part05_09.HealthStation/src/main/java/HealthStation.java b/mooc-java-programming-i/part05-Part05_09.HealthStation/src/main/java/HealthStation.java new file mode 100644 index 0000000..58658cc --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_09.HealthStation/src/main/java/HealthStation.java @@ -0,0 +1,10 @@ + +public class HealthStation { + + + public int weigh(Person person) { + // return the weight of the person passed as the parameter + return -1; + } + +} diff --git a/mooc-java-programming-i/part05-Part05_09.HealthStation/src/main/java/Main.java b/mooc-java-programming-i/part05-Part05_09.HealthStation/src/main/java/Main.java new file mode 100644 index 0000000..c5ad6e8 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_09.HealthStation/src/main/java/Main.java @@ -0,0 +1,7 @@ + +public class Main { + + public static void main(String[] args) { + // write experimental code here to check how your program functions + } +} diff --git a/mooc-java-programming-i/part05-Part05_09.HealthStation/src/main/java/Person.java b/mooc-java-programming-i/part05-Part05_09.HealthStation/src/main/java/Person.java new file mode 100644 index 0000000..8fbaf47 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_09.HealthStation/src/main/java/Person.java @@ -0,0 +1,65 @@ +/* + * Do not change the behavior of this class + */ + +public class Person { + + private String name; + private int age; + private int height; + private int weight; + + public Person(String name, int age, int height, int weight) { + this.name = name; + this.age = age; + this.height = height; + this.weight = weight; + } + + public void printPerson() { + System.out.println("My name is " + this.name + " and I am " + this.age + " years old"); + } + + public void growOlder() { + this.age++; + } + + public boolean isOfLegalAge() { + if (this.age > 17) { + return true; + } + + return false; + } + + public void setHeight(int height) { + this.height = height; + } + + public int getHeight() { + return this.height; + } + + public int getWeight() { + return this.weight; + } + + public void setWeight(int weight) { + this.weight = weight; + } + + public double bmi() { + double heightInMeters = this.height / 100.0; + + return this.weight / (heightInMeters * heightInMeters); + } + + public String getName() { + return this.name; + } + + @Override + public String toString() { + return "My name is " + this.name + " and I am " + this.age + " years old. My BMI is " + this.bmi(); + } +} diff --git a/mooc-java-programming-i/part05-Part05_09.HealthStation/src/test/java/HealthStationTest.java b/mooc-java-programming-i/part05-Part05_09.HealthStation/src/test/java/HealthStationTest.java new file mode 100644 index 0000000..8c29948 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_09.HealthStation/src/test/java/HealthStationTest.java @@ -0,0 +1,225 @@ + +import fi.helsinki.cs.tmc.edutestutils.Points; +import fi.helsinki.cs.tmc.edutestutils.ReflectionUtils; +import fi.helsinki.cs.tmc.edutestutils.Reflex; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Random; +import org.junit.*; +import static org.junit.Assert.*; + +public class HealthStationTest { + + HealthStation station; + Person peter; + Random rand = new Random(); + + Reflex.ClassRef klass; + String klassName = "HealthStation"; + + @Before + public void findClass() { + klass = Reflex.reflect(klassName); + } + + @Before + public void setUp() { + station = new HealthStation(); + peter = new Person("Peter", 33, 175, 78); + } + + @Points("05-09.1") + @Test + public void noExtraVariables1() { + sanityCheck(); + } + + @Test + @Points("05-09.1") + public void canWeigh() { + assertEquals("check the code: station = HealthStation(); " + + "p = new Person(\"Peter\", 33, 175, 78); " + + "System.out.println( station.weigh(p) )", peter.getWeight(), station.weigh(peter)); + + for (int i = 0; i < 5; i++) { + int weight = 60 + rand.nextInt(60); + Person ethan = new Person("Ethan", 45, 181, weight); + + assertEquals("check the code: station = HealthStation(); " + + "p = new Person(\"Ethan\", 45, 181, " + weight + "); " + + "System.out.println( station.weigh(p) )", ethan.getWeight(), station.weigh(ethan)); + } + } + + @Points("05-09.2") + @Test + public void noExtraVariables2() { + sanityCheck(); + } + + @Points("05-09.2") + @Test + public void aMethodCalledFeedExists() throws Throwable { + String method = "feed"; + + Person p = new Person("Peter", 20, 175, 85); + HealthStation s = new HealthStation(); + + assertTrue("implement a method public void " + method + "(Person p) for the class " + klassName, + klass.method(s, method).returningVoid().taking(Person.class).isPublic()); + + String e = "\nThe code that caused the error " + + "s = new HealthStation; p = new Person(\"Peter\", 20, 175, 85); s.weigh(p);"; + + klass.method(s, method).returningVoid().taking(Person.class).withNiceError(e).invoke(p); + } + + @Test + @Points("05-09.2") + public void canFeed() { + int expected = peter.getWeight() + 1; + feed(station, peter); + + assertEquals("Feeding should increase the weight of the person by one kilo. Check the code: \n" + + "station = HealthStation(); " + + "p = new Person(\"Peter\", 33, 175, 78); " + + "station.feed(p); " + + "System.out.println( p.getPaino() )", + expected, peter.getWeight()); + + assertEquals("Feeding should increase the weight of the person by one kilo. Check the code: \n" + + "station = HealthStation(); " + + "p = new Person(\"Peter\", 33, 175, 78); " + + "station.feed(p); " + + "System.out.println( station.weigh(p) )", + expected, station.weigh(peter)); + + feed(station, peter); + feed(station, peter); + feed(station, peter); + feed(station, peter); + + assertEquals("Feeding should increase the weight of the person by one kilo. Check the code: \n" + + "station = HealthStation(); " + + "peter = new Person(\"Peter\", 33, 175, 78); " + + "station.feed(peter); " + + "station.feed(peter); " + + "station.feed(peter); " + + "station.feed(peter); " + + "station.feed(peter); " + + "System.out.println( peter.getPaino() )", + expected + 4, peter.getWeight()); + } + + @Points("05-09.3") + @Test + public void noExtraVariables3() { + sanityCheck(); + } + + @Test + @Points("05-09.3") + public void aMethodCalledWeighingsExists() throws Throwable { + String method = "weighings"; + + HealthStation s = new HealthStation(); + + assertTrue("implement a method public int " + method + "() for the class " + klassName, + klass.method(s, method).returning(int.class).takingNoParams().isPublic()); + + String e = "\nThe code that caused the error: " + + "s = new HealthStation; s.weighings();"; + + klass.method(s, method).returning(int.class).takingNoParams().withNiceError(e).invoke(); + } + + @Test + @Points("05-09.3") + public void numberOfWeighingsInMemory() { + assertEquals("Does the method weighings() work as intended? Initially no one has been weighed! Try out the code " + + "station = HealthStation(); " + + "System.out.println( station.weighings() )", + 0, weighings(station)); + + station.weigh(peter); + assertEquals("Does the method weighings() work as intended? The method should tell how many times the method weigh() has been called " + + "Try out the code\n" + + "station = HealthStation(); " + + "p1 = new Person(\"Peter\", 33, 175, 78); " + + "station.weigh(p1);" + + "System.out.println( station.weighings() )", + 1, weighings(station)); + + Person ethan = new Person("Ethan", 0, 52, 4); + station.weigh(ethan); + assertEquals("Does the method weighings() work as intended? The method should tell how many times the method weigh() has been called " + + "Try out the code\n" + + "station = HealthStation(); " + + "p1 = new Person(\"Peter\", 33, 175, 78); " + + "p2 = new Person(\"Ethan\", 0, 52, 4); " + + "station.weigh(p1);" + + "station.weigh(p2);" + + "System.out.println( station.weighings() )", + 2, weighings(station)); + + station.weigh(ethan); + station.weigh(peter); + station.weigh(peter); + assertEquals("Does the method weighings() work as intended? The method should tell how many times the method weigh() has been called " + + "Try out the code\n" + + "station = HealthStation(); " + + "p1 = new Person(\"Peter\", 33, 175, 78); " + + "p2 = new Person(\"Ethan\", 0, 52, 4); " + + "station.weigh(p1);" + + "station.weigh(p2);" + + "station.weigh(p2);" + + "station.weigh(p1);" + + "station.weigh(p1);" + + "System.out.println( station.weighings() )", + 5, weighings(station)); + } + + String nameOfTheClass = "HealthStation"; + + private void feed(Object station, Person hlo) { + try { + Method feed = ReflectionUtils.requireMethod(HealthStation.class, "feed", Person.class); + ReflectionUtils.invokeMethod(void.class, feed, station, hlo); + } catch (Throwable t) { + } + } + + private int weighings(Object station) { + try { + Method weighings = ReflectionUtils.requireMethod(HealthStation.class, "weighings"); + return ReflectionUtils.invokeMethod(int.class, weighings, station); + } catch (Throwable t) { + } + return -1; + } + + private void sanityCheck() throws SecurityException { + String nameOfTheClass = "HealthStation"; + + Field[] fields = ReflectionUtils.findClass(nameOfTheClass).getDeclaredFields(); + + for (Field field : fields) { + assertFalse("you don't need \"static variables\", delete " + fieldName(field.toString()), field.toString().contains("static") && !field.toString().contains("final")); + assertTrue("visibility of every object variable of the class must be private, change " + fieldName(field.toString()), field.toString().contains("private")); + } + + if (fields.length > 1) { + int var = 0; + for (Field field : fields) { + if (!field.toString().contains("final")) { + var++; + } + } + assertTrue("The class " + nameOfTheClass + " only need the object variable that remembers the number of weighings. Delete unnecessary variables.", var < 2); + } + } + + private String fieldName(String toString) { + return toString.replace(nameOfTheClass + ".", ""); + } +} diff --git a/mooc-java-programming-i/part05-Part05_10.CardPayments/.tmcproject.yml b/mooc-java-programming-i/part05-Part05_10.CardPayments/.tmcproject.yml new file mode 100644 index 0000000..d2446da --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_10.CardPayments/.tmcproject.yml @@ -0,0 +1 @@ +force_new_sandbox: true diff --git a/mooc-java-programming-i/part05-Part05_10.CardPayments/pom.xml b/mooc-java-programming-i/part05-Part05_10.CardPayments/pom.xml new file mode 100644 index 0000000..38ac08c --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_10.CardPayments/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + tkt + Part05_10.CardPayments + Part05_10.CardPayments + 1.0-SNAPSHOT + jar + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + fi.helsinki.cs.tmc + edu-test-utils + 0.4.2 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + diff --git a/mooc-java-programming-i/part05-Part05_10.CardPayments/src/main/java/Main.java b/mooc-java-programming-i/part05-Part05_10.CardPayments/src/main/java/Main.java new file mode 100644 index 0000000..02466bd --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_10.CardPayments/src/main/java/Main.java @@ -0,0 +1,8 @@ + +public class Main { + + public static void main(String[] args) { + // write experimental main programs here + } +} + diff --git a/mooc-java-programming-i/part05-Part05_10.CardPayments/src/main/java/PaymentCard.java b/mooc-java-programming-i/part05-Part05_10.CardPayments/src/main/java/PaymentCard.java new file mode 100644 index 0000000..c10f29c --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_10.CardPayments/src/main/java/PaymentCard.java @@ -0,0 +1,24 @@ + +public class PaymentCard { + + private double balance; + + public PaymentCard(double balance) { + this.balance = balance; + } + + public double balance() { + return this.balance; + } + + public void addMoney(double increase) { + this.balance += increase; + } + + public boolean takeMoney(double amount) { + // implement the method so that it only takes money from the card if + // the balance is at least the amount parameter. + // returns true if successful and false otherwise + return false; + } +} diff --git a/mooc-java-programming-i/part05-Part05_10.CardPayments/src/main/java/PaymentTerminal.java b/mooc-java-programming-i/part05-Part05_10.CardPayments/src/main/java/PaymentTerminal.java new file mode 100644 index 0000000..670499e --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_10.CardPayments/src/main/java/PaymentTerminal.java @@ -0,0 +1,33 @@ + +public class PaymentTerminal { + + + private double money; // amount of cash + private int affordableMeals; // number of sold affordable meals + private int heartyMeals; // number of sold hearty meals + + + public PaymentTerminal() { + // register initially has 1000 euros of money + } + + public double eatAffordably(double payment) { + // an affordable meal costs 2.50 euros + // increase the amount of cash by the price of an affordable mean and return the change + // if the payment parameter is not large enough, no meal is sold and the method should return the whole payment + return -1; + } + + public double eatHeartily(double payment) { + // a hearty meal costs 4.30 euros + // increase the amount of cash by the price of a hearty mean and return the change + // if the payment parameter is not large enough, no meal is sold and the method should return the whole payment + return -1; + } + + + @Override + public String toString() { + return "money: " + money + ", number of sold affordable meals: " + affordableMeals + ", number of sold hearty meals: " + heartyMeals; + } +} diff --git a/mooc-java-programming-i/part05-Part05_10.CardPayments/src/test/java/CardPaymentsTest.java b/mooc-java-programming-i/part05-Part05_10.CardPayments/src/test/java/CardPaymentsTest.java new file mode 100644 index 0000000..41af055 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_10.CardPayments/src/test/java/CardPaymentsTest.java @@ -0,0 +1,472 @@ + +import fi.helsinki.cs.tmc.edutestutils.Points; +import fi.helsinki.cs.tmc.edutestutils.ReflectionUtils; +import fi.helsinki.cs.tmc.edutestutils.Reflex; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Random; +import org.junit.*; +import static org.junit.Assert.*; + +public class CardPaymentsTest { + + PaymentCard card; + PaymentTerminal terminal; + + @Before + public void setUp() { + card = new PaymentCard(10); + terminal = new PaymentTerminal(); + } + Reflex.ClassRef klassL; + String klassNameL = "PaymentCard"; + Reflex.ClassRef klassK; + String klassNameK = "PaymentTerminal"; + + @Before + public void findClass() { + klassL = Reflex.reflect(klassNameL); + klassK = Reflex.reflect(klassNameK); + } + + @Points("05-10.1") + @Test + public void notTooManyObjectVariablesForCard() { + sanityCheck("PaymentCard", 1, "Don't add new object variables to the PaymentCard class, they are unnecessary."); + } + + @Points("05-10.1") + @Test + public void canTakeMoneyFromCardIfBalanceIsEnough() { + assertEquals("If the balance on the card is sufficient, then the takeMoney method should return true. Check the code: \n" + + "t = new PaymentCard(10); t.takeMoney(8);", true, card.takeMoney(8)); + assertEquals("The balance on the card should decrease when money is taken. Check the code: " + + "t = new PaymentCard(10); t.takeMoney(8);", 2, card.balance(), 0.01); + } + + @Points("05-10.1") + @Test + public void canEmptyCard() { + assertEquals("One should be able to take all the money from the card. Check the code: " + + "t = new PaymentCard(10); t.takeMoney(10);", true, card.takeMoney(10)); + assertEquals("One should be able to take all the money from the card. Check the code: " + + "t = new PaymentCard(10); t.takeMoney(10);", 0, card.balance(), 0.01); + } + + /* + * + */ + @Points("05-10.2") + @Test + public void notTooManyObjectVariablesForTerminal1() { + sanityCheck("PaymentTerminal", 3, "Don't add new object variables to the PaymentTerminal class, they are unnecessary."); + } + + @Points("05-10.2") + @Test + public void initialMoneyInPaymentTerminal1000() { + assertTrue("When the payment terminal is created the object varaible tracking the amount of money should get the value 1000. By printing the object we should see that the amount of money is 1000. \n" + + "Currently the output is: \"" + terminal + "\"", terminal.toString().contains("money: 1000")); + } + + @Points("05-10.2") + @Test + public void initialMoney1000AndNoSoldLunches() { + String odotettu = "money: 1000.0, number of sold affordable meals: 0, number of sold hearty meals: 0"; + assertEquals("When the payment terminal is created the amount of money should be 1000 and sold meals should be 0, ", odotettu, terminal.toString()); + } + + @Points("05-10.2") + @Test + public void successfulAffordable() { + double change = terminal.eatAffordably(4); + + String error = "When buying an affordable meal using 4 euros in cash (calling terminal.eatAffordably(4) "; + assertEquals(error + "the method should return the correct amount of change.", 1.5, change, 0.01); + + assertTrue(error + " the money in the payment terminal should increase by 2.5 euros, i.e. the amount should be 1002.5. \nThe current state is: " + terminal, terminal.toString().contains("money: 1002.5")); + + assertTrue(error + " the amount of affordable meals sold should be 1. \n" + + "The current state is: " + terminal, terminal.toString().contains("affordable meals: 1")); + assertTrue(error + " the amount of hearty meals sold should still be 0. The current state is: " + terminal, terminal.toString().contains("hearty meals: 0")); + } + + @Points("05-10.2") + @Test + public void successfulHearty() { + double change = terminal.eatHeartily(5); + + String error = "When buying a hearty meal using 5 euros in cash (calling terminal.eatHeartily(5)) "; + assertEquals(error + "the method should return the correct amount of change.", 0.7, change, 0.01); + + assertTrue(error + "the money in the payment terminal should increase by 4.3 euros, i.e. the amount should be 1004.3. \nThe current state is: " + terminal, terminal.toString().contains("money: 1004.3") || terminal.toString().contains("money: 1004.299")); + + assertTrue(error + " the amount of hearty meals sold should be 1. The current state is: " + terminal, terminal.toString().contains("hearty meals: 1")); + assertTrue(error + " the amount of affordable meals sold should still be 0. The current state is: " + terminal, terminal.toString().contains("affordable meals: 0")); + } + + @Points("05-10.2") + @Test + public void successfulExactChangeAffordable() { + double change = terminal.eatAffordably(2.5); + + String error = "When buying an affordable meal using 2.5 euros in cash (calling terminal.eatAffordably(2.5)) "; + assertEquals(error + "all the money should be used up, i.e. the change should be 0.", 0, change, 0.01); + + assertTrue(error + " the money in the payment terminal should increase by 2.5, i.e. the amount should be 1002.5. The current state is: " + terminal, terminal.toString().contains("money: 1002.5")); + + assertTrue(error + " the amount of affordable meals sold should be 1. The current state is: " + terminal, terminal.toString().contains("affordable meals: 1")); + } + + @Points("05-10.2") + @Test + public void successfulExactChangeHearty() { + double change = terminal.eatHeartily(4.3); + + String virhe = "When buying a hearty meal using 4.3 euros in cash (calling terminal.eatHeartily(4.3)) "; + assertEquals(virhe + "all the money should be used up, i.e. the change should be 0.", 0, change, 0.01); + + assertTrue(virhe + " the money in the payment terminal should increase by 4.3, i.e. the amount should be 1004.3. The current state is: " + terminal, terminal.toString().contains("money: 1004.3") || terminal.toString().contains("money: 1004.299")); + + assertTrue(virhe + " the amount of hearty meals sold should be 1. \n" + + "The current state is: " + terminal, terminal.toString().contains("hearty meals: 1")); + } + + @Points("05-10.2") + @Test + public void multipleSold() { + terminal.eatHeartily(5); + terminal.eatAffordably(3); + terminal.eatHeartily(5); + terminal.eatHeartily(10); + terminal.eatAffordably(4); + + String virhe = "After executing the operations terminal.eatHeartily(5); terminal.eatAffordably(3); terminal.eatHeartily(5);" + + "terminal.eatHeartily(10); terminal.eatAffordably(4);"; + assertTrue(virhe + " the amount of money in the payment terminal should be 1017.9 euros. The current state is: " + terminal, terminal.toString().contains("money: 1017.899") || terminal.toString().contains("money: 1017.9")); + assertTrue(virhe + " the amount of hearty meals sold should be 3. The current state is: " + terminal, terminal.toString().contains("hearty meals: 3")); + assertTrue(virhe + " the amount of affordable meals sold should be 2. The current state is: " + terminal, terminal.toString().contains("affordable meals: 2")); + + } + + @Points("05-10.2") + @Test + public void ifNoMoneyTheSaleFailsAndTerminalUntouched() { + double change = terminal.eatAffordably(2); + + assertEquals("When trying to buy something using insufficient funds, e.g. terminal.eatAffordably(2), then the whole amount should be returned as change", 2, change, 0.01); + + String expected = "money: 1000.0, number of sold affordable meals: 0, number of sold hearty meals: 0"; + assertEquals("When trying to buy an affordable meal from an empty terminal using insufficient funds, " + + "the contents of the payment terminal should remain unchanged. The output should be: ", expected, terminal.toString()); + + change = terminal.eatHeartily(2); + assertEquals("When trying to buy something using insufficient funds, e.g. terminal.eatHeartily(2), then the whole amount should be returned as change", 2, change, 0.01); + + expected = "money: 1000.0, number of sold affordable meals: 0, number of sold hearty meals: 0"; + assertEquals("When trying to buy a hearty meal from an empty terminal using insufficient funds, " + + "the contents of the payment terminal should remain unchanged. The output should be: ", expected, terminal.toString()); + } + + /* + * + */ + @Points("05-10.3") + @Test + public void notTooManyObjectVariablesForTerminal2() { + sanityCheck("PaymentTerminal", 3, "Don't add new object variables to the PaymentCard class, they are unnecessary."); + } + + @Points("05-10.3") + @Test + public void methodForCardPurchaseAffordableExists() throws Throwable { + String method = "eatAffordably"; + + PaymentTerminal t = new PaymentTerminal(); + + assertTrue("implement a method public boolean " + method + "(PaymentCard card) for the class " + klassNameK, + klassK.method(t, method).returning(boolean.class).taking(PaymentCard.class).isPublic()); + + String e = "\nThe code that caused the error " + + "t = new PaymentTerminal(); ac = new PaymentCard(10); t." + method + "(ac);"; + + PaymentCard ac = new PaymentCard(10); + + klassK.method(t, method).returning(boolean.class).taking(PaymentCard.class).withNiceError(e).invoke(ac); + } + + @Points("05-10.3") + @Test + public void canBuyAffordableWithCardIfFundsSufficient() { + String scen = "terminal = new PaymentTerminal(); card = new PaymentCard(10); terminal.eatAffordably(card);"; + Boolean ok = eatAffordably(terminal, card); + + assertEquals("Buying an affordable meal using a card should be possible as long as the funds are sufficient. Check the following:\n" + scen, true, ok); + + assertEquals("The balance on the card should decrease by the price of one affordable meal. Check the code:\n" + + scen + " card.balance();\n", 7.5, card.balance(), 0.01); + + String expected = "money: 1000.0, number of sold affordable meals: 1, number of sold hearty meals: 0"; + assertEquals("When buying an affordable meal from an empty terminal using a card, the money in the payment terminal should remain unchanged and" + + " the amount of affordable meals sold should be 1.\n", expected, terminal.toString()); + } + + @Points("05-10.3") + @Test + public void canBuyAffordableWithCardIfFundsBarelySufficient() { + String scen = "terminal = new PaymentTerminal(); card = new PaymentCard(2.5); terminal.eatAffordably(card);"; + card = new PaymentCard(2.5); + Boolean ok = eatAffordably(terminal, card); + + assertEquals("Buying an affordable meal using a card should be possible if the balance on the card is exactly same as the price of the meal. Check the following:\n" + scen + "\n", true, ok); + + assertEquals("The balance on the card should drop to zero if we buy an affordable meal when the balance is exactly the price of that meal. Check the code:\n" + + scen + " card.balance();\n", 0, card.balance(), 0.01); + + String expected = "money: 1000.0, number of sold affordable meals: 1, number of sold hearty meals: 0"; + assertEquals("When buying an affordable meal from an empty terminal using a card, the money in the payment terminal should remain unchanged and" + + " the amount of affordable meals sold should be 1.", expected, terminal.toString()); + } + + @Points("05-10.3") + @Test + public void cannotBuyAffordableWithCardIfInsufficientFunds() { + String scen = "terminal = new PaymentTerminal(); card = new PaymentCard(2); terminal.eatAffordably(card);"; + card = new PaymentCard(2); + Boolean ok = eatAffordably(terminal, card); + + assertEquals("Should not be able to make a purchase using a card with insufficient funds. Check the following:\n" + + scen + "\n", false, ok); + + assertEquals("The balance on the card should remain unchanged if the funds are insufficient for the purchase. Check the code:\n" + + scen + " card.balance();\n", 2, card.balance(), 0.01); + + String expected = "money: 1000.0, number of sold affordable meals: 0, number of sold hearty meals: 0"; + assertEquals("When buying something from an empty terminal using a card with insufficient funds, the state of the terminal should remain unchanged.", + expected, terminal.toString()); + } + + @Points("05-10.3") + @Test + public void methodForCardPurchaseHeartyExists() throws Throwable { + String method = "eatHeartily"; + + PaymentTerminal t = new PaymentTerminal(); + + assertTrue("implement a method public boolean " + method + "(PaymentCard card) for the class " + klassNameK, + klassK.method(t, method).returning(boolean.class).taking(PaymentCard.class).isPublic()); + + String v = "\nThe code that caused the error " + + "t = new PaymentTerminal(); ac = new PaymentCard(10); t." + method + "(ac);"; + + PaymentCard ac = new PaymentCard(10); + + klassK.method(t, method).returning(boolean.class).taking(PaymentCard.class).withNiceError(v).invoke(ac); + } + + @Points("05-10.3") + @Test + public void canBuyHeartyWithCardIfFundsSufficient() { + String scen = "terminal = new PaymentTerminal(); card = new PaymentCard(10); terminal.eatHeartily(card);"; + Boolean ok = eatHeartily(terminal, card); + + assertEquals("Buying a hearty meal using a card should be possible as long as the funds are sufficient. Check the following: " + scen + " " + + "\n", true, ok); + + assertEquals("The balance on the card should decrease by the price of one hearty meal. \n" + + "Check the code " + + scen + " card.balance();\n", 5.7, card.balance(), 0.01); + + String expected = "money: 1000.0, number of sold affordable meals: 0, number of sold hearty meals: 1"; + assertEquals("When buying a hearty meal from an empty terminal using a card, the money in the payment terminal should remain unchanged and" + + " the amount of hearty meals sold should be 1.\n", expected, terminal.toString()); + } + + @Points("05-10.3") + @Test + public void canBuyHeartyWithCardIfFundsBarelySufficient() { + String scen = "terminal = new PaymentTerminal(); card = new PaymentCard(4.3);"; + card = new PaymentCard(4.3); + Boolean ok = eatHeartily(terminal, card); + + assertEquals("Buying a hearty meal using a card should be possible if the balance on the card is exactly same as the price of the meal. Check the following: " + scen + + "\n", true, ok); + + assertEquals("The balance on the card should drop to zero if we buy a hearty meal when the balance is exactly the price of that meal. Check the code " + + scen + " card.balance();\n", 0, card.balance(), 0.01); + + String expected = "money: 1000.0, number of sold affordable meals: 0, number of sold hearty meals: 1"; + assertEquals("When buying a hearty meal from an empty terminal using a card, the money in the payment terminal should remain unchanged and" + + " the amount of hearty meals sold should be 1. ", expected, terminal.toString()); + } + + @Points("05-10.3") + @Test + public void cannotBuyHeartyWithCardIfInsufficientFunds() { + String scen = "terminal = new PaymentTerminal(); card = new PaymentCard(4.1);"; + card = new PaymentCard(4.1); + Boolean ok = eatHeartily(terminal, card); + + assertEquals("Should not be able to make a purchase using a card with insufficient funds. Check the following:\n" + + scen + "\n", false, ok); + + assertEquals("The balance on the card should remain unchanged if the funds are insufficient for the purchase. Check the code:\n" + + scen + " card.balance();\n", 4.1, card.balance(), 0.01); + + String expected = "money: 1000.0, number of sold affordable meals: 0, number of sold hearty meals: 0"; + assertEquals("When buying something from an empty terminal using a card with insufficient funds, the state of the terminal should remain unchanged.", + expected, terminal.toString()); + } + + /* + * + */ + @Points("05-10.4") + @Test + public void notTooManyObjectVariablesForTerminal3() { + sanityCheck("PaymentTerminal", 3, "Don't add new object variables to the PaymentCard class, they are unnecessary."); + } + + @Points("05-10.4") + @Test + public void methodForAddingMoneyToCardExists() throws Throwable { + String method = "addMoneyToCard"; + + PaymentTerminal t = new PaymentTerminal(); + + assertTrue("implement a method public void " + method + "(PaymentCard card, double summa) for the class " + klassNameK, + klassK.method(t, method).returningVoid().taking(PaymentCard.class, double.class).isPublic()); + + String v = "\nThe code that caused the error " + + "t = new PaymentTerminal(); ac = new PaymentCard(10); t." + method + "(ac, 5);"; + + PaymentCard ac = new PaymentCard(10); + + klassK.method(t, method).returningVoid().taking(PaymentCard.class, double.class).withNiceError(v).invoke(ac, 5.0); + } + + @Points("05-10.4") + @Test + public void addingMoneyIncreasesTheBalanceOnTheCard() { + addMoneyToCard(terminal, card, 10); + String error = "Does adding money work? Check the code:\n" + + "terminal = new PaymentTerminal(); card = new PaymentCard(10); terminal.addMoneyToCard(card, 10); card.balance()"; + assertEquals(error, 20, card.balance(), 0.01); + + String expected = "money: 1010.0, number of sold affordable meals: 0, number of sold hearty meals: 0"; + assertEquals("When adding money to a card, the amount of money added to the card is put into the terminal. " + + "Initially the payment terminal contains 1000. When we add 10 euros to the card," + + " the output of the terminal should be: \n", expected, terminal.toString()); + + } + + @Points("05-10.4") + @Test + public void addingNegativeAmountDoesNotChangeCardBalance() { + addMoneyToCard(terminal, card, -10); + String error = "Adding a negative amount should neither change the balance on the card nor the money in the terminal! Check the code:\n" + + "terminal = new PaymentTerminal(); card = new PaymentCard(10); terminal.addMoneyToCard(card, -10); card.balance()"; + assertEquals(error, 10, card.balance(), 0.01); + + String expected = "money: 1000.0, number of sold affordable meals: 0, number of sold hearty meals: 0"; + assertEquals("Adding a negative amount should neither change the balance on the card nor the money in the terminal!" + + "Initially the payment terminal contains 1000. When we add -10 euros to the card," + + " the output of the terminal should be: \n", expected, terminal.toString()); + + } + + @Points("05-10.4") + @Test + public void addingMoneyMultipleTimesWorks() { + Random rand = new Random(); + int addedMoneyTotal = 0; + int[] addedMoney = new int[5]; + for (int i = 0; i < addedMoney.length; i++) { + int toAdd = 1 + rand.nextInt(20); + addedMoney[i] = toAdd; + addedMoneyTotal += toAdd; + addMoneyToCard(terminal, card, toAdd); + } + + String mj = ""; + for (int l : addedMoney) { + mj += l + " "; + } + + String error = "Does adding money work? check the balance on the card when you consecutively add the amounts " + mj + " to the card"; + assertEquals(error, 10 + addedMoneyTotal, card.balance(), 0.01); + + double exp = 1000 + addedMoneyTotal; + String expected = "money: " + exp + ", number of sold affordable meals: 0, number of sold hearty meals: 0"; + assertEquals("When adding money to a card, the amount of money added to the card is put into the terminal. " + + "Initially the payment terminal contains 1000. When we consecutively add the amounts " + mj + " to the card," + + " the output of the terminal should be: ", expected, terminal.toString()); + + } + /* + * + */ + + private void addMoneyToCard(Object terminal, Object card, double amount) { + String methodName = "addMoneyToCard"; + try { + Method method = ReflectionUtils.requireMethod(PaymentTerminal.class, methodName, PaymentCard.class, double.class); + ReflectionUtils.invokeMethod(void.class, method, terminal, card, amount); + } catch (Throwable t) { + t.printStackTrace(); + fail("implement a method public boolean addMoneyToCard(PaymentCard card, double summa) for the class PaymentTerminal"); + } + } + + private boolean eatAffordably(Object terminal, Object card) { + String methodName = "eatAffordably"; + try { + Method method = ReflectionUtils.requireMethod(PaymentTerminal.class, methodName, PaymentCard.class); + return ReflectionUtils.invokeMethod(boolean.class, method, terminal, card); + } catch (Throwable t) { + t.printStackTrace(); + fail("implement a method public boolean eatAffordably(PaymentCard card) for the class PaymentTerminal"); + } + return false; + } + + private boolean eatHeartily(Object terminal, Object card) { + String methodName = "eatHeartily"; + try { + Method method = ReflectionUtils.requireMethod(PaymentTerminal.class, methodName, PaymentCard.class); + return ReflectionUtils.invokeMethod(boolean.class, method, terminal, card); + } catch (Throwable t) { + t.printStackTrace(); + fail("implement a method public boolean eatHeartily(PaymentCard card) for the class PaymentTerminal"); + } + return false; + } + + private void sanityCheck(String className, int variable, String msg) throws SecurityException { + + Field[] fields = ReflectionUtils.findClass(className).getDeclaredFields(); + + String viesti = ", NB: if you wish to store the price of a meal into an object variable, do the following: " + + " private static final double AFFORDABLE_PRICE = 2.5; "; + + for (Field field : fields) { + assertFalse("you don't need \"static variables\", remove " + fieldName(field.toString()) + viesti, field.toString().contains("static") && !field.toString().contains("final")); + assertTrue("the visibility of all object variables for the class should be private, change " + fieldName(field.toString()) + viesti, + field.toString().contains("private")); + } + + if (fields.length > 1) { + int var = 0; + for (Field field : fields) { + if (!field.toString().contains("final")) { + var++; + } + } + assertTrue(msg + viesti, var <= variable); + } + } + + private String fieldName(String toString) { + return toString.replace("PaymentCard" + ".", ""); + } +} diff --git a/mooc-java-programming-i/part05-Part05_11.ComparingApartments/.tmcproject.yml b/mooc-java-programming-i/part05-Part05_11.ComparingApartments/.tmcproject.yml new file mode 100644 index 0000000..d2446da --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_11.ComparingApartments/.tmcproject.yml @@ -0,0 +1 @@ +force_new_sandbox: true diff --git a/mooc-java-programming-i/part05-Part05_11.ComparingApartments/pom.xml b/mooc-java-programming-i/part05-Part05_11.ComparingApartments/pom.xml new file mode 100644 index 0000000..95062da --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_11.ComparingApartments/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + tkt + Part05_11.ComparingApartments + Part05_11.ComparingApartments + 1.0-SNAPSHOT + jar + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + fi.helsinki.cs.tmc + edu-test-utils + 0.4.2 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + diff --git a/mooc-java-programming-i/part05-Part05_11.ComparingApartments/src/main/java/Apartment.java b/mooc-java-programming-i/part05-Part05_11.ComparingApartments/src/main/java/Apartment.java new file mode 100644 index 0000000..05e9aa5 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_11.ComparingApartments/src/main/java/Apartment.java @@ -0,0 +1,14 @@ + +public class Apartment { + + private int rooms; + private int squares; + private int princePerSquare; + + public Apartment(int rooms, int squares, int pricePerSquare) { + this.rooms = rooms; + this.squares = squares; + this.princePerSquare = pricePerSquare; + } + +} diff --git a/mooc-java-programming-i/part05-Part05_11.ComparingApartments/src/main/java/Main.java b/mooc-java-programming-i/part05-Part05_11.ComparingApartments/src/main/java/Main.java new file mode 100644 index 0000000..dd46575 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_11.ComparingApartments/src/main/java/Main.java @@ -0,0 +1,11 @@ + +public class Main { + + public static void main(String[] args) { + // you can write code here to try out your program + Apartment manhattanStudioApt = new Apartment(1, 16, 5500); + Apartment atlantaTwoBedroomApt = new Apartment(2, 38, 4200); + Apartment bangorThreeBedroomApt = new Apartment(3, 78, 2500); + + } +} diff --git a/mooc-java-programming-i/part05-Part05_11.ComparingApartments/src/test/java/ApartmentTest.java b/mooc-java-programming-i/part05-Part05_11.ComparingApartments/src/test/java/ApartmentTest.java new file mode 100644 index 0000000..39ffbae --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_11.ComparingApartments/src/test/java/ApartmentTest.java @@ -0,0 +1,161 @@ + +import fi.helsinki.cs.tmc.edutestutils.Points; +import fi.helsinki.cs.tmc.edutestutils.Reflex; +import org.junit.Test; +import static org.junit.Assert.*; +import org.junit.Before; + +public class ApartmentTest { + + Reflex.ClassRef klass; + String klassName = "Apartment"; + + @Before + public void findClass() { + klass = Reflex.reflect(klassName); + } + + @Points("05-11.1") + @Test + public void methodLargerThanExist() throws Throwable { + String method = "largerThan"; + + Apartment o = new Apartment(1, 20, 1000); + Apartment o2 = new Apartment(2, 30, 2000); + + assertTrue("implement a method public boolean " + method + "(Apartment verrattava) for the class " + klassName, klass.method(o, method) + .returning(boolean.class).taking(Apartment.class).isPublic()); + + String e = "\nThe code that caused the error: Apartment a = new Apartment(1, 20, 1000); Apartment b = new Apartment(2, 30, 100); " + + "a.largerThan(b)"; + + klass.method(o, method) + .returning(boolean.class).taking(Apartment.class).withNiceError(e).invoke(o2); + + } + + @Points("05-11.1") + @Test + public void largerThanWorks1() throws Throwable { + String method = "largerThan"; + + Apartment a1 = new Apartment(1, 20, 1000); + Apartment a2 = new Apartment(2, 30, 2000); + Apartment a3 = new Apartment(2, 25, 1500); + + assertEquals("Apartment a1 = new Apartment(1,20,1000); Apartment a2 = new Apartment(2,30,2000); Apartment a3 = new Apartment(2, 23, 1500);\n" + + "a1.largerThan(a2)", + false, klass.method(a1, method).returning(boolean.class).taking(Apartment.class).invoke(a2)); + assertEquals("Apartment a1 = new Apartment(1,20,1000); Apartment a2 = new Apartment(2,30,2000); Apartment a3 = new Apartment(2, 23, 1500);\n" + + "a2.largerThan(a1)", + true, klass.method(a2, method).returning(boolean.class).taking(Apartment.class).invoke(a1)); + assertEquals("Apartment a1 = new Apartment(1,20,1000); Apartment a2 = new Apartment(2,30,2000); Apartment a3 = new Apartment(2, 23, 1500);\n" + + "a2.largerThan(a3)", + true, klass.method(a2, method).returning(boolean.class).taking(Apartment.class).invoke(a3)); + assertEquals("Apartment a1 = new Apartment(1,20,1000); Apartment a2 = new Apartment(2,30,2000); Apartment a3 = new Apartment(2, 23, 1500);\n" + + "a3.largerThan(a2)", + false, klass.method(a3, method).returning(boolean.class).taking(Apartment.class).invoke(a2)); + assertEquals("Apartment a1 = new Apartment(1,20,1000); Apartment a2 = new Apartment(2,30,2000); Apartment a3 = new Apartment(2, 23, 1500);\n" + + "a1.largerThan(a3)", + false, klass.method(a1, method).returning(boolean.class).taking(Apartment.class).invoke(a3)); + assertEquals("Apartment a1 = new Apartment(1,20,1000); Apartment a2 = new Apartment(2,30,2000); Apartment a3 = new Apartment(2, 23, 1500);\n" + + "a3.largerThan(a1)", + true, klass.method(a3, method).returning(boolean.class).taking(Apartment.class).invoke(a1)); + } + + @Points("05-11.2") + @Test + public void methodPriceDifferenceExists() throws Throwable { + String method = "priceDifference"; + + Apartment o = new Apartment(1, 20, 1000); + Apartment o2 = new Apartment(2, 30, 2000); + + assertTrue("implement a method public int " + method + "(Apartment verrattava) for the class " + klassName, klass.method(o, method) + .returning(int.class).taking(Apartment.class).isPublic()); + + String e = "\nThe code that caused the error: Apartment a = new Apartment(1, 20, 1000); Apartment b = new Apartment(2, 30, 100); " + + "a.priceDifference(b)"; + + klass.method(o, method) + .returning(int.class).taking(Apartment.class).withNiceError(e).invoke(o2); + } + + @Points("05-11.2") + @Test + public void priceDifferenceWorks1() throws Throwable { + String method = "priceDifference"; + + Apartment a1 = new Apartment(1, 20, 1000); + Apartment a2 = new Apartment(2, 30, 2000); + Apartment a3 = new Apartment(2, 25, 1500); + + int res = klass.method(a1, method).returning(int.class).taking(Apartment.class).invoke(a2); + assertEquals("Apartment a1 = new Apartment(1,20,1000); Apartment a2 = new Apartment(2,30,2000); Apartment a3 = new Apartment(2, 23, 1500);\n" + + "a1.priceDifference(a2)", 40000, res); + + res = klass.method(a2, method).returning(int.class).taking(Apartment.class).invoke(a1); + assertEquals("Apartment a1 = new Apartment(1,20,1000); Apartment a2 = new Apartment(2,30,2000); Apartment a3 = new Apartment(2, 23, 1500);\n" + + "a2.priceDifference(a1)",40000, res); + res = klass.method(a2, method).returning(int.class).taking(Apartment.class).invoke(a3); + assertEquals("Apartment a1 = new Apartment(1,20,1000); Apartment a2 = new Apartment(2,30,2000); Apartment a3 = new Apartment(2, 23, 1500);\n" + + "a2.priceDifference(a3)",22500, res); + res = klass.method(a3, method).returning(int.class).taking(Apartment.class).invoke(a2); + assertEquals("Apartment a1 = new Apartment(1,20,1000); Apartment a2 = new Apartment(2,30,2000); Apartment a3 = new Apartment(2, 23, 1500);\n" + + "a3.priceDifference(a2)", 22500, res); + res = klass.method(a1, method).returning(int.class).taking(Apartment.class).invoke(a3); + assertEquals("Apartment a1 = new Apartment(1,20,1000); Apartment a2 = new Apartment(2,30,2000); Apartment a3 = new Apartment(2, 23, 1500);\n" + + "a1.priceDifference(a3)",17500, res); + res = klass.method(a3, method).returning(int.class).taking(Apartment.class).invoke(a1); + assertEquals("Apartment a1 = new Apartment(1,20,1000); Apartment a2 = new Apartment(2,30,2000); Apartment a3 = new Apartment(2, 23, 1500);\n" + + "a3.priceDifference(a1)", 17500, res); + } + + @Points("05-11.3") + @Test + public void methodMoreExpensiveThanExists() throws Throwable { + String method = "moreExpensiveThan"; + + Apartment o = new Apartment(1, 20, 1000); + Apartment o2 = new Apartment(2, 30, 2000); + + assertTrue("implement a method public boolean " + method + "(Apartment verrattava) for the class " + klassName, klass.method(o, method) + .returning(boolean.class).taking(Apartment.class).isPublic()); + + String v = "\nThe code that caused the error: Apartment a = new Apartment(1, 20, 1000); Apartment b = new Apartment(2, 30, 100); " + + "a.moreExpensiveThan(b)"; + + klass.method(o, method) + .returning(boolean.class).taking(Apartment.class).withNiceError(v).invoke(o2); + + } + + @Points("05-11.3") + @Test + public void moreExpensiveThanWorks1() throws Throwable { + String method = "moreExpensiveThan"; + + Apartment a1 = new Apartment(1, 20, 1000); + Apartment a2 = new Apartment(2, 30, 2000); + Apartment a3 = new Apartment(2, 25, 1500); + + assertEquals("Apartment a1 = new Apartment(1,20,1000); Apartment a2 = new Apartment(2,30,2000); Apartment a3 = new Apartment(2, 23, 1500);\n" + + "a1.moreExpensiveThan(a2)", + false, klass.method(a1, method).returning(boolean.class).taking(Apartment.class).invoke(a2)); + assertEquals("Apartment a1 = new Apartment(1,20,1000); Apartment a2 = new Apartment(2,30,2000); Apartment a3 = new Apartment(2, 23, 1500);\n" + + "a2.moreExpensiveThan(a1)", + true, klass.method(a2, method).returning(boolean.class).taking(Apartment.class).invoke(a1)); + assertEquals("Apartment a1 = new Apartment(1,20,1000); Apartment a2 = new Apartment(2,30,2000); Apartment a3 = new Apartment(2, 23, 1500);\n" + + "a2.moreExpensiveThan(a3)", + true, klass.method(a2, method).returning(boolean.class).taking(Apartment.class).invoke(a3)); + assertEquals("Apartment a1 = new Apartment(1,20,1000); Apartment a2 = new Apartment(2,30,2000); Apartment a3 = new Apartment(2, 23, 1500);\n" + + "a3.moreExpensiveThan(a2)", + false, klass.method(a3, method).returning(boolean.class).taking(Apartment.class).invoke(a2)); + assertEquals("Apartment a1 = new Apartment(1,20,1000); Apartment a2 = new Apartment(2,30,2000); Apartment a3 = new Apartment(2, 23, 1500);\n" + + "a1.moreExpensiveThan(a3)", + false, klass.method(a1, method).returning(boolean.class).taking(Apartment.class).invoke(a3)); + assertEquals("Apartment a1 = new Apartment(1,20,1000); Apartment a2 = new Apartment(2,30,2000); Apartment a3 = new Apartment(2, 23, 1500);\n" + + "a3.moreExpensiveThan(a1)", + true, klass.method(a3, method).returning(boolean.class).taking(Apartment.class).invoke(a1)); + } +} diff --git a/mooc-java-programming-i/part05-Part05_12.Song/.tmcproject.yml b/mooc-java-programming-i/part05-Part05_12.Song/.tmcproject.yml new file mode 100644 index 0000000..d2446da --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_12.Song/.tmcproject.yml @@ -0,0 +1 @@ +force_new_sandbox: true diff --git a/mooc-java-programming-i/part05-Part05_12.Song/pom.xml b/mooc-java-programming-i/part05-Part05_12.Song/pom.xml new file mode 100644 index 0000000..55583c6 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_12.Song/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + tkt + Part05_12.Song + Part05_12.Song + 1.0-SNAPSHOT + jar + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + fi.helsinki.cs.tmc + edu-test-utils + 0.4.2 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + diff --git a/mooc-java-programming-i/part05-Part05_12.Song/src/main/java/Main.java b/mooc-java-programming-i/part05-Part05_12.Song/src/main/java/Main.java new file mode 100644 index 0000000..cf0cdf4 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_12.Song/src/main/java/Main.java @@ -0,0 +1,18 @@ + +public class Main { + + public static void main(String[] args) { + // you can write code here for testing your program + + Song jackSparrow = new Song("The Lonely Island", "Jack Sparrow", 196); + Song anotherSparrow = new Song("The Lonely Island", "Jack Sparrow", 196); + + if (jackSparrow.equals(anotherSparrow)) { + System.out.println("Songs are equal."); + } + + if (jackSparrow.equals("Another object")) { + System.out.println("Strange things are afoot."); + } + } +} diff --git a/mooc-java-programming-i/part05-Part05_12.Song/src/main/java/Song.java b/mooc-java-programming-i/part05-Part05_12.Song/src/main/java/Song.java new file mode 100644 index 0000000..b32d7fb --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_12.Song/src/main/java/Song.java @@ -0,0 +1,20 @@ + +public class Song { + + private String artist; + private String name; + private int durationInSeconds; + + public Song(String artist, String name, int durationInSeconds) { + this.artist = artist; + this.name = name; + this.durationInSeconds = durationInSeconds; + } + + @Override + public String toString() { + return this.artist + ": " + this.name + " (" + this.durationInSeconds + " s)"; + } + + +} diff --git a/mooc-java-programming-i/part05-Part05_12.Song/src/test/java/SongTest.java b/mooc-java-programming-i/part05-Part05_12.Song/src/test/java/SongTest.java new file mode 100644 index 0000000..a6f6786 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_12.Song/src/test/java/SongTest.java @@ -0,0 +1,48 @@ + +import fi.helsinki.cs.tmc.edutestutils.Points; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; +import org.junit.Test; + +@Points("05-12") +public class SongTest { + + @Test + public void comparisonWorks1() throws Throwable { + Song song1 = new Song("The Lonely Island", "Jack Sparrow", 196); + Song song2 = new Song("The Lonely Island", "Jack Sparrow", 196); + + assertEquals("Try the program:\n" + + "Song song1 = new Song(\"The Lonely Island\", \"Jack Sparrow\", 196);\n" + + "Song song2 = new Song(\"The Lonely Island\", \"Jack Sparrow\", 196);\n" + + "if(song1.equals(song2)) {\n" + + " System.out.println(\"Same!\");\n" + + "}\n", song1, song2); + } + + @Test + public void comparisonWorks2() throws Throwable { + Song song1 = new Song("Ismo Leikola", "Pendolino", 194); + Song song2 = new Song("Ismo Leikola", "Pendolino", 194); + + assertEquals("Try the program:\n" + + "Song song1 = new Song(\"Ismo Leikola\", \"Pendolino\", 194);\n" + + "Song song2 = new Song(\"Ismo Leikola\", \"Pendolino\", 194);\n" + + "if(song1.equals(song2)) {\n" + + " System.out.println(\"Same!\");\n" + + "}\n", song1, song2); + } + + @Test + public void comparisonWorks3() throws Throwable { + Song song1 = new Song("The Lonely Island", "Jack Sparrow", 196); + Song song2 = new Song("Ismo Leikola", "Pendolino", 194); + + assertNotSame("Try the program:\n" + + "Song song1 = new Song(\"The Lonely Island\", \"Jack Sparrow\", 196);\n" + + "Song song2 = new Song(\"Ismo Leikola\", \"Pendolino\", 194);\n" + + "if(song1.equals(song2)) {\n" + + " System.out.println(\"Same!\");\n" + + "}\n", song1, song2); + } +} diff --git a/mooc-java-programming-i/part05-Part05_13.IdenticalTwins/.tmcproject.yml b/mooc-java-programming-i/part05-Part05_13.IdenticalTwins/.tmcproject.yml new file mode 100644 index 0000000..d2446da --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_13.IdenticalTwins/.tmcproject.yml @@ -0,0 +1 @@ +force_new_sandbox: true diff --git a/mooc-java-programming-i/part05-Part05_13.IdenticalTwins/pom.xml b/mooc-java-programming-i/part05-Part05_13.IdenticalTwins/pom.xml new file mode 100644 index 0000000..3887d5e --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_13.IdenticalTwins/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + tkt + Part05_13.IdenticalTwins + Part05_13.IdenticalTwins + 1.0-SNAPSHOT + jar + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + fi.helsinki.cs.tmc + edu-test-utils + 0.4.2 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + diff --git a/mooc-java-programming-i/part05-Part05_13.IdenticalTwins/src/main/java/Main.java b/mooc-java-programming-i/part05-Part05_13.IdenticalTwins/src/main/java/Main.java new file mode 100644 index 0000000..6a35bb6 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_13.IdenticalTwins/src/main/java/Main.java @@ -0,0 +1,9 @@ + +public class Main { + + public static void main(String[] args) { + // you can write code here to try out your program + + + } +} diff --git a/mooc-java-programming-i/part05-Part05_13.IdenticalTwins/src/main/java/Person.java b/mooc-java-programming-i/part05-Part05_13.IdenticalTwins/src/main/java/Person.java new file mode 100644 index 0000000..aacc39d --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_13.IdenticalTwins/src/main/java/Person.java @@ -0,0 +1,19 @@ + +import java.util.Objects; + +public class Person { + + private String name; + private SimpleDate birthday; + private int height; + private int weight; + + public Person(String name, SimpleDate birthday, int height, int weight) { + this.name = name; + this.birthday = birthday; + this.height = height; + this.weight = weight; + } + + // implement an equals method here for checking the equality of objects +} diff --git a/mooc-java-programming-i/part05-Part05_13.IdenticalTwins/src/main/java/SimpleDate.java b/mooc-java-programming-i/part05-Part05_13.IdenticalTwins/src/main/java/SimpleDate.java new file mode 100644 index 0000000..d9afec2 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_13.IdenticalTwins/src/main/java/SimpleDate.java @@ -0,0 +1,55 @@ + +public class SimpleDate { + + private int day; + private int month; + private int year; + + public SimpleDate(int day, int month, int year) { + this.day = day; + this.month = month; + this.year = year; + } + + public int getDay() { + return this.day; + } + + public int getMonth() { + return this.month; + } + + public int getYear() { + return this.year; + } + + public boolean equals(Object compared) { + // if the variables are located in the same place, they are the same. + if (this == compared) { + return true; + } + + // if the object is not instance of SimpleDate, the objects are not the same + if (!(compared instanceof SimpleDate)) { + return false; + } + + // let's cast the object to SimpleDate + SimpleDate otherDate = (SimpleDate) compared; + + // if the object's values are the same, the objects are the same + if (this.day == otherDate.day + && this.month == otherDate.month + && this.year == otherDate.year) { + return true; + } + + // other wise, the objects are not the same + return false; + } + + @Override + public String toString() { + return this.day + "." + this.month + "." + this.year; + } +} diff --git a/mooc-java-programming-i/part05-Part05_13.IdenticalTwins/src/test/java/IdenticalTwinsTest.java b/mooc-java-programming-i/part05-Part05_13.IdenticalTwins/src/test/java/IdenticalTwinsTest.java new file mode 100644 index 0000000..983c12a --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_13.IdenticalTwins/src/test/java/IdenticalTwinsTest.java @@ -0,0 +1,86 @@ + +import fi.helsinki.cs.tmc.edutestutils.Points; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import org.junit.Test; + +@Points("05-13") +public class IdenticalTwinsTest { + + @Test + public void test1() throws Throwable { + Person first = new Person("Leevi", new SimpleDate(1, 1, 2017), 70, 10); + Person second = new Person("Leevi", new SimpleDate(1, 1, 2017), 70, 10); + + assertEquals("After two calls\nnew Person(\"Leevi\", new SimpleDate(1, 1, 2017), 70, 10);\n the created person should be the same.\nTry:\n" + + "Person first = new Person(\"Leevi\", new SimpleDate(1, 1, 2017), 70, 10);\n" + + "Person second = new Person(\"Leevi\", new SimpleDate(1, 1, 2017), 70, 10);\n" + + "System.out.println(first.equals(second));", first, second); + } + + @Test + public void test2() throws Throwable { + Person first = new Person("Leevi", new SimpleDate(1, 1, 2017), 70, 10); + Person second = new Person("Leena", new SimpleDate(1, 1, 2017), 70, 10); + + assertFalse("Two persons with a different name should not be the same. Try:\n" + + "Henkilo eka = new Henkilo(\"Leevi\", new Paivays(1, 1, 2017), 70, 10);\n" + + "Henkilo toka = new Henkilo(\"Leena\", new Paivays(1, 1, 2017), 70, 10);\n" + + "System.out.println(first.equals(second));", first.equals(second)); + } + + @Test + public void test3() throws Throwable { + Person first = new Person("Leevi", new SimpleDate(1, 1, 2017), 70, 10); + Person second = new Person("Leevi", new SimpleDate(2, 1, 2017), 70, 10); + + assertFalse("Two persons with a same name but a different birthday should be the same. Try:\n" + + "Person first = new Person(\"Leevi\", new SimpleDate(1, 1, 2017), 70, 10);\n" + + "Person second = new Person(\"Leevi\", new SimpleDate(2, 1, 2017), 70, 10);\n" + + "System.out.println(first.equals(second));", first.equals(second)); + } + + @Test + public void test4() throws Throwable { + Person first = new Person("Leevi", new SimpleDate(1, 1, 2017), 70, 10); + Person second = new Person("Leevi", new SimpleDate(1, 2, 2017), 70, 10); + + assertFalse("Two persons with a same name but different month of birth should not be the same. Try:\n" + + "Person first = new Person(\"Leevi\", new SimpleDate(1, 1, 2017), 70, 10);\n" + + "Person second = new Person(\"Leevi\", new SimpleDate(1, 2, 2017), 70, 10);\n" + + "System.out.println(first.equals(second));", first.equals(second)); + } + + @Test + public void test5() throws Throwable { + Person first = new Person("Leevi", new SimpleDate(1, 1, 2017), 70, 10); + Person second = new Person("Leevi", new SimpleDate(1, 1, 2018), 70, 10); + + assertFalse("Two persons with same name but different year of birth should not be the same. Try:\n" + + "Person first = new Person(\"Leevi\", new SimpleDate(1, 1, 2017), 70, 10);\n" + + "Person second = new Person(\"Leevi\", new SimpleDate(1, 1, 2018), 70, 10);\n" + + "System.out.println(first.equals(second));", first.equals(second)); + } + + @Test + public void test6() throws Throwable { + Person first = new Person("Leevi", new SimpleDate(1, 1, 2017), 70, 10); + Person second = new Person("Leevi", new SimpleDate(1, 1, 2017), 71, 10); + + assertFalse("Two persons with different heights should not be the same. Try:\n" + + "Person first = new Person(\"Leevi\", new SimpleDate(1, 1, 2017), 70, 10);\n" + + "Person second = new Person(\"Leevi\", new SimpleDate(1, 1, 2017), 71, 10);\n" + + "System.out.println(first.equals(second));", first.equals(second)); + } + + @Test + public void test7() throws Throwable { + Person first = new Person("Leevi", new SimpleDate(1, 1, 2017), 70, 10); + Person second = new Person("Leevi", new SimpleDate(1, 1, 2017), 70, 11); + + assertFalse("Two persons with different weight should not be the same. Try:\n" + + "Person first = new Person(\"Leevi\", new SimpleDate(1, 1, 2017), 70, 10);\n" + + "Person second = new Person(\"Leevi\", new SimpleDate(1, 1, 2017), 70, 11);\n" + + "System.out.println(first.equals(second));", first.equals(second)); + } +} diff --git a/mooc-java-programming-i/part05-Part05_14.Books/.tmcproject.yml b/mooc-java-programming-i/part05-Part05_14.Books/.tmcproject.yml new file mode 100644 index 0000000..d2446da --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_14.Books/.tmcproject.yml @@ -0,0 +1 @@ +force_new_sandbox: true diff --git a/mooc-java-programming-i/part05-Part05_14.Books/pom.xml b/mooc-java-programming-i/part05-Part05_14.Books/pom.xml new file mode 100644 index 0000000..0be1eaa --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_14.Books/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + tkt + Part05_14.Books + Part05_14.Books + 1.0-SNAPSHOT + jar + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + fi.helsinki.cs.tmc + edu-test-utils + 0.4.2 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + diff --git a/mooc-java-programming-i/part05-Part05_14.Books/src/main/java/Book.java b/mooc-java-programming-i/part05-Part05_14.Books/src/main/java/Book.java new file mode 100644 index 0000000..e95a416 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_14.Books/src/main/java/Book.java @@ -0,0 +1,20 @@ + +public class Book { + + private String name; + private int publicationYear; + + public Book(String name, int publicationYear) { + this.name = name; + this.publicationYear = publicationYear; + } + + public String getName() { + return name; + } + + public int getPublicationYear() { + return publicationYear; + } + +} diff --git a/mooc-java-programming-i/part05-Part05_14.Books/src/main/java/Main.java b/mooc-java-programming-i/part05-Part05_14.Books/src/main/java/Main.java new file mode 100644 index 0000000..075dc6b --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_14.Books/src/main/java/Main.java @@ -0,0 +1,28 @@ + +import java.util.ArrayList; +import java.util.Scanner; + +public class Main { + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + ArrayList books = new ArrayList<>(); + + while (true) { + System.out.println("Name (empty will stop):"); + String name = scanner.nextLine(); + if (name.isEmpty()) { + break; + } + + System.out.println("Publication year:"); + int publicationYear = Integer.valueOf(scanner.nextLine()); + Book book = new Book(name, publicationYear); + books.add(book); + + } + + // NB! Don't alter the line below! + System.out.println("Thank you! Books added: " + books.size()); + } +} diff --git a/mooc-java-programming-i/part05-Part05_14.Books/src/test/java/BooksTest.java b/mooc-java-programming-i/part05-Part05_14.Books/src/test/java/BooksTest.java new file mode 100644 index 0000000..b2485b3 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_14.Books/src/test/java/BooksTest.java @@ -0,0 +1,70 @@ + +import fi.helsinki.cs.tmc.edutestutils.MockStdio; +import fi.helsinki.cs.tmc.edutestutils.Points; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import org.junit.Rule; +import org.junit.Test; + +public class BooksTest { + + @Rule + public MockStdio io = new MockStdio(); + + @Points("05-14") + @Test + public void addingSameBookTwice() { + test("book\n1990\nbook\n1990\n\n", 1); + } + + @Points("05-14") + @Test + public void addingSameBookThrice() { + test("abc\n1991\nabc\n1991\nabc\n1991\n\n", 1); + } + + @Points("05-14") + @Test + public void sameNamesDifferentYears() { + test("alphabet book\n2017\nalphabet book\n2018\n\n", 2); + } + + @Points("05-14") + @Test + public void differentNamesSameYears() { + test("alphabet book\n2018\nbetabet book\n2018\n\n", 2); + } + + @Points("05-14") + @Test + public void test1() { + test("book1\n2018\nbook2\n2018\nbook3\n2015\nbook4\n2015\nbook4\n2015\nbook5\n2018\nbook5\n2018\n\n", 5); + } + + private void test(String input, int expectedNumOfBooks) { + io.setSysIn(input); + + try { + Main.main(new String[]{}); + } catch (Throwable t) { + fail("Failed to execute the program."); + } + + String out = io.getSysOut(); + + for (int i = 0; i < 10; i++) { + if (expectedNumOfBooks == i) { + continue; + } + + assertFalse("The number of books was not what was expected. Try your program with the input:\n" + input, + out.contains("Thank you! Books added: " + i)); + } + + String expected = "Thank you! Books added: " + expectedNumOfBooks; + assertTrue("Expected the output to contain the string:\n\"" + expected + + "\"\nThis was not the case. Try the program with the input:\n" + input, out.contains(expected)); + } + +} diff --git a/mooc-java-programming-i/part05-Part05_15.Archive/.tmcproject.yml b/mooc-java-programming-i/part05-Part05_15.Archive/.tmcproject.yml new file mode 100644 index 0000000..d2446da --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_15.Archive/.tmcproject.yml @@ -0,0 +1 @@ +force_new_sandbox: true diff --git a/mooc-java-programming-i/part05-Part05_15.Archive/pom.xml b/mooc-java-programming-i/part05-Part05_15.Archive/pom.xml new file mode 100644 index 0000000..8d24d4c --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_15.Archive/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + tkt + Part05_15.Archive + Part05_15.Archive + 1.0-SNAPSHOT + jar + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + fi.helsinki.cs.tmc + edu-test-utils + 0.4.2 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + diff --git a/mooc-java-programming-i/part05-Part05_15.Archive/src/main/java/Main.java b/mooc-java-programming-i/part05-Part05_15.Archive/src/main/java/Main.java new file mode 100644 index 0000000..5d38933 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_15.Archive/src/main/java/Main.java @@ -0,0 +1,12 @@ + +import java.util.ArrayList; +import java.util.Scanner; + +public class Main { + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + + + } +} diff --git a/mooc-java-programming-i/part05-Part05_15.Archive/src/test/java/ArchiveTest.java b/mooc-java-programming-i/part05-Part05_15.Archive/src/test/java/ArchiveTest.java new file mode 100644 index 0000000..e8b62f5 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_15.Archive/src/test/java/ArchiveTest.java @@ -0,0 +1,81 @@ + +import fi.helsinki.cs.tmc.edutestutils.MockStdio; +import fi.helsinki.cs.tmc.edutestutils.Points; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import static org.junit.Assert.fail; +import org.junit.Rule; +import org.junit.Test; + +public class ArchiveTest { + + @Rule + public MockStdio io = new MockStdio(); + + @Points("05-15.1") + @Test + public void addingAndPrintingOneItem() { + test("identifier\nitem5\n\n", "identifier: item5"); + } + + @Points("05-15.1") + @Test + public void addingAndPrintingTwoItems() { + test("identifier\nitem\nsecond\nsecondItem\n\n", "identifier: item", "second: secondItem"); + } + + @Points("05-15.1") + @Test + public void readingStoppedWithEmptyName() { + test("identifier\nitem3\nsecond\n\n", "identifier: item3"); + } + + @Points("05-15.2") + @Test + public void printingTwoEqualItemsOnlyPrintsOneItem() { + test("identifier\nitem2\nidentifier\nitem2\n\n", "identifier: item2"); + } + + @Points("05-15.2") + @Test + public void printingTwoItemsWithDifferentNamesButSameIdentifiersOnlyContainsOneItem() { + test("identifier\nitem1\nidentifier\nitem2\n\n", "identifier: item1"); + } + + @Points("05-15.2") + @Test + public void printingTwoItemsWithSameNamesButDifferentIdentifiersContainsTwoItems() { + test("identifier1\nitem\nidentifier2\nitem\n\n", "identifier1: item", "identifier2: item"); + } + + private void test(String input, String... expectedOutput) { + io.setSysIn(input); + + try { + Main.main(new String[]{}); + } catch (Throwable t) { + fail("Executing the program failed."); + } + + List rows = new ArrayList<>(); + Arrays.stream(io.getSysOut().split("\n")).filter(r -> r.contains(":")).forEach(r -> rows.add(r)); + + if (rows.size() != expectedOutput.length) { + fail("With the input:" + input + " the print had " + rows.size() + " items:\n" + rows + "\nThe expected number of items was " + expectedOutput.length + ". \n Check your program -- also ensure that the only place you use colons in is when you print items."); + } + + NEXT: + for (String expected : expectedOutput) { + for (String row : rows) { + if (row.contains( expected)) { + continue NEXT; + } + } + + fail("With the input:\n" + input + "\n the output was expected to contain the string:\n\"" + expected + "\"\nThis was not the case. Test your program with this input."); + + } + } + +} diff --git a/mooc-java-programming-i/part05-Part05_16.DatingApp/.tmcproject.yml b/mooc-java-programming-i/part05-Part05_16.DatingApp/.tmcproject.yml new file mode 100644 index 0000000..d2446da --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_16.DatingApp/.tmcproject.yml @@ -0,0 +1 @@ +force_new_sandbox: true diff --git a/mooc-java-programming-i/part05-Part05_16.DatingApp/pom.xml b/mooc-java-programming-i/part05-Part05_16.DatingApp/pom.xml new file mode 100644 index 0000000..3a67d12 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_16.DatingApp/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + tkt + Part05_16.DatingApp + Part05_16.DatingApp + 1.0-SNAPSHOT + jar + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + fi.helsinki.cs.tmc + edu-test-utils + 0.4.2 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + diff --git a/mooc-java-programming-i/part05-Part05_16.DatingApp/src/main/java/Main.java b/mooc-java-programming-i/part05-Part05_16.DatingApp/src/main/java/Main.java new file mode 100644 index 0000000..61993e7 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_16.DatingApp/src/main/java/Main.java @@ -0,0 +1,7 @@ + +public class Main { + + public static void main(String[] args) { + // test your program here! + } +} diff --git a/mooc-java-programming-i/part05-Part05_16.DatingApp/src/main/java/SimpleDate.java b/mooc-java-programming-i/part05-Part05_16.DatingApp/src/main/java/SimpleDate.java new file mode 100644 index 0000000..7f3cd64 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_16.DatingApp/src/main/java/SimpleDate.java @@ -0,0 +1,36 @@ + +public class SimpleDate { + + private int day; + private int month; + private int year; + + public SimpleDate(int day, int month, int year) { + this.day = day; + this.month = month; + this.year = year; + } + + @Override + public String toString() { + return this.day + "." + this.month + "." + this.year; + } + + public boolean before(SimpleDate compared) { + if (this.year < compared.year) { + return true; + } + + if (this.year == compared.year && this.month < compared.month) { + return true; + } + + if (this.year == compared.year && this.month == compared.month && + this.day < compared.day) { + return true; + } + + return false; + } + +} diff --git a/mooc-java-programming-i/part05-Part05_16.DatingApp/src/test/java/A_DatingAppTest.java b/mooc-java-programming-i/part05-Part05_16.DatingApp/src/test/java/A_DatingAppTest.java new file mode 100644 index 0000000..36509dc --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_16.DatingApp/src/test/java/A_DatingAppTest.java @@ -0,0 +1,215 @@ + +import fi.helsinki.cs.tmc.edutestutils.Points; +import fi.helsinki.cs.tmc.edutestutils.ReflectionUtils; +import fi.helsinki.cs.tmc.edutestutils.Reflex; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import org.junit.Assert; +import static org.junit.Assert.*; +import org.junit.Before; +import org.junit.Test; + +public class A_DatingAppTest { + + Reflex.ClassRef klass; + String klassName = "SimpleDate"; + + @Before + public void fetchClass() { + klass = Reflex.reflect(klassName); + } + + @Points("05-16.1") + @Test + public void notTooManyObjectVariables1() { + sanityCheck("SimpleDate", 3, "Don't add new object variables to the SimpleDate class, they are not needed"); + } + + @Points("05-16.1") + @Test + public void methodAdvanceExists() throws Throwable { + String method = "advance"; + + Object object = new SimpleDate(1, 1, 2011); + + assertTrue("give the class " + klassName + " the method public void " + method + "()", klass.method(object, method) + .returningVoid().takingNoParams().isPublic()); + + + String e = "\nThe code that caused the error SimpleDate d = new SimpleDate(1, 1, 2011); " + + "d.advance();"; + + klass.method(object, method) + .returningVoid().takingNoParams().withNiceError(e).invoke(); + + } + + @Points("05-16.1") + @Test + public void methodAdvanceAdvancesOneDay() { + Class c = SimpleDate.class; + String method = "advance"; + String error = "Give the class SimpleDate the method public void advance()"; + Method advance = null; + try { + advance = ReflectionUtils.requireMethod(c, method); + } catch (Throwable t) { + fail(error); + } + assertTrue(error, advance.toString().contains("public")); + assertFalse(error, advance.toString().contains("static")); + + SimpleDate changedDate = new SimpleDate(26, 12, 2011); + + try { + ReflectionUtils.invokeMethod(void.class, advance, changedDate); + } catch (Throwable t) { + fail("Make sure the SimpleDate class has the method public void advance()."); + } + + + error = "Check that calling the advance method advances the date by one. \n" + + "When you create an object SimpleDate date = new SimpleDate(26, 12, 2011); and call the method date.advance() once, the date should be 27.12.2011.\n"; + Assert.assertEquals(error, "27.12.2011", changedDate.toString()); + } + + @Points("05-16.1") + @Test + public void methodAdvanceChangesMonthProperly() { + Class c = SimpleDate.class; + String method = "advance"; + String error = "Give the class SimpleDate the method public void advance()"; + Method advance = null; + try { + advance = ReflectionUtils.requireMethod(c, method); + } catch (Throwable t) { + fail(error); + } + assertTrue(error, advance.toString().contains("public")); + assertFalse(error, advance.toString().contains("static")); + + SimpleDate modifyDate = new SimpleDate(29, 12, 2011); + + try { + ReflectionUtils.invokeMethod(void.class, advance, modifyDate); + } catch (Throwable t) { + fail("Make sure the SimpleDate class has the method public void advance()."); + } + + error = "Check that calling the advance method advances the date by one. \n" + + "When you create an object SimpleDate date = new SimpleDate(29, 12, 2011); and call the method date.advance() once, the date should be 30.12.2011.\n"; + Assert.assertEquals(error, "30.12.2011", modifyDate.toString()); + + try { + ReflectionUtils.invokeMethod(void.class, advance, modifyDate); + } catch (Throwable t) { + fail("Make sure the SimpleDate class has the method public void advance()."); + } + + error = "Check that calling the advance method advances the date by one. \n" + + "When you create an object SimpleDate date = new SimpleDate(30, 12, 2011); and call the method date.advance() once, the date should be 1.1.2012.\n"; + Assert.assertEquals(error, "1.1.2012", modifyDate.toString()); + } + + @Points("05-16.1") + @Test + public void repeatedlyCallingAdvanceAlsoAdvancesMonths() { + Class c = SimpleDate.class; + String method = "advance"; + String error = "Give the class SimpleDate the method public void advance()"; + Method advance = null; + try { + advance = ReflectionUtils.requireMethod(c, method); + } catch (Throwable t) { + fail(error); + } + assertTrue(error, advance.toString().contains("public")); + assertFalse(error, advance.toString().contains("static")); + + SimpleDate modifyDate = new SimpleDate(30, 12, 2011); + + try { + for (int i = 0; i < 500; i++) { + ReflectionUtils.invokeMethod(void.class, advance, modifyDate); + } + } catch (Throwable t) { + fail("Make sure the SimpleDate class has the method public void advance()."); + } + + + error = "Check that calling the advance method advances the date by one. \n" + + "When you create an object SimpleDate date = new SimpleDate(30, 12, 2011); and call the method date.advance() 500 times, the date should in the year 2013.\nYou printed: " + modifyDate.toString(); + Assert.assertTrue(error, modifyDate.toString().contains("2013")); + } + + @Points("05-16.2") + @Test + public void parameterizedMethodAdvanceExists() throws Throwable { + String method = "advance"; + + Object object = new SimpleDate(1, 1, 2011); + + assertTrue("give the class " + klassName + " the method public void " + method + "(int howManyDays) ", + klass.method(object, method) + .returningVoid().taking(int.class).isPublic()); + + String e = "\nThe code that caused the error SimpleDate d = new SimpleDate(1, 1, 2011); " + + "d.advance(23);"; + + klass.method(object, method) + .returningVoid().taking(int.class).withNiceError(e).invoke(23); + + } + + @Points("05-16.2") + @Test + public void parameterizedMethodAdvanceAdvancesByOneDay() { + Class c = SimpleDate.class; + String method = "advance"; + String error = "Give the class SimpleDate the method public void advance(int howManyDays)"; + Method advance = null; + try { + advance = ReflectionUtils.requireMethod(c, method, int.class); + } catch (Throwable t) { + fail(error); + } + assertTrue(error, advance.toString().contains("public")); + assertFalse(error, advance.toString().contains("static")); + + SimpleDate modifyDate = new SimpleDate(30, 12, 2011); + try { + ReflectionUtils.invokeMethod(void.class, advance, modifyDate, 3); + } catch (Throwable t) { + fail("Make sure the SimpleDate class has the method public void advance(int howManyDays)."); + } + + Assert.assertEquals("Check that the parameterized advance method advances days by the specified number. \n" + + "Try out executing SimpleDate date = new SimpleDate(30, 12, 2011); date.advance(3); Now the date should be 3.1.2012.\n", + "3.1.2012", + modifyDate.toString()); + } + + private void sanityCheck(String className, int numOfVariables, String msg) throws SecurityException { + + Field[] fields = ReflectionUtils.findClass(className).getDeclaredFields(); + + for (Field field : fields) { + assertFalse("you don't need \"static variables\", delete " + field(field.toString()), field.toString().contains("static") && !field.toString().contains("final")); + assertTrue("the visibility of all the object variables should be private, change " + field(field.toString()), field.toString().contains("private")); + } + + if (fields.length > 1) { + int var = 0; + for (Field field : fields) { + if (!field.toString().contains("final")) { + var++; + } + } + assertTrue(msg, var <= numOfVariables); + } + } + + private String field(String toString) { + return toString.replace("SimpleDate" + ".", ""); + } +} diff --git a/mooc-java-programming-i/part05-Part05_16.DatingApp/src/test/java/B_DatingAppTest.java b/mooc-java-programming-i/part05-Part05_16.DatingApp/src/test/java/B_DatingAppTest.java new file mode 100644 index 0000000..b93b5f6 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_16.DatingApp/src/test/java/B_DatingAppTest.java @@ -0,0 +1,77 @@ + +import fi.helsinki.cs.tmc.edutestutils.Points; +import fi.helsinki.cs.tmc.edutestutils.ReflectionUtils; +import fi.helsinki.cs.tmc.edutestutils.Reflex; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import org.junit.Assert; +import static org.junit.Assert.*; +import org.junit.Before; +import org.junit.Test; + +public class B_DatingAppTest { + + Reflex.ClassRef klass; + String klassName = "SimpleDate"; + + @Before + public void fetchClass() { + klass = Reflex.reflect(klassName); + } + + @Points("05-16.3") + @Test + public void methodAfterNumberOfDaysExists() throws Throwable { + String method = "afterNumberOfDays"; + + Object object = new SimpleDate(1, 1, 2011); + + assertTrue("give the class " + klassName + " the method public SimpleDate " + method + "(int days) ", klass.method(object, method) + .returning(SimpleDate.class).taking(int.class).isPublic()); + + String e = "\nThe code that caused the error SimpleDate d = new Date(1, 1, 2011); " + + "d.afterNumberOfDays(7);"; + + + klass.method(object, method) + .returning(SimpleDate.class).taking(int.class).withNiceError(e).invoke(7); + + } + + @Points("05-16.3") + @Test + public void methodAfterNumberOfDaysCreatesNewObject() { + Class c = SimpleDate.class; + String method = "afterNumberOfDays"; + String error = "Give the class SimpleDate the method public SimpleDate afterNumberOfDays(int days)"; + Method m = null; + try { + m = ReflectionUtils.requireMethod(c, method, int.class); + } catch (Throwable t) { + fail(error); + } + assertTrue(error, m.toString().contains("public")); + assertFalse(error, m.toString().contains("static")); + + + SimpleDate modifyDate = new SimpleDate(30, 12, 2011); + SimpleDate newDate = null; + try { + newDate = ReflectionUtils.invokeMethod(SimpleDate.class, m, modifyDate, 4); + } catch (Throwable t) { + fail(error); + } + + Assert.assertEquals("Check that the afterNumberOfDays method does not change the values of the original object.", + "30.12.2011", + modifyDate.toString()); + + Assert.assertFalse("Now the afterNumberOfDays method returns the value null.\n Try executing SimpleDate date = new SimpleDate(30, 12, 2011); SimpleDate newDate = date.afterNumberOfDays(5); The newDate should be in January 2012.", + newDate==null); + + Assert.assertEquals("Check that the afterNumberOfDays method advances the new object by the specified number of days. \n" + + "Execute SimpleDate date = new SimpleDate(30, 12, 2011); SimpleDate newDate = date.afterNumberOfDays(5); The newDate should be in January of 2012.", + "4.1.2012", newDate.toString()); + } + +} diff --git a/mooc-java-programming-i/part05-Part05_17.Money/.tmcproject.yml b/mooc-java-programming-i/part05-Part05_17.Money/.tmcproject.yml new file mode 100644 index 0000000..d2446da --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_17.Money/.tmcproject.yml @@ -0,0 +1 @@ +force_new_sandbox: true diff --git a/mooc-java-programming-i/part05-Part05_17.Money/pom.xml b/mooc-java-programming-i/part05-Part05_17.Money/pom.xml new file mode 100644 index 0000000..284d115 --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_17.Money/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + tkt + Part05_17.Money + Part05_17.Money + 1.0-SNAPSHOT + jar + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + fi.helsinki.cs.tmc + edu-test-utils + 0.4.2 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + + + + tmc + TMC repo + https://maven.mooc.fi/releases + + true + + + true + + + + diff --git a/mooc-java-programming-i/part05-Part05_17.Money/src/main/java/MainProgram.java b/mooc-java-programming-i/part05-Part05_17.Money/src/main/java/MainProgram.java new file mode 100644 index 0000000..ad55aee --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_17.Money/src/main/java/MainProgram.java @@ -0,0 +1,7 @@ + +public class MainProgram { + + public static void main(String[] args) { + // test your class here + } +} diff --git a/mooc-java-programming-i/part05-Part05_17.Money/src/main/java/Money.java b/mooc-java-programming-i/part05-Part05_17.Money/src/main/java/Money.java new file mode 100644 index 0000000..a559f7b --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_17.Money/src/main/java/Money.java @@ -0,0 +1,35 @@ + +public class Money { + + private final int euros; + private final int cents; + + public Money(int euros, int cents) { + + if (cents > 99) { + euros = euros + cents / 100; + cents = cents % 100; + } + + this.euros = euros; + this.cents = cents; + } + + public int euros() { + return this.euros; + } + + public int cents() { + return this.cents; + } + + public String toString() { + String zero = ""; + if (this.cents < 10) { + zero = "0"; + } + + return this.euros + "." + zero + this.cents + "e"; + } + +} diff --git a/mooc-java-programming-i/part05-Part05_17.Money/src/test/java/MoneyTest.java b/mooc-java-programming-i/part05-Part05_17.Money/src/test/java/MoneyTest.java new file mode 100644 index 0000000..da3df9b --- /dev/null +++ b/mooc-java-programming-i/part05-Part05_17.Money/src/test/java/MoneyTest.java @@ -0,0 +1,233 @@ + +import fi.helsinki.cs.tmc.edutestutils.Points; +import fi.helsinki.cs.tmc.edutestutils.ReflectionUtils; +import fi.helsinki.cs.tmc.edutestutils.Reflex; +import fi.helsinki.cs.tmc.edutestutils.Reflex.ClassRef; +import java.lang.reflect.Field; +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assert.*; + +public class MoneyTest { + + Reflex.ClassRef classToBeTested; + String className = "Money"; + + @Before + public void findClass() { + classToBeTested = Reflex.reflect(className); + } + + @Points("05-17.1 05-17.2 05-17.3") + @Test + public void noUnnecessaryVariables() { + sanitaryCheck("Money", 2, " object variables for the amount of euroes and cents"); + } + + @Points("05-17.1") + @Test + public void testPlusMethod() throws Throwable { + String methodToTest = "plus"; + + Reflex.ClassRef classToTest = Reflex.reflect(className); + + Money firstMoneyObject = new Money(1, 0); + + assertTrue("In the class" + className + " create method public Money " + methodToTest + "(Money addition) ", + classToTest.method(firstMoneyObject, methodToTest).returning(Money.class).taking(Money.class).isPublic()); + + Money secondMoneyObject = new Money(2, 0); + + String codeToRun = " Money firstMoneyObject = new Money(1, 0);" + + "secondMoneyObject = new Money(2, 0);" + + "Money firstPlusSecond = firstMoneyObject.plus(secondMoneyObject);"; + + Money firstPlusSecond = classToTest.method(firstMoneyObject, methodToTest).returning(Money.class).taking(Money.class). + withNiceError("Failing code: " + codeToRun).invoke(secondMoneyObject); + + assertFalse("When we did " + codeToRun + " the plus method returned null ", firstPlusSecond == null); + + assertEquals(codeToRun + " firstPlusSecond.euros();", 3, firstPlusSecond.euros()); + assertEquals(codeToRun + " firstPlusSecond.cents(); ", 0, firstPlusSecond.cents()); + assertEquals(codeToRun + " System.out.println(firstPlusSecond)", "3.00e", firstPlusSecond.toString()); + assertEquals("Alkuperäiset oliot eivät saa muuttua:\n" + codeToRun + " System.out.println(firstMoneyObject)", "1.00e", firstMoneyObject.toString()); + assertEquals("Alkuperäiset oliot eivät saa muuttua:\n" + codeToRun + " System.out.println(secondMoneyObject)", "2.00e", secondMoneyObject.toString()); + + firstMoneyObject = new Money(7, 50); + secondMoneyObject = new Money(1, 60); + + codeToRun = " Money firstMoneyObject = new Money(7, 50);" + + "secondMoneyObject = new Money(1, 60);" + + "Money firstPlusSecond = firstMoneyObject.plus(secondMoneyObject);"; + + firstPlusSecond = classToTest.method(firstMoneyObject, methodToTest).returning(Money.class).taking(Money.class). + withNiceError("Failing code: " + codeToRun).invoke(secondMoneyObject); + + assertEquals(codeToRun + " System.out.println(firstPlusSecond)", "9.10e", firstPlusSecond.toString()); + assertEquals("The original objects should not change:\n" + codeToRun + " System.out.println(firstMoneyObject)", "7.50e", firstMoneyObject.toString()); + assertEquals("The original objects should not change:\n" + codeToRun + " System.out.println(secondMoneyObject)", "1.60e", secondMoneyObject.toString()); + + } + + @Points("05-17.2") + @Test + public void testMethodLess() throws Throwable { + String methodToTest = "lessThan"; + + Reflex.ClassRef classToTest = Reflex.reflect(className); + + Money firstMoneyObject = new Money(1, 0); + + assertTrue("In the class" + className + " create the method public boolean " + methodToTest + "(Money compared) ", + classToTest.method(firstMoneyObject, methodToTest).returning(boolean.class).taking(Money.class).isPublic()); + + Money secondMoneyObject = new Money(1, 5); + Money thirdMoneyObject = new Money(-3, 5); + Money fourthMoneyObject = new Money(2, 0); + + String codeToTest = "When Money firstMoneyObject = new Money(1, 0); " + + "secondMoneyObject = new Money(1, 50); " + + "thirdMoneyObject = new Money(-3,5); " + + "fourthMoneyObject = new Money(2,0); "; + + check(firstMoneyObject, secondMoneyObject, true, codeToTest + " firstMoneyObject.lessThan(secondMoneyObject);", classToTest); + check(secondMoneyObject, firstMoneyObject, false, codeToTest + " secondMoneyObject.lessThan(firstMoneyObject);", classToTest); + + check(firstMoneyObject, thirdMoneyObject, false, codeToTest + " firstMoneyObject.lessThan(thirdMoneyObject);", classToTest); + check(thirdMoneyObject, firstMoneyObject, true, codeToTest + " thirdMoneyObject.lessThan(firstMoneyObject);", classToTest); + + check(secondMoneyObject, thirdMoneyObject, false, codeToTest + " secondMoneyObject.lessThan(thirdMoneyObject);", classToTest); + check(thirdMoneyObject, secondMoneyObject, true, codeToTest + " thirdMoneyObject.lessThan(secondMoneyObject);", classToTest); + + check(secondMoneyObject, fourthMoneyObject, true, codeToTest + " secondMoneyObject.lessThan(fourthMoneyObject);", classToTest); + check(fourthMoneyObject, secondMoneyObject, false, codeToTest + " fourthMoneyObject.lessThan(secondMoneyObject);", classToTest); + + check(thirdMoneyObject, fourthMoneyObject, true, codeToTest + " thirdMoneyObject.lessThan(fourthMoneyObject);", classToTest); + check(fourthMoneyObject, thirdMoneyObject, false, codeToTest + " fourthMoneyObject.lessThan(thirdMoneyObject);", classToTest); + } + + private void check(Money e, Money t, boolean res, String v, ClassRef klass) throws Throwable { + + assertEquals(v, res, klass.method(e, "lessThan").returning(boolean.class).taking(Money.class).invoke(t)); + } + + @Points("05-17.3") + @Test + public void testMinusMethod() throws Throwable { + String methodToBeTested = "minus"; + + Reflex.ClassRef classToBeTested = Reflex.reflect(className); + + Money firstMoneyObject = new Money(10, 0); + + assertTrue("For the class " + className + ", create method Money" + methodToBeTested + "(Money decreaser) ", classToBeTested.method(firstMoneyObject, methodToBeTested) + .returning(Money.class).taking(Money.class).isPublic()); + + Money secondMoneyObject = new Money(2, 0); + + String codeToRun = "Money firstMoneyObject = new Money(10, 0);" + + "Money secondMoneyObjecy = new Money(2, 0);" + + "Money tennerMinusTwoEuros = firstMoneyObject.minus(secondMoneyObject);"; + + Money firstMinusSecond = classToBeTested.method(firstMoneyObject, methodToBeTested).returning(Money.class).taking(Money.class). + withNiceError("Failing code " + codeToRun).invoke(secondMoneyObject); + + assertFalse("When we did" + codeToRun + " the minus method returned a null", firstMinusSecond == null); + + assertEquals(codeToRun + " tennerMinusTwoEuros.euros();", 8, firstMinusSecond.euros()); + assertEquals(codeToRun + " tennerMinusTwoEuros.cents(); ", 0, firstMinusSecond.cents()); + assertEquals(codeToRun + " System.out.println(r3)", "8.00e", firstMinusSecond.toString()); + assertEquals("The original objects should not change:\n" + codeToRun + " System.out.println(tenner)", "10.00e", firstMoneyObject.toString()); + assertEquals("The original objects should not change:\n" + codeToRun + " System.out.println(twoEuros)", "2.00e", secondMoneyObject.toString()); + + secondMoneyObject = new Money(7, 40); + + codeToRun = "Money firstMoneyObject = new Money(10, 0);" + + "Money secondMoneyObject = new Money(7, 40);" + + "Money firstMinusSecond = firstMoneyObject.minus(secondMoneyObject);"; + + firstMinusSecond = classToBeTested.method(firstMoneyObject, methodToBeTested).returning(Money.class).taking(Money.class). + withNiceError("Failing code: " + codeToRun).invoke(secondMoneyObject); + + assertEquals(codeToRun + " firstMinusSecond.euros();", 2, firstMinusSecond.euros()); + assertEquals(codeToRun + " firstMinusSecond.cents(); ", 60, firstMinusSecond.cents()); + assertEquals(codeToRun + " System.out.println(firstMinusSecond)", "2.60e", firstMinusSecond.toString()); + assertEquals("The original objects should not change:\n" + codeToRun + " System.out.println(firstMoneyObject)", "10.00e", firstMoneyObject.toString()); + assertEquals("The original objects should not change:\n" + codeToRun + " System.out.println(secondMoneyObject)", "7.40e", secondMoneyObject.toString()); + + firstMoneyObject = new Money(1, 00); + secondMoneyObject = new Money(2, 00); + + codeToRun = "Remember that a Money cannot have a negative value: test the code \n" + + "Money firstMoneyObject = new Money(1, 0);" + + "Money secondMoneyObject = new Money(2, 0);" + + "Money firstMinusSecond = firstMoneyObject.minus(secondMoneyObject);"; + + firstMinusSecond = classToBeTested.method(firstMoneyObject, methodToBeTested).returning(Money.class).taking(Money.class). + withNiceError("Failing code: " + codeToRun).invoke(secondMoneyObject); + + assertEquals(codeToRun + " firstMinusSecond.euros();", 0, firstMinusSecond.euros()); + assertEquals(codeToRun + " firstMinusSecond.cents(); ", 0, firstMinusSecond.cents()); + assertEquals(codeToRun + " System.out.println(r3)", "0.00e", firstMinusSecond.toString()); + assertEquals("The original objects should not change:\n" + codeToRun + " System.out.println(firstMoneyObject)", "1.00e", firstMoneyObject.toString()); + assertEquals("The original objects should not change:\n" + codeToRun + " System.out.println(secondMoneyObject)", "2.00e", secondMoneyObject.toString()); + + + firstMoneyObject = new Money(1, 50); + secondMoneyObject = new Money(2, 00); + + codeToRun = "Remember that a Money cannot have a negative value: test the code \nMoney firstMoneyObject = new Money(1, 50);" + + "Money secondMoneyObject = new Money(2, 0);" + + "Money firstMinusSecond = firstMoneyObject.minus(secondMoneyObject);"; + + firstMinusSecond = classToBeTested.method(firstMoneyObject, methodToBeTested).returning(Money.class).taking(Money.class). + withNiceError("Failing code: " + codeToRun).invoke(secondMoneyObject); + + assertEquals(codeToRun + " firstMinusSecond.euros();", 0, firstMinusSecond.euros()); + assertEquals(codeToRun + " firstMinusSecond.cents(); ", 0, firstMinusSecond.cents()); + assertEquals(codeToRun + " System.out.println(r3)", "0.00e", firstMinusSecond.toString()); + assertEquals("The original objects should not change:\n" + codeToRun + " System.out.println(firstMoneyObject)", "1.50e", firstMoneyObject.toString()); + assertEquals("The original objects should not change:\n" + codeToRun + " System.out.println(secondMoneyObject)", "2.00e", secondMoneyObject.toString()); + + firstMoneyObject = new Money(2, 50); + secondMoneyObject = new Money(2, 00); + + codeToRun = "Remember the cents. Test the code: \n" + + "Money firstMoneyObject = new Money(2, 50);" + + "Money secondMoneyObject = new Money(2, 0);" + + "Money firstMinusSecond = firstMoneyObject.minus(secondMoneyObject);"; + + firstMinusSecond = classToBeTested.method(firstMoneyObject, methodToBeTested).returning(Money.class).taking(Money.class). + withNiceError("Failing code: " + codeToRun).invoke(secondMoneyObject); + + assertEquals(codeToRun + " firstMinusSecond.euros();", 0, firstMinusSecond.euros()); + assertEquals(codeToRun + " firstMinusSecond.cents(); ", 50, firstMinusSecond.cents()); + assertEquals(codeToRun + " System.out.println(r3)", "0.50e", firstMinusSecond.toString()); + assertEquals("The original objects should not change:\n" + codeToRun + " System.out.println(firstMoneyObject)", "2.50e", firstMoneyObject.toString()); + assertEquals("The original objects should not change:\n" + codeToRun + " System.out.println(secondMoneyObject)", "2.00e", secondMoneyObject.toString()); + + } + + private void sanitaryCheck(String className, int numberOfVariablesNeeded, String explanationOfNeededVariables) throws SecurityException { + Field[] fields = ReflectionUtils.findClass(className).getDeclaredFields(); + + for (Field field : fields) { + assertFalse("You do not need \"static variables\", remove from class " + className + " variables " + field(field.toString(), className), field.toString().contains("static") && !field.toString().contains("final")); + assertTrue("All object variables of a class should be private, but class " + className + " has: " + field(field.toString(), className), field.toString().contains("private")); + } + + if (fields.length > 1) { + int var = 0; + for (Field field : fields) { + if (!field.toString().contains("final")) { + var++; + } + } + assertTrue("You do not need for" + className + "class other than " + explanationOfNeededVariables + ", remove all others", var <= numberOfVariablesNeeded); + } + } + + private String field(String toString, String className) { + return toString.replace(className + ".", "").replace("java.lang.", ""); + } +}