diff --git a/Doc/Sd1/Exam/2021/Winter/exam.xml b/Doc/Sd1/Exam/2021/Winter/exam.xml new file mode 100644 index 0000000000000000000000000000000000000000..fa895dcca777914bdbbb7fe290a8e3ff9e4025ab --- /dev/null +++ b/Doc/Sd1/Exam/2021/Winter/exam.xml @@ -0,0 +1,481 @@ +<?xml version="1.0" encoding="UTF-8"?> +<section version="5.0" xml:id="sd1_exam_2021_winter" xml:lang="en" + xmlns="http://docbook.org/ns/docbook" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes" + xmlns:xi="http://www.w3.org/2001/XInclude" + xmlns:trans="http://docbook.org/ns/transclusion" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:m="http://www.w3.org/1998/Math/MathML" + xmlns:html="http://www.w3.org/1999/xhtml" + xmlns:db="http://docbook.org/ns/docbook"> + <title>SD1 examination winter 2021</title> + + <section xml:id="sd1_exam_2021_winter_task1"> + <title>Implementing tasks</title> + + <section xml:id="sd1_exam_2021_winter_task1_preparation"> + <title>Preparation</title> + + <para>Download and unzip the above file <filename>exam.zip</filename>. + Then import the resulting <filename>Exam</filename> Project into your + <productname>IDEA</productname> IDE by choosing »File --> Open...« + for selecting the <filename>Exam/pom.xml</filename> file.</para> + </section> + + <section xml:id="sd1_exam_2021_winter_task1_description"> + <title>Description</title> + + <para>Your imported project contains:</para> + + <itemizedlist> + <listitem> + <para>Partial implementations of classes and methods.</para> + </listitem> + + <listitem> + <para><productname>Javadoc</productname> comments describing the + desired (not yet implemented) behaviour.</para> + </listitem> + + <listitem> + <para><productname>Junit</productname> tests for testing the desired + behaviour.</para> + </listitem> + </itemizedlist> + </section> + + <section xml:id="sd1_exam_2021_winter_task1_tasks"> + <title>Tasks</title> + + <para>Complete the implementation of classes and methods in both + packages <package>de.hdm_stuttgart.mi.sd1.task1</package> and + <package>de.hdm_stuttgart.mi.sd1.task2</package>. Your project's + <filename>test</filename> branch contains corresponding + <productname>Junit</productname> tests for each class / method to be + implemented.</para> + </section> + + <section xml:id="sd1_exam_2021_winter_task1_hints"> + <title>Hints</title> + + <itemizedlist> + <listitem> + <para>Your score solely depends on the number of successfully + executing unit tests. A »nearly correct« implementation failing with + respect to a given unit tests will not contribute any points at + all.</para> + + <para>General advice: Implement less but correctly.</para> + </listitem> + + <listitem> + <para>Mind special cases <abbrev>i.e.</abbrev> <code>null</code> + variable values or <code>null</code> values being contained in + arrays.</para> + </listitem> + + <listitem> + <para>In case of test failures both the + <productname>IDEA</productname> debugger and logging statements are + your friend.</para> + </listitem> + + <listitem> + <para>Executing + <package>de.hdm_stuttgart.mi.sd1</package>.<classname>ShowReachedPoints</classname> + in your project's <filename>test</filename> branch as a + <productname>Java</productname> application (not as + <productname>Junit</productname> test!) shows your number of points + reached so far.</para> + </listitem> + + <listitem> + <para>Do not model your implementations along unit test definitions + i.e avoid <link + xlink:href="https://freedocs.mi.hdm-stuttgart.de/__slidesd1_appendix.html#/sd1_fig_testDontCheat">cheating + this way</link>! Such behaviour will be regarded as an attempt at + deception (<foreignphrase + xml:lang="de">Täuschungsversuch</foreignphrase>).</para> + </listitem> + </itemizedlist> + </section> + + <section version="5.1" xml:id="sd1_exam_2021_winter_uploadFirst"> + <title>Project upload</title> + + <para>Export your project by hitting »File« --> »Export« --> + »Project to Zip File« in IDEA creating <abbrev>e.g.</abbrev> a file + <filename>solution-1.zip</filename>. Hit the <quote> choose file</quote> + button in your <productname>ILIAS</productname> browser tab and select + <filename>solution-1.zip</filename>. Subsequently click + <quote>upload</quote>. Do not forget to advance to the next question for + actually saving your upload. Common pitfalls:</para> + + <itemizedlist> + <listitem> + <para>Do not select the wrong archive! In particular avoid choosing + the original <filename>exam.zip</filename> file.</para> + </listitem> + + <listitem> + <para>After uploading check for <filename>solution_1.zip</filename> + being visible in the examination system.</para> + </listitem> + + <listitem> + <para>On advancing your implementation you may upload improved + versions i.e. <filename>solution_2.zip</filename> etc. of your + project at any time. Only your least uploaded archive will become + subject to marking.</para> + </listitem> + </itemizedlist> + </section> + + <section xml:id="sd1_exam_2021_winter_examCaveats"> + <title>Caveats</title> + + <itemizedlist> + <listitem> + <para>When approaching end of examination check your input for + completeness prior to being automatically logged out by the system. + Remember: There is 120 minutes for the examination and another 5 + minutes to check for completeness.</para> + </listitem> + + <listitem> + <para>Projects residing just on your local workstation's file system + cannot be recovered after finishing the exam.</para> + </listitem> + </itemizedlist> + </section> + </section> + + <section xml:id="sd1_exam_2021_winter_task2"> + <title><methodname>equals()</methodname> and + <methodname>hashCode()</methodname></title> + + <qandaset defaultlabel="qanda" xml:id="sd1_exam_2021_winter_task2Qanda"> + <qandadiv> + <qandaentry> + <question> + <para>Consider the following <classname>Person</classname> + class:</para> + + <programlisting language="java">public class Person { + + private String name, // Guaranteed never + comment; // to be null + + private int ageInYears; + + // Other methods omitted for brevity + + @Override public boolean equals(Object o) { + if (o instanceof Person) { + final Person p = (Person) o; + return ageInYears == p.ageInYears && + name.equals(p.name); + } else { + return false; + } + } + + @Override public int hashCode() { + return ageInYears + 13 * comment.hashCode(); + } +}</programlisting> + + <para>We assume the above <methodname>equals()</methodname> + implementation to be correct. Answer the following two + questions:</para> + + <orderedlist> + <listitem> + <para>Is this implementation correct regarding the <link + xlink:href="https://freedocs.mi.hdm-stuttgart.de/doc/openjdk-17-doc/api/java.base/java/lang/Object.html#hashCode()">contract + between <methodname>equals()</methodname> and + <methodname>hashCode()</methodname></link>? Correct if + necessary.</para> + </listitem> + + <listitem> + <para>After correcting possible flaws: Is the resulting + implementation »good« with respect to distinguishing objects? + Amend if possible.</para> + </listitem> + </orderedlist> + + <para>Explain your answers.</para> + </question> + + <answer> + <orderedlist> + <listitem> + <para>The <methodname>equals(...)</methodname> method defines + two <classname>Person</classname> instances to be equal when + having common age and Name. Thus two instances e.g. <code>(18, + "Eve Porter", "New Friend from holiday")</code> and <code>(18, + "Eve Porter", "Friendly person")</code>of common name and age + but having a different comment will still considered to be + equal.</para> + + <para>Since equality is being defined solely on + <property>age</property> and <property>name</property> the + <property>comment</property> attribute must not be used for + implementing <methodname>hashCode()</methodname>. Otherwise + the above example will result in different hash values + contradicting the <methodname>equals(...)</methodname> / + <methodname>hashCode()</methodname> contract. We thus + have:</para> + + <programlisting language="java">public class Person { + ... + @Override public int hashCode() { + return ageInYears; + } +}</programlisting> + </listitem> + + <listitem> + <para>The previously corrected + <methodname>hashCode()</methodname> implementation is correct + with respect to its related <methodname>equals()</methodname> + method. However all <classname>Person</classname> instances of + common <property>age</property> but different + <property>name</property> will be defined to be different by + our <methodname>equals(...)</methodname> method. But they will + all share the same <methodname>hashCode()</methodname> value + throughout. So our <methodname>hashCode()</methodname> method + is not particularly good when it comes to distinguish objects. + Adding the <property>name</property> property to our + <methodname>hashCode()</methodname> calculation solves this + issue:</para> + + <programlisting language="java">public class Person { + ... + @Override public int hashCode() { + return ageInYears + 13 * name.hashCode(); + } +}</programlisting> + </listitem> + </orderedlist> + </answer> + </qandaentry> + </qandadiv> + </qandaset> + </section> + + <section xml:id="sd1_exam_2021_winter_task3"> + <title>The average of three byte values</title> + + <qandaset defaultlabel="qanda" xml:id="sd1_exam_2021_winter_task3Qanda"> + <qandadiv> + <qandaentry> + <question> + <para>A newbie programmer codes the following snippet:</para> + + <programlisting language="java">/** + * The average of three values + * + * @param a First value + * @param b Second value + * @param c Third value + * + * @return Closest <code>byte</code> value to â…“ (a + b + c) + */ +public static byte getAverage(byte a, final byte b, final byte c) { + a += b; + a += c; + a /= 3; + return a; +}</programlisting> + + <para>A senior programming companion warns about two possible + problems:</para> + + <orderedlist> + <listitem> + <para>The implementation is prone to overflow errors.</para> + </listitem> + + <listitem> + <para>The implementation will in many cases return + unnecessarily inaccurate results.</para> + </listitem> + </orderedlist> + + <para>Explain both points in the answer box below.</para> + + <para>In addition provide a solution by modifying the above code. + You may present your code in the answer box below as well.</para> + + <para>Alternatively correct the implementation of + <package>de.hdm_stuttgart.mi.sd1.task4_no_unit_test</package>.<classname>Mathextend</classname> + within your downloaded and imported <filename>exam.zip</filename> + project using your IDEA IDE. In this case <emphasis role="red">Do + not forget to export and upload after finishing by using task 1 of + this examination</emphasis>.</para> + + <tip> + <para><methodname + xlink:href="https://freedocs.mi.hdm-stuttgart.de/lib/openjdk-17-doc/api/java.base/java/lang/Math.html#round(double)">Math.round(double)</methodname> + might be your friend.</para> + </tip> + </question> + + <answer> + <orderedlist> + <listitem> + <para>Biggest problem here: The operator <code + language="java">+=</code>'s way of cycling through a <code + language="java">byte</code>'s range when exceeding <code + language="java" + xlink:href="https://freedocs.mi.hdm-stuttgart.de/lib/openjdk-17-doc/api/java.base/java/lang/Byte.html#MAX_VALUE">Byte.MAX_VALUE</code> + or <code language="java" + xlink:href="https://freedocs.mi.hdm-stuttgart.de/lib/openjdk-17-doc/api/java.base/java/lang/Byte.html#MIN_VALUE">Byte.MIN_VALUE</code> + boundaries. Consider:</para> + + <informaltable border="1"> + <colgroup width="76%"/> + + <colgroup width="24%"/> + + <tr> + <th>Code</th> + + <th>Output</th> + </tr> + + <tr> + <td valign="top"><programlisting language="java">byte b = 127; +b += 1; +System.out.println("Result: " + b);</programlisting></td> + + <td valign="top"><screen>Result: -128</screen></td> + </tr> + + <tr> + <td valign="top"><programlisting language="java">byte b = -128; +b += -1; +System.out.println("Result: " + b);</programlisting></td> + + <td valign="top"><screen>Result: +127</screen></td> + </tr> + + <tr> + <td valign="top"><programlisting language="java">// Expecting 129 / 3 == +43 +System.out.println("Result: " + + getAverage((byte) 127, (byte) 1, (byte) 1));</programlisting></td> + + <td valign="top"><screen>Result: -42</screen></td> + </tr> + </informaltable> + </listitem> + + <listitem> + <para>Converting fractions to byte values is next on the list + of troubles. The <code language="java">/=</code> operator will + simply cut off fractional values rather then rounding them + properly.</para> + + <para>Switching to real values we have <inlineequation> + <m:math display="inline"> + <m:mrow> + <m:mrow> + <m:mfrac bevelled="true"> + <m:mi>1</m:mi> + + <m:mi>3</m:mi> + </m:mfrac> + + <m:mo>â¢</m:mo> + + <m:mrow> + <m:mo>(</m:mo> + + <m:mrow> + <m:mi>1</m:mi> + + <m:mo>+</m:mo> + + <m:mi>1</m:mi> + + <m:mo>+</m:mo> + + <m:mi>0</m:mi> + </m:mrow> + + <m:mo>)</m:mo> + </m:mrow> + </m:mrow> + + <m:mo>=</m:mo> + + <m:mi>0.66...</m:mi> + </m:mrow> + </m:math> + </inlineequation> . Our byte valued method should thus + return a value of 1 rather than 0. However:</para> + + <informaltable border="1"> + <colgroup width="76%"/> + + <colgroup width="24%"/> + + <tr> + <th>Code</th> + + <th>Output</th> + </tr> + + <tr> + <td valign="top"><programlisting language="java">System.out.println("Result: " + + getAverage((byte) 1, (byte) 1, (byte) 0));</programlisting></td> + + <td valign="top"><screen>Result: 0</screen></td> + </tr> + </informaltable> + </listitem> + </orderedlist> + + <para>Solving these flaws requires using a data type behaving free + of overflow errors with respect to the given context of summing up + three byte values. Choosing <code>short</code> is sufficient for + adding either <code language="java" + xlink:href="https://freedocs.mi.hdm-stuttgart.de/lib/openjdk-17-doc/api/java.base/java/lang/Byte.html#MAX_VALUE">Byte.MAX_VALUE</code> + or <code language="java" + xlink:href="https://freedocs.mi.hdm-stuttgart.de/lib/openjdk-17-doc/api/java.base/java/lang/Byte.html#MIN_VALUE">Byte.MIN_VALUE</code> + even three times in a row.</para> + + <para>Dividing by 3 should be a floating point rather than an + integer operation to avoid cutting off fractional values. On top + we finally use the <classname + xlink:href="https://freedocs.mi.hdm-stuttgart.de/lib/openjdk-17-doc/api/java.base/java/lang/Math.html">Math</classname><code + language="java">.</code><methodname + xlink:href="https://freedocs.mi.hdm-stuttgart.de/lib/openjdk-17-doc/api/java.base/java/lang/Math.html#round(double)">round(double)</methodname> + method avoiding rounding errors like the one shown + previously.</para> + + <para>Finally we need a cast for converting back the rounded + value's type <code language="java">double</code> to the method's + return type <code language="java">byte</code>. The final result + reads:</para> + + <programlisting language="java">public static byte getAverage(final byte a, final byte b, final byte c) { + + short sum = a; + sum += b; + sum += c; + final double avg = sum / 3.; // Floating point rather than integer division + return (byte) Math.round(avg); +} + +// Note: final short sum = a + b + c does not even compile as being explained at +// https://freedocs.mi.hdm-stuttgart.de/sd1_sect_arithmeticOperators.html#sd1_explainNoByteByteOperator</programlisting> + </answer> + </qandaentry> + </qandadiv> + </qandaset> + </section> +</section> diff --git a/Doc/Sd1/appendix.xml b/Doc/Sd1/appendix.xml index 1d59125f48ff563bd2cc14ac28e65104063a816a..164b17ff4814abaa426e273529eb72a92f5dca3e 100644 --- a/Doc/Sd1/appendix.xml +++ b/Doc/Sd1/appendix.xml @@ -3100,6 +3100,10 @@ Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.372 sec</scree <section xml:id="sd1_exams"> <title>Past Software Development 1 examinations</title> + + <xi:include href="Exam/2021/Winter/exam.xml" xpointer="element(/1)" + ns:idfixup="auto"/> + <xi:include href="Exam/2021/Summer/exam.xml" xpointer="element(/1)" ns:idfixup="auto"/> diff --git a/Klausuren/Sd1/2021winter/Exam/pom.xml b/Klausuren/Sd1/2021winter/Exam/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..0c0738ff79961945bb37e5c5ef5b42a4e8581785 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/pom.xml @@ -0,0 +1,130 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>de.hdm-stuttgart.mi.sd1</groupId> + <artifactId>sd1_2021winter_exam</artifactId> + <version>0.9</version> + <packaging>jar</packaging> + + <name>sd1_2021winter_exam</name> + + <url>https://freedocs.mi.hdm-stuttgart.de/sd1_sect_mavenCli.html</url> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + + <maven.compiler.target>17</maven.compiler.target> + <maven.compiler.source>17</maven.compiler.source> + + <freedocs.url>https://freedocs.mi.hdm-stuttgart.de</freedocs.url> + <jdk.api_17.url>${freedocs.url}/doc/openjdk-17-doc/api/</jdk.api_17.url> + <mathjax.url>${freedocs.url}/mathjax/MathJax.js?config=TeX-AMS-MML_HTMLorMML</mathjax.url> + <libhighlight.url>${freedocs.url}/lib/highlight.js</libhighlight.url> + </properties> + + <repositories> + <repository> + <id>hdm-mi-internal-maven-repo</id> + <url>https://maven.mi.hdm-stuttgart.de/nexus/repository/mi-maven</url> + </repository> + </repositories> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.13.2</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-core</artifactId> + <version>2.17.1</version> + </dependency> + + <dependency> + <groupId>de.hdm_stuttgart.mi.exam</groupId> + <artifactId>unitmarking</artifactId> + <version>1.1</version> + </dependency> + + </dependencies> + + <build> + <plugins> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.1</version> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>3.3.0</version> + + <configuration> + <!-- Tweak: Get rid of Error message + »fetching link: .../target/javadoc-bundle-options. Ignored it« + corresponding to api_11 below --> + <release>11</release> + <doclint>all</doclint> + <show>public</show> + <docfilessubdirs>true</docfilessubdirs> + <addStylesheets> + <stylesheet>resources/jdocSupplement.css</stylesheet> + </addStylesheets> + + <javaApiLinks> + <property> + <name>api_11</name> + <value>${jdk.api_17.url}</value> + </property> + </javaApiLinks> + + <additionalOptions> + <additionalOption>-html5 --allow-script-in-comments</additionalOption> + </additionalOptions> + <nohelp>true</nohelp> + + <header><![CDATA[ + <script type="text/javascript" src="${mathjax.url}"></script> + <script type="text/javascript" src="{@docRoot}/resources/jdocSupplement.js"></script> + <link rel="stylesheet" href="${libhighlight.url}/styles/idea.css"> + <script src="${libhighlight.url}/highlight.js"></script> + <script type="text/javascript">hljs.initHighlightingOnLoad();</script>]]> + </header> + </configuration> + </plugin> + + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <version>3.3.0</version> + <configuration> + <descriptors> + <descriptor>src/main/assembly/assembly.xml</descriptor> + </descriptors> + </configuration> + <executions> + <execution> + <id>make-assembly</id> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + <configuration> + <archive> + <manifest> + <mainClass>de.hdm_stuttgart.mi.sd1.ShowReachedPoints</mainClass> + </manifest> + </archive> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/Klausuren/Sd1/2021winter/Exam/src/main/assembly/assembly.xml b/Klausuren/Sd1/2021winter/Exam/src/main/assembly/assembly.xml new file mode 100644 index 0000000000000000000000000000000000000000..85268e2965620878373d76337f524d8785fd0e1f --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/src/main/assembly/assembly.xml @@ -0,0 +1,36 @@ +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd"> + <id>fat-tests</id> + <formats> + <format>jar</format> + </formats> + <includeBaseDirectory>false</includeBaseDirectory> + <dependencySets> + <dependencySet> + <outputDirectory/> + <useProjectArtifact>true</useProjectArtifact> + <unpack>true</unpack> + <scope>test</scope> + </dependencySet> + </dependencySets> + <fileSets> + <fileSet> + <directory>${project.build.directory}/test-classes</directory> + <outputDirectory/> + <includes> + <include>**/*.class</include> + </includes> + <useDefaultExcludes>true</useDefaultExcludes> + </fileSet> + <fileSet> + <directory>${project.build.directory}/classes</directory> + <outputDirectory/> + <includes> + <include>**/*.class</include> + </includes> + <useDefaultExcludes>true</useDefaultExcludes> + </fileSet> + </fileSets> +</assembly> \ No newline at end of file diff --git a/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/A_TrafficLight.java b/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/A_TrafficLight.java new file mode 100644 index 0000000000000000000000000000000000000000..c94ac78bd2e748c58d83cea2c305e9b0fc078cc8 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/A_TrafficLight.java @@ -0,0 +1,66 @@ +package de.hdm_stuttgart.mi.sd1.task1; + +/** + * <p>Stop and go at trafficlights.</p> + */ +public class A_TrafficLight { + /** + * <p>Traffic light stop / go indications.</p> + * + * <p>German traffic lights feature three different colours red, yellow and green. We assume the following rules:</p> + * + * <table style="border-spacing: 10ex 0;"> + * <caption>German traffic light states</caption> + * <tr> + * <td + * style="border: 2px solid black;border-radius: 10px;font-size:40px;background:black;"> + * <ul> + * <li style="color:red;"></li> + * <li style="color:black;"></li> + * <li style="color:black;"></li> + * </ul> + * </td> + * <td style="border: 2px solid black;border-radius: 10px;font-size:40px;background:black;"> + * <ul> + * <li style="color:red;"></li> + * <li style="color:yellow;"></li> + * <li style="color:black;"></li> + * </ul> + * </td> + * <td style="border: 2px solid black;border-radius: 10px;font-size:40px;background:black;"> + * <ul> + * <li style="color:black;"></li> + * <li style="color:black;"></li> + * <li style="color:green;"></li> + * </ul> + * </td> + * <td style="border: 2px solid black;border-radius: 10px;font-size:40px;background:black;"> + * <ul> + * <li style="color:black;"></li> + * <li style="color:yellow;"></li> + * <li style="color:black;"></li> + * </ul> + * </td> + * </tr> + * <tr> + * <td>Stop</td> + * <td>Go</td> + * <td>Go</td> + * <td>Stop</td> + * </tr> + * + * </table> + * + * @param red <code>true</code> represents »on«, <code>false</code> represents »off«. + * @param yellow <code>true</code> represents »on«, <code>false</code> represents »off«. + * @param green <code>true</code> represents »on«, <code>false</code> represents »off«. + * + * @return <code>true</code> represents »you must stop«, <code>false</code> represents »go«. + */ + static public boolean mustStop(boolean red, boolean yellow, boolean green) { + return false; // TODO: Implement me correctly + } + + private A_TrafficLight(){/* Ignore me: My sole purpose is suppressing default constructor javadoc generation */} + +} diff --git a/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/B_StringHelper.java b/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/B_StringHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..642a280e8982373b9c71d4db9b37e8b4dac1e1e0 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/B_StringHelper.java @@ -0,0 +1,44 @@ +package de.hdm_stuttgart.mi.sd1.task1; + +/** + * String related helper method. Currently {@link #getMaxLength(String[])} is on offer. + */ +public class B_StringHelper { + + /** + * <p>Get the maximum string length among an array of strings. In the following example the longest of three + * strings is <code class="java">"Longman"</code> having length 7:</p> + * + * <table class="goikTableDefaults"> + * <caption>Finding the longest string</caption> + * <tbody> + * <tr> + * <th>Code</th> + * <th>Result</th> + * </tr> + * <tr> + * <td> + * <pre><code class="java"> final String[] names = + * {"Eve", "Longman", "Peter"}; + * + * System.out.println("Longest name's length: " + + * getMaxLength(names));</code></pre> + * </td> + * <td> + * <pre><code class="nohighlight"> Longest name's length: 7</code></pre> + * </td> + * </tr> + * </tbody> + * </table> + * + * @param strings A non-empty array possibly containing both strings and <code>null</code> values. + * @return The greatest length of all strings. <code>null</code> values will be treated like empty strings. + */ + static public int getMaxLength(final String[] strings) { + + return 123;// TODO: Implement me correctly + } + + private B_StringHelper(){/* Ignore me: My sole purpose is suppressing default constructor javadoc generation */} + +} diff --git a/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/C_ArrayHelper.java b/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/C_ArrayHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..dc6226838ad877bf4b20e0de46c68d56b7085c42 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/C_ArrayHelper.java @@ -0,0 +1,42 @@ +package de.hdm_stuttgart.mi.sd1.task1; + +/** + * <p>Array related helper method</p> + */ +public class C_ArrayHelper { + + /** + * <p>Collect all values from a given array being above its average value. The following example + * features an array of five values resulting in an average of 6. Only the values 8, 12 and 8 + * are strictly above average:</p> + * + * <table class="goikTableDefaults"> + * <caption>Finding values above average</caption> + * <tbody> + * <tr> + * <th>Code</th> + * <th>Result</th> + * </tr> + * <tr> + * <td> + * <pre><code class="java"> final int[] values = {-4, 6, 8, 12, 8}; + * System.out.println( "Above average: " + + * Arrays.toString(getAboveAverage(values)));</code></pre> + * </td> + * <td> + * <pre><code class="nohighlight"> Above average: [8, 12, 8] </code></pre> + * </td> + * </tr> + * </tbody> + * </table> + * + * @param values A list of values. + * @return All values from the list being strictly above the list's average thereby preserving + * the original array's order of appearance. + */ + static public int[] getAboveAverage (int[] values) { + return null;// TODO: Implement me correctly + } + private C_ArrayHelper(){/* Ignore me: My sole purpose is suppressing default constructor javadoc generation */} + +} diff --git a/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/D_TextFrame.java b/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/D_TextFrame.java new file mode 100644 index 0000000000000000000000000000000000000000..7441a36e73808788bcd5986b48152e511d0064d8 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/D_TextFrame.java @@ -0,0 +1,69 @@ +package de.hdm_stuttgart.mi.sd1.task1; + +/** + * <p>ASCII art related method.</p> + */ +public class D_TextFrame { + + /** + * <p>Arranging a list of strings line by line and surrounding it by a rectangular frame. The following + * example transforms an array containing two strings into a corresponding framed output:</p> + * + * <table class="goikTableDefaults"> + * <caption>ASCII art frame</caption> + * <tbody> + * <tr> + * <th>Code</th> + * <th>Result</th> + * </tr> + * <tr> + * <td> + * <pre><code class="java"> final String[] words = {"This is a first", "sample"}; + * System.out.println(createTextFrame(words));</code></pre> + * </td> + * <td> + * <pre><code class="nohighlight"> ******************* + * * This is a first * + * * sample * + * *******************</code></pre> + * </td> + * </tr> + * </tbody> + * </table> + * + * <p>Note the additional empty spaces »<span style="color:red;font-weight:bold;">_</span>« between each + * starting * and before each ending *:</p> + * + * <pre><code class="nohighlight"> ******************* + * *<span style="color:red;font-weight:bold;">_</span>This is a first<span style="color:red;font-weight:bold;">_</span>* + * *<span style="color:red;font-weight:bold;">_</span>sample <span style="color:red;font-weight:bold;">_</span>* + * *******************</code></pre> + * + * @param strings A non-empty array possibly containing both strings and <code>null</code> values. + * @return An ASCII frame surrounding lines of text. + * + * <section class="implementationHints"> + * <h4 class="implementationHints">Hints:</h4> + * + * <ul> + * <li>You may use {@link B_StringHelper#getMaxLength(String[])} to get the longest + * string length in the list for sizing your frame.</li> + * + * <li>{@link String#repeat(int)} for repeating both <code>"*"</code> and empty spaces <code>" "</code> + * using e.g. <code>"*".repeat(10)</code>.</li> + * + * <li>Watch out for spaces and invisible newlines at end of your returned string. These are difficult to spot + * and may cause tests to fail.</li> + * + * </ul> + * + * </section> + */ + static public String createTextFrame(final String[] strings) { + + + return "***"; // TODO: Implement me correctly + } + + private D_TextFrame(){/* Ignore me: My sole purpose is suppressing default constructor javadoc generation */} +} diff --git a/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/package-info.java b/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..fb7bb58c281c72e0241b31061906c3bf633172d2 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/package-info.java @@ -0,0 +1,17 @@ +/** + * <p>This package mostly (if not completely) contains static methods.</p> + * + * <p>The ordering being implied by class names reflects the author's opinion with respect to ascending implementation + * difficulty. Hints:</p> + * + * <ul> + * <li>Run <code>mvn javadoc:javadoc</code> and open the generated + * <code>/home/.../target/site/apidocs/index.html</code> file in your browser of choice.</li> + * + * <li>Use the corresponding unit tests to check your implementation's consistency and class + * <code>de.hdm_stuttgart.mi.sd1.test.ShowReachedPoints</code> from your project's “unit test†branch.</li> + * + * </ul> + * + */ +package de.hdm_stuttgart.mi.sd1.task1; \ No newline at end of file diff --git a/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task2/QuadratPolynom.java b/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task2/QuadratPolynom.java new file mode 100644 index 0000000000000000000000000000000000000000..6d70260069807d3de29d93c80e5617d9f5f0e208 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task2/QuadratPolynom.java @@ -0,0 +1,142 @@ +package de.hdm_stuttgart.mi.sd1.task2; + +/** + * <p>Providing zeroes (German: "Nullstellen") of quadratic polynomials.</p> + * + * <p>A quadratic polynomial \( p(x) = a x² + b x + c \) is being defined by its three coefficients + * \(a\), \(b\) and \(c\). This class limits coefficients \(a\), \(b\) and \(c\) to type <code>int</code>. A general + * solution is being provided by:</p> + * + * <p>\[ x_{1,2} = {{-b \pm \sqrt{b^2 - 4 ac}} \over {2a}} \]</p> + * + * <p>Depending on \( b^2 - 4 ac \) being positive, zero or negative we have either two, one or no real solutions.</p> + * + * <p>The following sample illustrates zeroes calculation depending on given values of \(a\), \(b\) and \(c\):</p> + * + * <table class="goikTableDefaults"> + * <caption>Sample code illustrating zero values calculation</caption> + * <tbody> + * <tr> + * <th>Code</th> + * <th>Result</th> + * </tr> + * <tr> + * <td> + * <pre><code class="java"> final QuadratPolynom poly = // Representing + * new QuadratPolynom(4, -3, -10); // p(x) = 4x² - 3x - 10 + * + * double[] zeroes = poly.getZeroes(); + * + * System.out.println("Found " + zeroes.length + " zeroes:"); + * + * System.out.println("x_1 = " + zeroes[0]); + * System.out.println("x_2 = " + zeroes[1]);</code></pre> + * </td> + * <td> + * <pre><code class="nohighlight"> Found 2 zeroes: + * x_1 = -1.25 + * x_2 = 2.0</code></pre> + * </td> + * </tr> + * </tbody> + * </table> + * + * <p>We allow for re-setting a polynomial's coefficients. Continuing from the above example we have:</p> + * + * <table class="goikTableDefaults"> + * <caption>Changing coefficients</caption> + * <tbody> + * <tr> + * <th>Code</th> + * <th>Result</th> + * </tr> + * <tr> + * <td> + * <pre><code class="java"> ... + * poly.setA(1); // Representing + * poly.setB(-8); // p(x) = x² -8x + 16 + * poly.setC(16); + * + * zeroes = poly.getZeroes(); + * System.out.println("Found " + zeroes.length + " zero:"); + * + * System.out.println("x_1 = " + zeroes[0]);</code></pre> + * </td> + * <td> + * <pre><code class="nohighlight"> ... + * Found 1 zero: + * x_1 = 4.0</code></pre> + * </td> + * </tr> + * </tbody> + * </table> + * + * <p>Some polynomials do not have any (real valued) solution:</p> + * + * <table class="goikTableDefaults"> + * <caption>Changing coefficients again</caption> + * <tbody> + * <tr> + * <th>Code</th> + * <th>Result</th> + * </tr> + * <tr> + * <td> + * <pre><code class="java"> ... + * poly.setA(1); // Representing + * poly.setB(0); // p(x) = x² + 1 + * poly.setC(1); // (No zero solution) + * + * zeroes = poly.getZeroes(); + * System.out.println("Found " + zeroes.length + " zero");</code></pre> + * </td> + * <td> + * <pre><code class="nohighlight"> ... + * Found 0 zero</code></pre> + * </td> + * </tr> + * </tbody> + * </table> + * + * <p>Finally setting \(a=0\) in \(ax²\) leaves us with just a linear polynomial \(bx + c\). To + * avoid unpredictable results the attempt shall result in throwing an + * <a href="https://freedocs.mi.hdm-stuttgart.de/doc/openjdk-17-doc/api/java.base/java/lang/ArithmeticException.html" + * ><code>ArithmeticException</code></a>:</p> + * + * <table class="goikTableDefaults"> + * <caption>Dealing with 0 value at square coefficient.</caption> + * <tbody> + * <tr> + * <th>Code</th> + * <th>Result</th> + * </tr> + * <tr> + * <td> + * <pre><code class="java"> ... + * poly.setA(0); // Trying to represent p(x) = 1</code></pre> + * </td> + * <td> + * <pre><code class="nohighlight"> ... + * Exception in thread "main" java.lang.ArithmeticException: + * Square coefficient must not be zero</code></pre> + * </td> + * </tr> + * </tbody> + * </table> + * + * <p>Likewise a <code>new QuadratPolynom(0, ..., ...)</code> constructor call setting \(a=0\) shall raise an + * <a href="https://freedocs.mi.hdm-stuttgart.de/doc/openjdk-17-doc/api/java.base/java/lang/ArithmeticException.html"> + * <code>ArithmeticException</code></a> as well.</p> + * + * <section class="implementationHints"> + * <h2 class="implementationHints">Hint:</h2> + * + * <p>This class is yet unimplemented. The above code snippets provide a clue to an implementation + * satisfying the corresponding unit tests.</p> + * + * </section> + */ +public class QuadratPolynom { + // TODO: Implement me + private QuadratPolynom(){/* Ignore me: My sole purpose is suppressing default constructor javadoc generation */} +} diff --git a/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task4_no_unit_test/Mathextend.java b/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task4_no_unit_test/Mathextend.java new file mode 100644 index 0000000000000000000000000000000000000000..f254528aa4b685cf7e60b361601ad2c706284ab4 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task4_no_unit_test/Mathextend.java @@ -0,0 +1,31 @@ +package de.hdm_stuttgart.mi.sd1.task4_no_unit_test; + +/** + * <p>This class corresponds to your examination's task 3. Read its description in your web browser.</p> + * + * <p>In particular no unit tests are being associated with this class.</p> + * + * <p>If you correct the implementation of {@link #getAverage(byte, byte, byte)} using your IDEA IDE please + * <em style="color: red;">do not forget</em> to export and upload your project afterwards.</p> + * + */ +public class Mathextend { + + /** + * <p>Compute the average of three values.</p> + * + * @param a First value + * @param b Second value + * @param c Third value + * + * @return Closest <code>byte</code> value to â…“ (a + b + c) + */ + public static byte getAverage(byte a, final byte b, final byte c) { + a += b; + a += c; + a /= 3; + return a; + } + + private Mathextend(){/* Ignore me: My sole purpose is suppressing default constructor javadoc generation */} +} diff --git a/Klausuren/Sd1/2021winter/Exam/src/main/javadoc/resources/fonts/dejavu.css b/Klausuren/Sd1/2021winter/Exam/src/main/javadoc/resources/fonts/dejavu.css new file mode 100644 index 0000000000000000000000000000000000000000..4fec2b593cdcc719fd7edd6744a33a3395ca8401 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/src/main/javadoc/resources/fonts/dejavu.css @@ -0,0 +1,3 @@ +/* shame on you, javadoc! Still providing +@import url('resources/fonts/dejavu.css') line in stylesheet.css +*/ \ No newline at end of file diff --git a/Klausuren/Sd1/2021winter/Exam/src/main/javadoc/resources/jdocSupplement.css b/Klausuren/Sd1/2021winter/Exam/src/main/javadoc/resources/jdocSupplement.css new file mode 100644 index 0000000000000000000000000000000000000000..9f39b10d8588f548a5a009835cff44add2bdb638 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/src/main/javadoc/resources/jdocSupplement.css @@ -0,0 +1,68 @@ +/* Javadoc extensions: */ + +table.goikTableDefaults, +table.goikTableDefaults>caption, +table.goikTableDefaults>tr>th, +table.goikTableDefaults>tr>td, +table.goikTableDefaults>tbody>tr>th, +table.goikTableDefaults>tbody>tr>td { + border: 2px solid black; + border-collapse: collapse; + padding: 1ex; + vertical-align: top; +} + +table.goikTableDefaults>caption { + /* border-top-style: solid; border-left-style: solid; border-right-style: solid' */ + border-bottom-style: none; + font-weight: bold; + background:#dee3e9; + text-align:left; + padding:8px 3px 3px 7px; +} + +table.goikTableDefaults>tbody>tr>td { + vertical-align:top; +} +table.goikTableDefaults { + border-spacing: 0px !important; +} + +table.indexTable { + border-collapse: collapse; + border-style: hidden; +} + +table.indexTable caption { + text-align: left; +} + +table.indexTable td, table.indexTable th { + border: 1px solid black; + padding: 0.5ex; +} + +em { + font-weight: bold; + font-style: normal; +} +section.implementationHints>h3 { + font-weight: bold; + background-color: rgb(222, 227, 233); +} + +code { + white-space: pre; +} + +.implementationHints { + background-color: hsl(120, 100%, 95%) !important; +} + +.myRed { + color: red; +} + +.myGreen { + color: limegreen; +} diff --git a/Klausuren/Sd1/2021winter/Exam/src/main/javadoc/resources/jdocSupplement.js b/Klausuren/Sd1/2021winter/Exam/src/main/javadoc/resources/jdocSupplement.js new file mode 100644 index 0000000000000000000000000000000000000000..97911e5581090aac5e37323427450f8c8c8a3f94 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/src/main/javadoc/resources/jdocSupplement.js @@ -0,0 +1,7 @@ +for(var i in document.links) { + var link = document.links[i]; + if (link.href && link.href.indexOf('http') === 0) { + link.target = '_blank'; + } +} + diff --git a/Klausuren/Sd1/2021winter/Exam/src/main/resources/log4j2.xml b/Klausuren/Sd1/2021winter/Exam/src/main/resources/log4j2.xml new file mode 100644 index 0000000000000000000000000000000000000000..130f87a144c4eb0107a846e580c8fa7f5e819fc1 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/src/main/resources/log4j2.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration> + <Appenders> + <File name="A1" fileName="A1.log" append="false"> + <PatternLayout pattern="%t %-5p %c{2} - %m%n"/> + </File> + <Console name="STDOUT" target="SYSTEM_OUT"> + <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> + </Console> + </Appenders> + <Loggers> + + <!-- You my want to define class or package level per-logger rules --> + <Logger name="de.hdm_stuttgart.mi.sd1.App" level="debug"> + <AppenderRef ref="A1"/> + </Logger> + <Root level="info"> + <AppenderRef ref="STDOUT"/> + </Root> + </Loggers> +</Configuration> \ No newline at end of file diff --git a/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/ShowReachedPoints.java b/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/ShowReachedPoints.java new file mode 100644 index 0000000000000000000000000000000000000000..ae8720eb01d5a8631b073dc214bfd936ef4eb9cb --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/ShowReachedPoints.java @@ -0,0 +1,22 @@ +package de.hdm_stuttgart.mi.sd1; + +import de.hdm_stuttgart.mi.exam.unitmarking.RunTests; + +import de.hdm_stuttgart.mi.sd1.task1.*; +import de.hdm_stuttgart.mi.sd1.task2.Test_QuadratPolynom; + +public class ShowReachedPoints { + + /** + * Revealing total number of reached points fromm all tasks. + * + * @param args Unused + */ + public static void main(String[] args) { + RunTests.exec( + "Task 1" + , A_TrafficLightTest.class, B_StringHelperTest.class, C_ArrayHelperTest.class, D_TextFrameTest.class + ); + RunTests.exec("Task 2", Test_QuadratPolynom.class); + } +} \ No newline at end of file diff --git a/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/ignore_me/ObjectWrapper.java b/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/ignore_me/ObjectWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..85ea78ca4b9c3fd5a617f4074b1d0a4c9b847d54 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/ignore_me/ObjectWrapper.java @@ -0,0 +1,231 @@ +package de.hdm_stuttgart.mi.sd1.ignore_me; + +import org.junit.Assert; + +import java.lang.reflect.*; +import java.util.Arrays; +import java.util.stream.Collectors; + +public class ObjectWrapper<T> { + + private final Class classz; + private final T instance; + + static public void assertFinal(final Class classZ, final String fieldName) { + try { + final int modifier = classZ.getDeclaredField(fieldName).getModifiers(); + Assert.assertTrue("»" + fieldName + "« can be modified, no immutable!", Modifier.isFinal(modifier)); + + } catch (NoSuchFieldException e) { + Assert.fail("No such field »" + fieldName + "«"); + } + } + + public ObjectWrapper(final Class<T> classz, final Object ... parameter) { + this.classz = classz; + T tmpInstance = null; + final Constructor<?>[] candidates = Arrays. + stream(classz.getConstructors()). + filter(c -> matchesArgumentList(c, parameter)). + toArray(Constructor<?>[]::new); + if (0 == candidates.length) { + Assert.fail("No suitable constructor in class »" + classz.getName() + "« matching arguments »(" + + Arrays.stream(parameter).map(Object::toString).collect(Collectors.joining(", ")) + + ")«"); + } else if (1 < candidates.length) { + Assert.fail("Multiple constructor matches due to ambiguous signature"); + } else { + try { + tmpInstance = (T) candidates[0].newInstance( + Arrays.stream(parameter).toArray()); + } catch (Exception e) { + Assert.fail("Unable to instantiate instance of class »" + classz.getName() + "«: "+ e); + } + } + instance = tmpInstance; + } + + public ObjectWrapper(final Class<T> classz, final Class<? extends Throwable> expectedException, final Object ... parameter) { + this.classz = classz; + T tmpInstance = null; + final Constructor<?>[] candidates = Arrays. + stream(classz.getConstructors()). + filter(c -> matchesArgumentList(c, parameter)). + toArray(Constructor<?>[]::new); + if (0 == candidates.length) { + Assert.fail("No suitable constructor in class »" + classz.getName() + "« matching arguments »(" + + Arrays.stream(parameter).map(Object::toString).collect(Collectors.joining(", ")) + + ")«"); + } else if (1 < candidates.length) { + Assert.fail("Multiple constructor matches due to ambiguous signature"); + } else { + try { + tmpInstance = (T) candidates[0].newInstance( + Arrays.stream(parameter).toArray()); + Assert.fail("Expected exception of type »" + expectedException.getName() + "« to be thrown"); + } catch (InstantiationException|IllegalAccessException|IllegalArgumentException|InvocationTargetException e) { + if (e.getCause().getClass() != expectedException) { + Assert.fail("Unable to instantiate: " + e + ", cause:\n Expected exception of type »" + + expectedException.getName() + "« but was »"+ e.getCause().getClass().getName() + "«"); + } + } + } + instance = tmpInstance; + } + + public <R> void assertFieldExists(final Class<R> valueType, final String name) { + try { + final Field field = classz.getField(name); + if (!valueType.equals(field.getType())) { + Assert.fail("Field »" + name + "« in class »" + classz.getName() + "« is not of type »" + + valueType.getName() + "«"); + } + } catch (final NoSuchFieldException e) { + Assert.fail("No such field »" + name + "« in class »" + classz.getName() + "«"); + } + } + + public <R> R get(final Class<R> valueType, final String name) { + + try { + final Field field = classz.getField(name); + if (valueType.equals(field.getType())) { + return (R) field.get(instance); + } else { + Assert.fail("Field »" + name + "« in class »" + classz.getName() + "« is not of type »" + + valueType.getName() + "«"); + } + } catch (final NoSuchFieldException e) { + Assert.fail("No such field »" + name + "« in class »" + classz.getName() + "«"); + } catch (final IllegalAccessException e) { + Assert.fail("Unable to access field »" + name + "« in class »" + classz.getName() + "«: " + e.getMessage()); + } + return null; + } + public void set(final String name, final Object value) { + + try { + final Field field = classz.getField(name); + final Class argumentType = value.getClass(); + if (field.getType().equals(argumentType) || + field.getType().equals(getPrimitiveType(argumentType))){ + field.set(instance, value); + } else { + Assert.fail("Field »" + name + "« in class »" + classz.getName() + "« is not of type »" + + argumentType.getName() + "«"); + } + } catch (final NoSuchFieldException e) { + Assert.fail("No such field »" + name + "« in class »" + classz.getName() + "«"); + } catch (final IllegalAccessException e) { + Assert.fail("Unable to access field »" + name + "« in class »" + classz.getName() + "«: " + e.getMessage()); + } + } + + public <R> R invoke(final Class<R> returnType, final String name, final Object ... parameter) { + + final Method[] candidates = Arrays. + stream(classz.getMethods()). + filter(m-> m.getName().equals(name) && matchesArgumentList(m, parameter)). + toArray(Method[]::new); + + if (0 == candidates.length) { + Assert.fail("No suitable method found"); + } else if (1 < candidates.length) { + Assert.fail("Multiple method matches due to ambiguous signature"); + } else { + final Method method = candidates[0]; + if (method.getReturnType().equals(returnType)) { + try { + return (R) method.invoke(instance, parameter); + } catch (final IllegalAccessException| IllegalArgumentException|InvocationTargetException e) { + Assert.fail("Unable to execute method: " + e + ", cause:" + e.getCause()); + } + } else { + Assert.fail("Method »" + method.getName() + "« does have return type »" + method.getReturnType() + "«" + + "rather then »" + returnType.getName() + "«"); + } + } + return null; + } + public <R> R invoke(final Class<R> returnType, final String name, + final Class<? extends Throwable> expectedException, final Object ... parameter) { + + final Method[] candidates = Arrays. + stream(classz.getMethods()). + filter(m-> m.getName().equals(name) && matchesArgumentList(m, parameter)). + toArray(Method[]::new); + + if (0 == candidates.length) { + Assert.fail("No suitable method found"); + } else if (1 < candidates.length) { + Assert.fail("Multiple method matches due to ambiguous signature"); + } else { + final Method method = candidates[0]; + if (method.getReturnType().equals(returnType)) { + try { + R ret = (R) method.invoke(instance, parameter); + Assert.fail("Expected exception of type »" + expectedException.getName() + "«"); + return ret; + } catch (final IllegalAccessException| IllegalArgumentException|InvocationTargetException e) { + if (e.getCause().getClass() != expectedException) { + Assert.fail("Unable to execute method: " + e + ", cause:\n Expected exception of type »" + + expectedException.getName() + "« but was »"+ e.getCause().getClass().getName() + "«"); + } + } + } else { + Assert.fail("Method »" + method.getName() + "« does have return type »" + method.getReturnType() + "«" + + "rather then »" + returnType.getName() + "«"); + } + } + return null; + } + + /** + * Check for a given array of objects matching an {@link Executable}'s argument list. + * + * @param executable + * @param parameter + * @return <code>true</code> if parameters match the {@link Executable}'s argument list, <code>false</code> + * otherwise. + */ + private boolean matchesArgumentList(final Executable executable, final Object ... parameter) { + + if (executable.getParameterCount() != parameter.length) { + return false; + } else { + final Class<?>[] formalArgumentTypes = executable.getParameterTypes(); + for (int i = 0; i < formalArgumentTypes.length; i++) { + final Class parametersClass = parameter[i].getClass(); + + if (!formalArgumentTypes[i].equals(parametersClass) && + !formalArgumentTypes[i].equals(getPrimitiveType(parametersClass))) { + return false; + } + } + } + return true; + } + + static private Class<?> getPrimitiveType (final Class<?> in) { + if (in.equals(Byte.class)) { + return byte.class; + } else if (in.equals(Short.class)) { + return short.class; + } else if (in.equals(Integer.class)) { + return int.class; + } else if (in.equals(Long.class)) { + return long.class; + } else if (in.equals(Float.class)) { + return float.class; + } else if (in.equals(Double.class)) { + return double.class; + } else if (in.equals(Boolean.class)) { + return boolean.class; + } else if (in.equals(Character.class)) { + return char.class; + } else { + return in; // Type is no primitive + } + } + +} diff --git a/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task1/A_TrafficLightTest.java b/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task1/A_TrafficLightTest.java new file mode 100644 index 0000000000000000000000000000000000000000..fae220dd2d62ef8ccffc094d3863399d47390bf7 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task1/A_TrafficLightTest.java @@ -0,0 +1,25 @@ +package de.hdm_stuttgart.mi.sd1.task1; + +import de.hdm_stuttgart.mi.exam.unitmarking.ExaminationTestDefaults; +import de.hdm_stuttgart.mi.exam.unitmarking.Marking; +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import static de.hdm_stuttgart.mi.sd1.task1.A_TrafficLight.mustStop; + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class A_TrafficLightTest extends ExaminationTestDefaults { + + @Test + @Marking(points = 16) + public void test_100() { + Assert.assertTrue( mustStop(true, false, false)); // Red :Stop + Assert.assertFalse(mustStop(true, true, false)); // Red + yellow :Go + + Assert.assertFalse(mustStop(false, false, true)); // Green :Go + Assert.assertTrue( mustStop(false, true, false)); // Yellow :Stop + } +} diff --git a/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task1/B_StringHelperTest.java b/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task1/B_StringHelperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..176ccc7edd646b1dfcf790344f63bda7af9fa981 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task1/B_StringHelperTest.java @@ -0,0 +1,37 @@ +package de.hdm_stuttgart.mi.sd1.task1; + +import de.hdm_stuttgart.mi.exam.unitmarking.ExaminationTestDefaults; +import de.hdm_stuttgart.mi.exam.unitmarking.Marking; +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import static de.hdm_stuttgart.mi.sd1.task1.B_StringHelper.getMaxLength; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class B_StringHelperTest extends ExaminationTestDefaults { + + @Test + @Marking(points = 2) + public void test_100_minimum() { + Assert.assertEquals(0, getMaxLength(new String[]{null})); + Assert.assertEquals(0, getMaxLength(new String[]{""})); + } + + @Test + @Marking(points = 6) + public void test_200_single() { + Assert.assertEquals(1, getMaxLength(new String[]{"a"})); + Assert.assertEquals(11, getMaxLength(new String[]{"csd wde dwe"})); + } + + @Test + @Marking(points = 6) + public void test_300_multi() { + Assert.assertEquals(1, getMaxLength(new String[]{"a", "b", "c"})); + Assert.assertEquals(5, getMaxLength(new String[]{"Eve", "Peter", "Jill", "Tom"})); + Assert.assertEquals(12, getMaxLength(new String[]{"Looooooooong", "Loooooong", null, "Looong", null})); + Assert.assertEquals(12, getMaxLength(new String[]{null, "Loooooong", "Looooooooong", "Looong", null})); + } +} diff --git a/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task1/C_ArrayHelperTest.java b/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task1/C_ArrayHelperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..bb48553fe9ee6b9b886ea513643a3dfad017603a --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task1/C_ArrayHelperTest.java @@ -0,0 +1,42 @@ +package de.hdm_stuttgart.mi.sd1.task1; + +import de.hdm_stuttgart.mi.exam.unitmarking.ExaminationTestDefaults; +import de.hdm_stuttgart.mi.exam.unitmarking.Marking; +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import static de.hdm_stuttgart.mi.sd1.task1.C_ArrayHelper.getAboveAverage; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class C_ArrayHelperTest extends ExaminationTestDefaults { + + @Test + @Marking(points = 2) + public void test_100_minimum() { + Assert.assertArrayEquals(new int[]{}, getAboveAverage(new int[]{1})); + } + + @Test + @Marking(points = 4) + public void test_200_equal() { + Assert.assertArrayEquals(new int[]{}, getAboveAverage(new int[]{20, 20})); + Assert.assertArrayEquals(new int[]{}, getAboveAverage(new int[]{7, 7, 7, 7})); + } + + @Test + @Marking(points = 4) + public void test_200_regular() { + Assert.assertArrayEquals(new int[]{1}, getAboveAverage(new int[]{1, 0})); + Assert.assertArrayEquals(new int[]{1}, getAboveAverage(new int[]{0, 1})); + Assert.assertArrayEquals(new int[]{5, 4}, getAboveAverage(new int[]{1, 2, 3, 5, 4})); + Assert.assertArrayEquals(new int[]{55, 100}, getAboveAverage(new int[]{-30, 2, 4, 55, 100, 9})); + } + + @Test + @Marking(points = 2) + public void test_200_big() { + Assert.assertArrayEquals(new int[]{Integer.MAX_VALUE, Integer.MAX_VALUE}, getAboveAverage(new int[]{Integer.MAX_VALUE, Integer.MAX_VALUE, 0})); + } +} diff --git a/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task1/D_TextFrameTest.java b/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task1/D_TextFrameTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c003f80e721e6719eb7e378e8fff83291909dcf6 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task1/D_TextFrameTest.java @@ -0,0 +1,89 @@ +package de.hdm_stuttgart.mi.sd1.task1; + +import de.hdm_stuttgart.mi.exam.unitmarking.ExaminationTestDefaults; +import de.hdm_stuttgart.mi.exam.unitmarking.Marking; +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import static de.hdm_stuttgart.mi.sd1.task1.D_TextFrame.createTextFrame; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class D_TextFrameTest extends ExaminationTestDefaults { + + @Test + @Marking(points = 2) + public void test_100_minimum() { + + final String expected = """ + **** + * * + ****"""; + + Assert.assertEquals(expected, createTextFrame(new String[]{null})); + Assert.assertEquals(expected, createTextFrame(new String[]{""})); + } + + @Test + @Marking(points = 2) + public void test_200_one() { + + { + final String expected = """ + ***** + * * + *****"""; + + Assert.assertEquals(expected, createTextFrame(new String[]{" "})); + } + { + final String expected = """ + ***** + * j * + *****"""; + + Assert.assertEquals(expected, createTextFrame(new String[]{"j"})); + } + } + + @Test + @Marking(points = 2) + public void test_300_multi() { + + { + final String expected = """ + ****************** + * This is a very * + * simple test. * + ******************"""; + + Assert.assertEquals(expected, createTextFrame(new String[]{"This is a very", "simple test."})); + } + { + final String expected = """ + ******************* + * An example * + * featuring three * + * lines * + *******************"""; + + Assert.assertEquals(expected, createTextFrame(new String[]{"An example", "featuring three", "lines"})); + } + } + + @Test + @Marking(points = 2) + public void test_400_null() { + + final String expected = """ + ********************** + * Sometimes there is * + * * + * a hole. * + * * + **********************"""; + + Assert.assertEquals(expected, createTextFrame(new String[]{"Sometimes there is", null, "a hole.", null})); + } +} diff --git a/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task2/Test_QuadratPolynom.java b/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task2/Test_QuadratPolynom.java new file mode 100644 index 0000000000000000000000000000000000000000..055651ad7c3b63499d3c38874807b674c43985a0 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task2/Test_QuadratPolynom.java @@ -0,0 +1,226 @@ +package de.hdm_stuttgart.mi.sd1.task2; + +import de.hdm_stuttgart.mi.exam.unitmarking.ExaminationTestDefaults; +import de.hdm_stuttgart.mi.exam.unitmarking.Marking; +import de.hdm_stuttgart.mi.sd1.ignore_me.ObjectWrapper; +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) + +public class Test_QuadratPolynom extends ExaminationTestDefaults { + + @Test + @Marking(points = 5) + public void test_100_NoZero() { + final ObjectWrapper<QuadratPolynom> poly = new ObjectWrapper<>(QuadratPolynom.class,1, 1, 1); + assertNoZero(poly, composeDescription(1,2,1).toString()); + + final ObjectWrapper<QuadratPolynom> poly2 = new ObjectWrapper<>(QuadratPolynom.class,1, 2, 3); + assertNoZero(1, 6, 20, poly2); + assertNoZero(2, 13, 41, poly2); + } + + @Test + @Marking(points = 5) + public void test_200_OneZero() { + final ObjectWrapper<QuadratPolynom> poly = new ObjectWrapper<>(QuadratPolynom.class,1, 2, 1); + assertOneZero(poly, -1, composeDescription(1,2,1).toString()); + + final ObjectWrapper<QuadratPolynom> poly2 = new ObjectWrapper<>(QuadratPolynom.class,1, 2, 3); + assertOneZero(6, -84, 294, poly2, 7); + assertOneZero(21, 126, 189, poly2, -3); + } + + @Test + @Marking(points = 5) + public void test_300_twoZeroes() { + + final ObjectWrapper<QuadratPolynom> poly = new ObjectWrapper<>(QuadratPolynom.class,1, 3, 2); + assertTwoZeroes(poly, -2, -1, "x² + 3x + 2"); + + assertTwoZeroes(3, 7, 4, poly, -4./3, -1); + + assertTwoZeroes(-2, 1, 3, poly, -1, 1.5); + + assertTwoZeroes(-1, 5, 6, poly, -1, 6); + + assertTwoZeroes(7, 11, 4, poly, -1, -4./7); + + assertTwoZeroes(4, -3, -10, poly, -1.25, 2); + + assertTwoZeroes(5, 6, 1, poly, -1, -0.2); + + } + + @Test + @Marking(points = 2) + public void test_400_Exception() { + final ObjectWrapper<QuadratPolynom> poly = new ObjectWrapper<>(QuadratPolynom.class,1, -200, 2); + + final Class<ArithmeticException> expectedArithmeticException = ArithmeticException.class; + + // Coefficient ax² must not be 0 + poly.invoke(void.class, "setA", expectedArithmeticException, 0); + new ObjectWrapper<>(QuadratPolynom.class, expectedArithmeticException, 0, 88, 99); + } + + @Test + @Marking(points = 3) + public void test_500_TwoZeroExzess() { + final ObjectWrapper<QuadratPolynom> poly = new ObjectWrapper<>(QuadratPolynom.class, + 46010, 598130,-1960026000); + assertTwoZeroes(poly,-213,200, + composeDescription(46010, 598130,-1960026000).toString()); + } + + // End of tests ------------------------------------------------------------------------------------------------- + // Test helper methods + // + static private final double delta = 1.E-12; + + static private StringBuffer composeDescription(final int a, final int b, final int c) { + final StringBuffer ret = new StringBuffer(); + ret.append(a).append("x²"); + if (0 < b) { + ret.append(" + ").append(b).append("x"); + } else if (b < 0) { + ret.append(" ").append(b).append("x"); + } + // Slight code duplication avoiding a method definition. Yepp: I'm lazy sometimes! + if (0 < c) { + ret.append(" + ").append(c); + } else if (c < 0) { + ret.append(" ").append(c); + } + return ret; + } + + /** + * Testing given polynomial for no real zero value. + * + * @param poly Polynomial to be tested + * @param description E.g. "-2x² + 4x -3" + */ + static private void assertNoZero(final ObjectWrapper<QuadratPolynom> poly, final String description) { + + Assert.assertEquals("No zero expected for polynom »" + description + "«", + 0, poly.invoke(double[].class, "getZeroes").length); + } + + /** + * Testing for no real valued zero solution. + * + * @param a Square coefficient + * @param b Linear coefficient + * @param c Constant coefficient + * @param poly Square polynomial + */ + static private void assertNoZero(final int a, + final int b, + final int c, + final ObjectWrapper<QuadratPolynom> poly) { + poly.invoke(void.class, "setA", a); + poly.invoke(void.class, "setB", b); + poly.invoke(void.class, "setC", c); + Assert.assertEquals("One zero expected for polynom »" + composeDescription(a, b, c) + "«", + 0, poly.invoke(double[].class, "getZeroes").length); + + + } + + /** + * Testing given polynomial for one zeroes to be returned + * + * @param poly Polynomial to be tested + * @param expected zero value + * @param description E.g. "-2x² + 4x -3" + */ + static private void assertOneZero(final ObjectWrapper<QuadratPolynom> poly, + double expected, + final String description) { + final double[] result = poly.invoke(double[].class, "getZeroes"); + + Assert.assertEquals("One zero expected for polynom »" + description + "«", + 1, result.length); + Assert.assertEquals("Expected zero of »" + description +"« to be " + expected, expected, result[0], delta); + } + + /** + * Like {@link #assertOneZero(ObjectWrapper, double, String)} but re-setting coefficients beforehand, + * @param a Square coefficient + * @param b Linear coefficient + * @param c Constant coefficient + * @param poly Square polynomial + */ + static private void assertOneZero(final int a, + final int b, + final int c, + final ObjectWrapper<QuadratPolynom> poly, + double expected) { + poly.invoke(void.class, "setA", a); + poly.invoke(void.class, "setB", b); + poly.invoke(void.class, "setC", c); + final double[] result = poly.invoke(double[].class, "getZeroes"); + + final StringBuffer polynomDescription = composeDescription(a, b, c); + + Assert.assertEquals(2 + " zeroes expected for polynom »" + polynomDescription + "«", + 1, result.length); + Assert.assertEquals("Expected zero of »" + polynomDescription +"« to be " + expected, + expected, result[0], delta); + } + + /** + * Testing given polynomial for two zeroes to be returned + * + * @param poly Polynomial to be tested + * @param expectedLower Lower zero value + * @param expectedUpper Upper zero value + * @param description E.g. "-2x² + 4x -3" + */ + static private void assertTwoZeroes(final ObjectWrapper<QuadratPolynom> poly, + double expectedLower, + double expectedUpper, + final String description) { + final double[] result = poly.invoke(double[].class, "getZeroes"); + + Assert.assertEquals(2 + " zeroes expected for polynom »" + description + "«", + 2, result.length); + Assert.assertEquals("Expected lower zero of »" + description +"« to be " + expectedLower, + expectedLower, result[0], delta); + Assert.assertEquals("Expected upper zero of »" + description +"« to be " + expectedUpper, + expectedUpper, result[1], delta); + } + + /** + * Like {@link #assertTwoZeroes(ObjectWrapper, double, double, String)} but re-setting coeficients beforehand, + * @param a Square coefficient + * @param b Linear coefficient + * @param c Constant coefficient + * @param poly Square polynomial + * @param expectedLower Expected lower zero value + * @param expectedUpper Expected upper zero value + */ + static private void assertTwoZeroes(final int a, + final int b, + final int c, + final ObjectWrapper<QuadratPolynom> poly, + double expectedLower, + double expectedUpper) { + poly.invoke(void.class, "setA", a); + poly.invoke(void.class, "setB", b); + poly.invoke(void.class, "setC", c); + final double[] result = poly.invoke(double[].class, "getZeroes"); + + final StringBuffer polynomDescription = composeDescription(a, b, c); + + Assert.assertEquals(2 + " zeroes expected for polynom »" + polynomDescription + "«", + 2, result.length); + Assert.assertEquals("Expected lower zero of »" + polynomDescription +"« to be " + expectedLower, + expectedLower, result[0], delta); + Assert.assertEquals("Expected upper zero of »" + polynomDescription +"« to be " + expectedUpper, + expectedUpper, result[1], delta); + } +} diff --git a/Klausuren/Sd1/2021winter/Solve/Doc/wurzel.ods b/Klausuren/Sd1/2021winter/Solve/Doc/wurzel.ods new file mode 100644 index 0000000000000000000000000000000000000000..2a290ccd9f4fabf32cf1218c4fcba096fcb485fe Binary files /dev/null and b/Klausuren/Sd1/2021winter/Solve/Doc/wurzel.ods differ diff --git a/Klausuren/Sd1/2021winter/Solve/pom.xml b/Klausuren/Sd1/2021winter/Solve/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..d447ccb00fc387853f947291ef8eca915d550103 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/pom.xml @@ -0,0 +1,130 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>de.hdm-stuttgart.mi.sd1</groupId> + <artifactId>sd1_2021winter_solve</artifactId> + <version>0.9</version> + <packaging>jar</packaging> + + <name>sd1_2021winter_solve</name> + + <url>https://freedocs.mi.hdm-stuttgart.de/sd1_sect_mavenCli.html</url> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + + <maven.compiler.target>17</maven.compiler.target> + <maven.compiler.source>17</maven.compiler.source> + + <freedocs.url>https://freedocs.mi.hdm-stuttgart.de</freedocs.url> + <jdk.api_17.url>${freedocs.url}/doc/openjdk-17-doc/api/</jdk.api_17.url> + <mathjax.url>${freedocs.url}/mathjax/MathJax.js?config=TeX-AMS-MML_HTMLorMML</mathjax.url> + <libhighlight.url>${freedocs.url}/lib/highlight.js</libhighlight.url> + </properties> + + <repositories> + <repository> + <id>hdm-mi-internal-maven-repo</id> + <url>https://maven.mi.hdm-stuttgart.de/nexus/repository/mi-maven</url> + </repository> + </repositories> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.13.2</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-core</artifactId> + <version>2.17.1</version> + </dependency> + + <dependency> + <groupId>de.hdm_stuttgart.mi.exam</groupId> + <artifactId>unitmarking</artifactId> + <version>1.1</version> + </dependency> + + </dependencies> + + <build> + <plugins> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.1</version> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>3.3.0</version> + + <configuration> + <!-- Tweak: Get rid of Error message + »fetching link: .../target/javadoc-bundle-options. Ignored it« + corresponding to api_11 below --> + <release>11</release> + <doclint>all</doclint> + <show>public</show> + <docfilessubdirs>true</docfilessubdirs> + <addStylesheets> + <stylesheet>resources/jdocSupplement.css</stylesheet> + </addStylesheets> + + <javaApiLinks> + <property> + <name>api_11</name> + <value>${jdk.api_17.url}</value> + </property> + </javaApiLinks> + + <additionalOptions> + <additionalOption>-html5 --allow-script-in-comments</additionalOption> + </additionalOptions> + <nohelp>true</nohelp> + + <header><![CDATA[ + <script type="text/javascript" src="${mathjax.url}"></script> + <script type="text/javascript" src="{@docRoot}/resources/jdocSupplement.js"></script> + <link rel="stylesheet" href="${libhighlight.url}/styles/idea.css"> + <script src="${libhighlight.url}/highlight.js"></script> + <script type="text/javascript">hljs.initHighlightingOnLoad();</script>]]> + </header> + </configuration> + </plugin> + + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <version>3.3.0</version> + <configuration> + <descriptors> + <descriptor>src/main/assembly/assembly.xml</descriptor> + </descriptors> + </configuration> + <executions> + <execution> + <id>make-assembly</id> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + <configuration> + <archive> + <manifest> + <mainClass>de.hdm_stuttgart.mi.sd1.ShowReachedPoints</mainClass> + </manifest> + </archive> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/Klausuren/Sd1/2021winter/Solve/src/main/assembly/assembly.xml b/Klausuren/Sd1/2021winter/Solve/src/main/assembly/assembly.xml new file mode 100644 index 0000000000000000000000000000000000000000..85268e2965620878373d76337f524d8785fd0e1f --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/src/main/assembly/assembly.xml @@ -0,0 +1,36 @@ +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd"> + <id>fat-tests</id> + <formats> + <format>jar</format> + </formats> + <includeBaseDirectory>false</includeBaseDirectory> + <dependencySets> + <dependencySet> + <outputDirectory/> + <useProjectArtifact>true</useProjectArtifact> + <unpack>true</unpack> + <scope>test</scope> + </dependencySet> + </dependencySets> + <fileSets> + <fileSet> + <directory>${project.build.directory}/test-classes</directory> + <outputDirectory/> + <includes> + <include>**/*.class</include> + </includes> + <useDefaultExcludes>true</useDefaultExcludes> + </fileSet> + <fileSet> + <directory>${project.build.directory}/classes</directory> + <outputDirectory/> + <includes> + <include>**/*.class</include> + </includes> + <useDefaultExcludes>true</useDefaultExcludes> + </fileSet> + </fileSets> +</assembly> \ No newline at end of file diff --git a/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/A_TrafficLight.java b/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/A_TrafficLight.java new file mode 100644 index 0000000000000000000000000000000000000000..fff60a3b2d83150fb2fc56fd2b78df5d5812aeec --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/A_TrafficLight.java @@ -0,0 +1,66 @@ +package de.hdm_stuttgart.mi.sd1.task1; + +/** + * <p>Stop and go at trafficlights.</p> + */ +public class A_TrafficLight { + /** + * <p>Traffic light stop / go indications.</p> + * + * <p>German traffic lights feature three different colours red, yellow and green. We assume the following rules:</p> + * + * <table style="border-spacing: 10ex 0;"> + * <caption>German traffic light states</caption> + * <tr> + * <td + * style="border: 2px solid black;border-radius: 10px;font-size:40px;background:black;"> + * <ul> + * <li style="color:red;"></li> + * <li style="color:black;"></li> + * <li style="color:black;"></li> + * </ul> + * </td> + * <td style="border: 2px solid black;border-radius: 10px;font-size:40px;background:black;"> + * <ul> + * <li style="color:red;"></li> + * <li style="color:yellow;"></li> + * <li style="color:black;"></li> + * </ul> + * </td> + * <td style="border: 2px solid black;border-radius: 10px;font-size:40px;background:black;"> + * <ul> + * <li style="color:black;"></li> + * <li style="color:black;"></li> + * <li style="color:green;"></li> + * </ul> + * </td> + * <td style="border: 2px solid black;border-radius: 10px;font-size:40px;background:black;"> + * <ul> + * <li style="color:black;"></li> + * <li style="color:yellow;"></li> + * <li style="color:black;"></li> + * </ul> + * </td> + * </tr> + * <tr> + * <td>Stop</td> + * <td>Go</td> + * <td>Go</td> + * <td>Stop</td> + * </tr> + * + * </table> + * + * @param red <code>true</code> represents »on«, <code>false</code> represents »off«. + * @param yellow <code>true</code> represents »on«, <code>false</code> represents »off«. + * @param green <code>true</code> represents »on«, <code>false</code> represents »off«. + * + * @return <code>true</code> represents »you must stop«, <code>false</code> represents »go«. + */ + static public boolean mustStop(boolean red, boolean yellow, boolean green) { + return (red && !yellow) || (yellow && !red); + } + + private A_TrafficLight(){/* Ignore me: My sole purpose is suppressing default constructor javadoc generation */} + +} diff --git a/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/B_StringHelper.java b/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/B_StringHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..7b3910a4db5c08780364969dd62d8abcf8d5027b --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/B_StringHelper.java @@ -0,0 +1,49 @@ +package de.hdm_stuttgart.mi.sd1.task1; + +/** + * String related helper method. Currently {@link #getMaxLength(String[])} is on offer. + */ +public class B_StringHelper { + + /** + * <p>Get the maximum string length among an array of strings. In the following example the longest of three + * strings is <code class="java">"Longman"</code> having length 7:</p> + * + * <table class="goikTableDefaults"> + * <caption>Finding the longest string</caption> + * <tbody> + * <tr> + * <th>Code</th> + * <th>Result</th> + * </tr> + * <tr> + * <td> + * <pre><code class="java"> final String[] names = + * {"Eve", "Longman", "Peter"}; + * + * System.out.println("Longest name's length: " + + * getMaxLength(names));</code></pre> + * </td> + * <td> + * <pre><code class="nohighlight"> Longest name's length: 7</code></pre> + * </td> + * </tr> + * </tbody> + * </table> + * + * @param strings A non-empty array possibly containing both strings and <code>null</code> values. + * @return The greatest length of all strings. <code>null</code> values will be treated like empty strings. + */ + static public int getMaxLength(final String[] strings) { + int maxLength = 0; + for (final String s: strings) { + if (null != s) { + maxLength = Math.max(maxLength, s.length()); + } + } + return maxLength; + } + + private B_StringHelper(){/* Ignore me: My sole purpose is suppressing default constructor javadoc generation */} + +} diff --git a/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/C_ArrayHelper.java b/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/C_ArrayHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..5997a5dc40787b30d40891b0918f437be41086d1 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/C_ArrayHelper.java @@ -0,0 +1,61 @@ +package de.hdm_stuttgart.mi.sd1.task1; + +import java.util.Arrays; + +/** + * <p>Array related helper method</p> + */ +public class C_ArrayHelper { + + /** + * <p>Collect all values from a given array being above its average value. The following example + * features an array of five values resulting in an average of 6. Only the values 8, 12 and 8 + * are strictly above average:</p> + * + * <table class="goikTableDefaults"> + * <caption>Finding values above average</caption> + * <tbody> + * <tr> + * <th>Code</th> + * <th>Result</th> + * </tr> + * <tr> + * <td> + * <pre><code class="java"> final int[] values = {-4, 6, 8, 12, 8}; + * System.out.println( "Above average: " + + * Arrays.toString(getAboveAverage(values)));</code></pre> + * </td> + * <td> + * <pre><code class="nohighlight"> Above average: [8, 12, 8] </code></pre> + * </td> + * </tr> + * </tbody> + * </table> + * + * @param values A list of values. + * @return All values from the list being strictly above the list's average thereby preserving + * the original array's order of appearance. + */ + static public int[] getAboveAverage (int[] values) { + + final int length = values.length; + long sum = 0; + + for (final int v: values) { + sum += v; + } + + final int[] result = new int[length]; + int index = 0; + + for (final int vTmp: values) { + final long v = vTmp; // Tribute to values exceeding Integer.INT_MAX + if (sum < length * v) { + result[index++] = vTmp; + } + } + return Arrays.copyOf(result, index); + } + private C_ArrayHelper(){/* Ignore me: My sole purpose is suppressing default constructor javadoc generation */} + +} diff --git a/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/D_TextFrame.java b/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/D_TextFrame.java new file mode 100644 index 0000000000000000000000000000000000000000..d6cb4dd86b9c7aea7f47c8e0f1273b81e6f63d9e --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/D_TextFrame.java @@ -0,0 +1,77 @@ +package de.hdm_stuttgart.mi.sd1.task1; + + +/** + * <p>ASCII art related method.</p> + */ +public class D_TextFrame { + + /** + * <p>Arranging a list of strings line by line and surrounding it by a rectangular frame. The following + * example transforms an array containing two strings into a corresponding framed output:</p> + * + * <table class="goikTableDefaults"> + * <caption>ASCII art frame</caption> + * <tbody> + * <tr> + * <th>Code</th> + * <th>Result</th> + * </tr> + * <tr> + * <td> + * <pre><code class="java"> final String[] words = {"This is a first", "sample"}; + * System.out.println(createTextFrame(words));</code></pre> + * </td> + * <td> + * <pre><code class="nohighlight"> ******************* + * * This is a first * + * * sample * + * *******************</code></pre> + * </td> + * </tr> + * </tbody> + * </table> + * + * <p>Note the additional empty spaces »<span style="color:red;font-weight:bold;">_</span>« between each + * starting * and before each ending *:</p> + * + * <pre><code class="nohighlight"> ******************* + * *<span style="color:red;font-weight:bold;">_</span>This is a first<span style="color:red;font-weight:bold;">_</span>* + * *<span style="color:red;font-weight:bold;">_</span>sample <span style="color:red;font-weight:bold;">_</span>* + * *******************</code></pre> + * + * @param strings A non-empty array possibly containing both strings and <code>null</code> values. + * @return An ASCII frame surrounding lines of text. + * + * <section class="implementationHints"> + * <h4 class="implementationHints">Hints:</h4> + * + * <ul> + * <li>You may use {@link B_StringHelper#getMaxLength(String[])} to get the longest + * string length in the list for sizing your frame.</li> + * + * <li>{@link String#repeat(int)} for repeating both <code>"*"</code> and empty spaces <code>" "</code> + * using e.g. <code>"*".repeat(10)</code>.</li> + * + * <li>Watch out for spaces and invisible newlines at end of your returned string. These are difficult to spot + * and may cause tests to fail.</li> + * + * </ul> + * + * </section> + */ + static public String createTextFrame(final String[] strings) { + + final int maxLength = B_StringHelper.getMaxLength(strings); + + final StringBuffer ret = new StringBuffer("*".repeat(maxLength + 4)).append('\n'); + for (final String s: strings) { + final String insert = null == s ? "" : s; + ret.append("* ").append(insert).append(" ".repeat(maxLength - insert.length())).append(" *\n"); + } + ret.append("*".repeat(maxLength + 4)); + return ret.toString(); + } + + private D_TextFrame(){/* Ignore me: My sole purpose is suppressing default constructor javadoc generation */} +} diff --git a/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/package-info.java b/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..fb7bb58c281c72e0241b31061906c3bf633172d2 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/package-info.java @@ -0,0 +1,17 @@ +/** + * <p>This package mostly (if not completely) contains static methods.</p> + * + * <p>The ordering being implied by class names reflects the author's opinion with respect to ascending implementation + * difficulty. Hints:</p> + * + * <ul> + * <li>Run <code>mvn javadoc:javadoc</code> and open the generated + * <code>/home/.../target/site/apidocs/index.html</code> file in your browser of choice.</li> + * + * <li>Use the corresponding unit tests to check your implementation's consistency and class + * <code>de.hdm_stuttgart.mi.sd1.test.ShowReachedPoints</code> from your project's “unit test†branch.</li> + * + * </ul> + * + */ +package de.hdm_stuttgart.mi.sd1.task1; \ No newline at end of file diff --git a/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task2/QuadratPolynom.java b/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task2/QuadratPolynom.java new file mode 100644 index 0000000000000000000000000000000000000000..954eb15290f909bcde84ee947b36e3adcd493cc4 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task2/QuadratPolynom.java @@ -0,0 +1,241 @@ +package de.hdm_stuttgart.mi.sd1.task2; + +/** + * <p>Providing zeroes (German: "Nullstellen") of quadratic polynomials.</p> + * + * <p>A quadratic polynomial \( p(x) = a x² + b x + c \) is being defined by its three coefficients + * \(a\), \(b\) and \(c\). This class limits coefficients \(a\), \(b\) and \(c\) to type <code>int</code>. A general + * solution is being provided by:</p> + * + * <p>\[ x_{1,2} = {{-b \pm \sqrt{b^2 - 4 ac}} \over {2a}} \]</p> + * + * <p>Depending on \( b^2 - 4 ac \) being positive, zero or negative we have either two, one or no real solutions.</p> + * + * <p>The following sample illustrates zeroes calculation depending on given values of \(a\), \(b\) and \(c\):</p> + * + * <table class="goikTableDefaults"> + * <caption>Sample code illustrating zero values calculation</caption> + * <tbody> + * <tr> + * <th>Code</th> + * <th>Result</th> + * </tr> + * <tr> + * <td> + * <pre><code class="java"> final QuadratPolynom poly = // Representing + * new QuadratPolynom(4, -3, -10); // p(x) = 4x² - 3x - 10 + * + * double[] zeroes = poly.getZeroes(); + * + * System.out.println("Found " + zeroes.length + " zeroes:"); + * + * System.out.println("x_1 = " + zeroes[0]); + * System.out.println("x_2 = " + zeroes[1]);</code></pre> + * </td> + * <td> + * <pre><code class="nohighlight"> Found 2 zeroes: + * x_1 = -1.25 + * x_2 = 2.0</code></pre> + * </td> + * </tr> + * </tbody> + * </table> + * + * <p>We allow for re-setting a polynomial's coefficients. Continuing from the above example we have:</p> + * + * <table class="goikTableDefaults"> + * <caption>Changing coefficients</caption> + * <tbody> + * <tr> + * <th>Code</th> + * <th>Result</th> + * </tr> + * <tr> + * <td> + * <pre><code class="java"> ... + * poly.setA(1); // Representing + * poly.setB(-8); // p(x) = x² -8x + 16 + * poly.setC(16); + * + * zeroes = poly.getZeroes(); + * System.out.println("Found " + zeroes.length + " zero:"); + * + * System.out.println("x_1 = " + zeroes[0]);</code></pre> + * </td> + * <td> + * <pre><code class="nohighlight"> ... + * Found 1 zero: + * x_1 = 4.0</code></pre> + * </td> + * </tr> + * </tbody> + * </table> + * + * <p>Some polynomials do not have any (real valued) solution:</p> + * + * <table class="goikTableDefaults"> + * <caption>Changing coefficients again</caption> + * <tbody> + * <tr> + * <th>Code</th> + * <th>Result</th> + * </tr> + * <tr> + * <td> + * <pre><code class="java"> ... + * poly.setA(1); // Representing + * poly.setB(0); // p(x) = x² + 1 + * poly.setC(1); // (No zero solution) + * + * zeroes = poly.getZeroes(); + * System.out.println("Found " + zeroes.length + " zero");</code></pre> + * </td> + * <td> + * <pre><code class="nohighlight"> ... + * Found 0 zero</code></pre> + * </td> + * </tr> + * </tbody> + * </table> + * + * <p>Finally setting \(a=0\) in \(ax²\) leaves us with just a linear polynomial \(bx + c\). To + * avoid unpredictable results the attempt shall result in throwing an + * <a href="https://freedocs.mi.hdm-stuttgart.de/doc/openjdk-17-doc/api/java.base/java/lang/ArithmeticException.html" + * ><code>ArithmeticException</code></a>:</p> + * + * <table class="goikTableDefaults"> + * <caption>Dealing with 0 value at square coefficient.</caption> + * <tbody> + * <tr> + * <th>Code</th> + * <th>Result</th> + * </tr> + * <tr> + * <td> + * <pre><code class="java"> ... + * poly.setA(0); // Trying to represent p(x) = 1</code></pre> + * </td> + * <td> + * <pre><code class="nohighlight"> ... + * Exception in thread "main" java.lang.ArithmeticException: + * Square coefficient must not be zero</code></pre> + * </td> + * </tr> + * </tbody> + * </table> + * + * <p>Likewise a <code>new QuadratPolynom(0, ..., ...)</code> constructor call setting \(a=0\) shall raise an + * <a href="https://freedocs.mi.hdm-stuttgart.de/doc/openjdk-17-doc/api/java.base/java/lang/ArithmeticException.html"> + * <code>ArithmeticException</code></a> as well.</p> + * + * <section class="implementationHints"> + * <h2 class="implementationHints">Hint:</h2> + * + * <p>This class is yet unimplemented. The above code snippets provide a clue to an implementation + * satisfying the corresponding unit tests.</p> + * + * </section> + */ +public class QuadratPolynom { + + private int a, b, c; + + /** + * <p>Defining a polynomial \( p(x) = a x² + b x + c \).</p> + * + * @param a Square coefficient. + * @param b Linear coefficient. + * @param c Constant coefficient. + * @throws ArithmeticException The square coefficient \( a x² \) must not be zero + */ + public QuadratPolynom(int a, int b, int c) throws ArithmeticException { + setA(a); + setB(b); + setC(c); + } + + /** + * <p>Re- setting the square coefficient in \( a x² \).</p> + * @param a The desired new value. + * @throws ArithmeticException The square coefficient \( a x² \) must not be zero + */ + public void setA(final int a) throws ArithmeticException { + if (0 == a) { + throw new ArithmeticException("Square coefficient must not be zero"); + } + this.a = a; + } + /** + * <p>Re- setting the linear coefficient in \( b x \).</p> + * @param b The desired new value. + */ + public void setB(final int b) { + this.b = b; + } + /** + * <p>Re- setting the constant coefficient \( c \).</p> + * @param c The desired new value. + */ + public void setC(final int c) { + this.c = c; + } + + /** + * <p>Zeroes are all values of \(x\) solving \(a x² + b x + c = 0\).</p> + * + * <p>Zeros are being calculated using:</p> + * + * <p>\[ x = {{ -b \pm \sqrt {b² - 4 a c}} \over {2 a}} \]</p> + * + * <p>Modifying returned array values does not affect the called instance's internal state.</p> + * + * @return <p>Three distinct cases:</p> + * + * <dl> + * + * <dt>\( b² - 4 a c < 0\):</dt> + * <dd><p>An <code>double[0]</code> empty array indicating the non-existence of any real valued solution.</p></dd> + * + * <dt>\( b² - 4 a c = 0\):</dt> + * <dd><p>An <code>double[1]</code> array containing the single zero {\(-b \over {2 a} \)}.</p></dd> + * + * <dt>\( b² - 4 a c > 0\):</dt> + * <dd><p>An <code>double[2]</code> array containing two distinct zeroes + * \( {1\over {2 a}}\left( -b - \sqrt {b² - 4 a c}\right) \) + * and \( {1\over {2 a}}\left( -b + \sqrt {b² - 4 a c}\right) \) ordered by size.</p></dd> + * + * </dl> + * + * <section class = "implementationHints"> + * <h4>Implementation hints:</h4> + * + * <ul> + * <li><a href= + * "https://freedocs.mi.hdm-stuttgart.de/lib/openjdk-17-doc/api/java.base/java/lang/Math.html#sqrt(double)" + * >Math.sqrt(...)</a></li> + * + * </ul> + * + * </section> + */ + public double[] getZeroes() { + final long radicand = ((long) b) * ((long) b) - 4 * ((long) a) * ((long) c) ; +// final int radicand = b * b - 4 * a * c; // failing at higher values due to overflow + + if (0 > radicand) { + return new double[]{}; + } else if (0 == radicand) { + return new double[]{-b / 2. / a}; + } else { + final double radicandRoot = Math.sqrt(radicand); + + if (0 < a) { + return new double[]{(-b - radicandRoot) / 2 / a, (-b + radicandRoot) / 2 / a}; + } else { + return new double[]{(-b + radicandRoot) / 2 / a, (-b - radicandRoot) / 2 / a}; + } + + } + } + private QuadratPolynom(){/* Ignore me: My sole purpose is suppressing default constructor javadoc generation */} +} diff --git a/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task4_no_unit_test/Mathextend.java b/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task4_no_unit_test/Mathextend.java new file mode 100644 index 0000000000000000000000000000000000000000..f254528aa4b685cf7e60b361601ad2c706284ab4 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task4_no_unit_test/Mathextend.java @@ -0,0 +1,31 @@ +package de.hdm_stuttgart.mi.sd1.task4_no_unit_test; + +/** + * <p>This class corresponds to your examination's task 3. Read its description in your web browser.</p> + * + * <p>In particular no unit tests are being associated with this class.</p> + * + * <p>If you correct the implementation of {@link #getAverage(byte, byte, byte)} using your IDEA IDE please + * <em style="color: red;">do not forget</em> to export and upload your project afterwards.</p> + * + */ +public class Mathextend { + + /** + * <p>Compute the average of three values.</p> + * + * @param a First value + * @param b Second value + * @param c Third value + * + * @return Closest <code>byte</code> value to â…“ (a + b + c) + */ + public static byte getAverage(byte a, final byte b, final byte c) { + a += b; + a += c; + a /= 3; + return a; + } + + private Mathextend(){/* Ignore me: My sole purpose is suppressing default constructor javadoc generation */} +} diff --git a/Klausuren/Sd1/2021winter/Solve/src/main/javadoc/resources/fonts/dejavu.css b/Klausuren/Sd1/2021winter/Solve/src/main/javadoc/resources/fonts/dejavu.css new file mode 100644 index 0000000000000000000000000000000000000000..4fec2b593cdcc719fd7edd6744a33a3395ca8401 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/src/main/javadoc/resources/fonts/dejavu.css @@ -0,0 +1,3 @@ +/* shame on you, javadoc! Still providing +@import url('resources/fonts/dejavu.css') line in stylesheet.css +*/ \ No newline at end of file diff --git a/Klausuren/Sd1/2021winter/Solve/src/main/javadoc/resources/jdocSupplement.css b/Klausuren/Sd1/2021winter/Solve/src/main/javadoc/resources/jdocSupplement.css new file mode 100644 index 0000000000000000000000000000000000000000..9f39b10d8588f548a5a009835cff44add2bdb638 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/src/main/javadoc/resources/jdocSupplement.css @@ -0,0 +1,68 @@ +/* Javadoc extensions: */ + +table.goikTableDefaults, +table.goikTableDefaults>caption, +table.goikTableDefaults>tr>th, +table.goikTableDefaults>tr>td, +table.goikTableDefaults>tbody>tr>th, +table.goikTableDefaults>tbody>tr>td { + border: 2px solid black; + border-collapse: collapse; + padding: 1ex; + vertical-align: top; +} + +table.goikTableDefaults>caption { + /* border-top-style: solid; border-left-style: solid; border-right-style: solid' */ + border-bottom-style: none; + font-weight: bold; + background:#dee3e9; + text-align:left; + padding:8px 3px 3px 7px; +} + +table.goikTableDefaults>tbody>tr>td { + vertical-align:top; +} +table.goikTableDefaults { + border-spacing: 0px !important; +} + +table.indexTable { + border-collapse: collapse; + border-style: hidden; +} + +table.indexTable caption { + text-align: left; +} + +table.indexTable td, table.indexTable th { + border: 1px solid black; + padding: 0.5ex; +} + +em { + font-weight: bold; + font-style: normal; +} +section.implementationHints>h3 { + font-weight: bold; + background-color: rgb(222, 227, 233); +} + +code { + white-space: pre; +} + +.implementationHints { + background-color: hsl(120, 100%, 95%) !important; +} + +.myRed { + color: red; +} + +.myGreen { + color: limegreen; +} diff --git a/Klausuren/Sd1/2021winter/Solve/src/main/javadoc/resources/jdocSupplement.js b/Klausuren/Sd1/2021winter/Solve/src/main/javadoc/resources/jdocSupplement.js new file mode 100644 index 0000000000000000000000000000000000000000..97911e5581090aac5e37323427450f8c8c8a3f94 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/src/main/javadoc/resources/jdocSupplement.js @@ -0,0 +1,7 @@ +for(var i in document.links) { + var link = document.links[i]; + if (link.href && link.href.indexOf('http') === 0) { + link.target = '_blank'; + } +} + diff --git a/Klausuren/Sd1/2021winter/Solve/src/main/resources/log4j2.xml b/Klausuren/Sd1/2021winter/Solve/src/main/resources/log4j2.xml new file mode 100644 index 0000000000000000000000000000000000000000..130f87a144c4eb0107a846e580c8fa7f5e819fc1 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/src/main/resources/log4j2.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration> + <Appenders> + <File name="A1" fileName="A1.log" append="false"> + <PatternLayout pattern="%t %-5p %c{2} - %m%n"/> + </File> + <Console name="STDOUT" target="SYSTEM_OUT"> + <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> + </Console> + </Appenders> + <Loggers> + + <!-- You my want to define class or package level per-logger rules --> + <Logger name="de.hdm_stuttgart.mi.sd1.App" level="debug"> + <AppenderRef ref="A1"/> + </Logger> + <Root level="info"> + <AppenderRef ref="STDOUT"/> + </Root> + </Loggers> +</Configuration> \ No newline at end of file diff --git a/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/ShowReachedPoints.java b/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/ShowReachedPoints.java new file mode 100644 index 0000000000000000000000000000000000000000..ae8720eb01d5a8631b073dc214bfd936ef4eb9cb --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/ShowReachedPoints.java @@ -0,0 +1,22 @@ +package de.hdm_stuttgart.mi.sd1; + +import de.hdm_stuttgart.mi.exam.unitmarking.RunTests; + +import de.hdm_stuttgart.mi.sd1.task1.*; +import de.hdm_stuttgart.mi.sd1.task2.Test_QuadratPolynom; + +public class ShowReachedPoints { + + /** + * Revealing total number of reached points fromm all tasks. + * + * @param args Unused + */ + public static void main(String[] args) { + RunTests.exec( + "Task 1" + , A_TrafficLightTest.class, B_StringHelperTest.class, C_ArrayHelperTest.class, D_TextFrameTest.class + ); + RunTests.exec("Task 2", Test_QuadratPolynom.class); + } +} \ No newline at end of file diff --git a/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/ignore_me/ObjectWrapper.java b/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/ignore_me/ObjectWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..85ea78ca4b9c3fd5a617f4074b1d0a4c9b847d54 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/ignore_me/ObjectWrapper.java @@ -0,0 +1,231 @@ +package de.hdm_stuttgart.mi.sd1.ignore_me; + +import org.junit.Assert; + +import java.lang.reflect.*; +import java.util.Arrays; +import java.util.stream.Collectors; + +public class ObjectWrapper<T> { + + private final Class classz; + private final T instance; + + static public void assertFinal(final Class classZ, final String fieldName) { + try { + final int modifier = classZ.getDeclaredField(fieldName).getModifiers(); + Assert.assertTrue("»" + fieldName + "« can be modified, no immutable!", Modifier.isFinal(modifier)); + + } catch (NoSuchFieldException e) { + Assert.fail("No such field »" + fieldName + "«"); + } + } + + public ObjectWrapper(final Class<T> classz, final Object ... parameter) { + this.classz = classz; + T tmpInstance = null; + final Constructor<?>[] candidates = Arrays. + stream(classz.getConstructors()). + filter(c -> matchesArgumentList(c, parameter)). + toArray(Constructor<?>[]::new); + if (0 == candidates.length) { + Assert.fail("No suitable constructor in class »" + classz.getName() + "« matching arguments »(" + + Arrays.stream(parameter).map(Object::toString).collect(Collectors.joining(", ")) + + ")«"); + } else if (1 < candidates.length) { + Assert.fail("Multiple constructor matches due to ambiguous signature"); + } else { + try { + tmpInstance = (T) candidates[0].newInstance( + Arrays.stream(parameter).toArray()); + } catch (Exception e) { + Assert.fail("Unable to instantiate instance of class »" + classz.getName() + "«: "+ e); + } + } + instance = tmpInstance; + } + + public ObjectWrapper(final Class<T> classz, final Class<? extends Throwable> expectedException, final Object ... parameter) { + this.classz = classz; + T tmpInstance = null; + final Constructor<?>[] candidates = Arrays. + stream(classz.getConstructors()). + filter(c -> matchesArgumentList(c, parameter)). + toArray(Constructor<?>[]::new); + if (0 == candidates.length) { + Assert.fail("No suitable constructor in class »" + classz.getName() + "« matching arguments »(" + + Arrays.stream(parameter).map(Object::toString).collect(Collectors.joining(", ")) + + ")«"); + } else if (1 < candidates.length) { + Assert.fail("Multiple constructor matches due to ambiguous signature"); + } else { + try { + tmpInstance = (T) candidates[0].newInstance( + Arrays.stream(parameter).toArray()); + Assert.fail("Expected exception of type »" + expectedException.getName() + "« to be thrown"); + } catch (InstantiationException|IllegalAccessException|IllegalArgumentException|InvocationTargetException e) { + if (e.getCause().getClass() != expectedException) { + Assert.fail("Unable to instantiate: " + e + ", cause:\n Expected exception of type »" + + expectedException.getName() + "« but was »"+ e.getCause().getClass().getName() + "«"); + } + } + } + instance = tmpInstance; + } + + public <R> void assertFieldExists(final Class<R> valueType, final String name) { + try { + final Field field = classz.getField(name); + if (!valueType.equals(field.getType())) { + Assert.fail("Field »" + name + "« in class »" + classz.getName() + "« is not of type »" + + valueType.getName() + "«"); + } + } catch (final NoSuchFieldException e) { + Assert.fail("No such field »" + name + "« in class »" + classz.getName() + "«"); + } + } + + public <R> R get(final Class<R> valueType, final String name) { + + try { + final Field field = classz.getField(name); + if (valueType.equals(field.getType())) { + return (R) field.get(instance); + } else { + Assert.fail("Field »" + name + "« in class »" + classz.getName() + "« is not of type »" + + valueType.getName() + "«"); + } + } catch (final NoSuchFieldException e) { + Assert.fail("No such field »" + name + "« in class »" + classz.getName() + "«"); + } catch (final IllegalAccessException e) { + Assert.fail("Unable to access field »" + name + "« in class »" + classz.getName() + "«: " + e.getMessage()); + } + return null; + } + public void set(final String name, final Object value) { + + try { + final Field field = classz.getField(name); + final Class argumentType = value.getClass(); + if (field.getType().equals(argumentType) || + field.getType().equals(getPrimitiveType(argumentType))){ + field.set(instance, value); + } else { + Assert.fail("Field »" + name + "« in class »" + classz.getName() + "« is not of type »" + + argumentType.getName() + "«"); + } + } catch (final NoSuchFieldException e) { + Assert.fail("No such field »" + name + "« in class »" + classz.getName() + "«"); + } catch (final IllegalAccessException e) { + Assert.fail("Unable to access field »" + name + "« in class »" + classz.getName() + "«: " + e.getMessage()); + } + } + + public <R> R invoke(final Class<R> returnType, final String name, final Object ... parameter) { + + final Method[] candidates = Arrays. + stream(classz.getMethods()). + filter(m-> m.getName().equals(name) && matchesArgumentList(m, parameter)). + toArray(Method[]::new); + + if (0 == candidates.length) { + Assert.fail("No suitable method found"); + } else if (1 < candidates.length) { + Assert.fail("Multiple method matches due to ambiguous signature"); + } else { + final Method method = candidates[0]; + if (method.getReturnType().equals(returnType)) { + try { + return (R) method.invoke(instance, parameter); + } catch (final IllegalAccessException| IllegalArgumentException|InvocationTargetException e) { + Assert.fail("Unable to execute method: " + e + ", cause:" + e.getCause()); + } + } else { + Assert.fail("Method »" + method.getName() + "« does have return type »" + method.getReturnType() + "«" + + "rather then »" + returnType.getName() + "«"); + } + } + return null; + } + public <R> R invoke(final Class<R> returnType, final String name, + final Class<? extends Throwable> expectedException, final Object ... parameter) { + + final Method[] candidates = Arrays. + stream(classz.getMethods()). + filter(m-> m.getName().equals(name) && matchesArgumentList(m, parameter)). + toArray(Method[]::new); + + if (0 == candidates.length) { + Assert.fail("No suitable method found"); + } else if (1 < candidates.length) { + Assert.fail("Multiple method matches due to ambiguous signature"); + } else { + final Method method = candidates[0]; + if (method.getReturnType().equals(returnType)) { + try { + R ret = (R) method.invoke(instance, parameter); + Assert.fail("Expected exception of type »" + expectedException.getName() + "«"); + return ret; + } catch (final IllegalAccessException| IllegalArgumentException|InvocationTargetException e) { + if (e.getCause().getClass() != expectedException) { + Assert.fail("Unable to execute method: " + e + ", cause:\n Expected exception of type »" + + expectedException.getName() + "« but was »"+ e.getCause().getClass().getName() + "«"); + } + } + } else { + Assert.fail("Method »" + method.getName() + "« does have return type »" + method.getReturnType() + "«" + + "rather then »" + returnType.getName() + "«"); + } + } + return null; + } + + /** + * Check for a given array of objects matching an {@link Executable}'s argument list. + * + * @param executable + * @param parameter + * @return <code>true</code> if parameters match the {@link Executable}'s argument list, <code>false</code> + * otherwise. + */ + private boolean matchesArgumentList(final Executable executable, final Object ... parameter) { + + if (executable.getParameterCount() != parameter.length) { + return false; + } else { + final Class<?>[] formalArgumentTypes = executable.getParameterTypes(); + for (int i = 0; i < formalArgumentTypes.length; i++) { + final Class parametersClass = parameter[i].getClass(); + + if (!formalArgumentTypes[i].equals(parametersClass) && + !formalArgumentTypes[i].equals(getPrimitiveType(parametersClass))) { + return false; + } + } + } + return true; + } + + static private Class<?> getPrimitiveType (final Class<?> in) { + if (in.equals(Byte.class)) { + return byte.class; + } else if (in.equals(Short.class)) { + return short.class; + } else if (in.equals(Integer.class)) { + return int.class; + } else if (in.equals(Long.class)) { + return long.class; + } else if (in.equals(Float.class)) { + return float.class; + } else if (in.equals(Double.class)) { + return double.class; + } else if (in.equals(Boolean.class)) { + return boolean.class; + } else if (in.equals(Character.class)) { + return char.class; + } else { + return in; // Type is no primitive + } + } + +} diff --git a/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task1/A_TrafficLightTest.java b/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task1/A_TrafficLightTest.java new file mode 100644 index 0000000000000000000000000000000000000000..fae220dd2d62ef8ccffc094d3863399d47390bf7 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task1/A_TrafficLightTest.java @@ -0,0 +1,25 @@ +package de.hdm_stuttgart.mi.sd1.task1; + +import de.hdm_stuttgart.mi.exam.unitmarking.ExaminationTestDefaults; +import de.hdm_stuttgart.mi.exam.unitmarking.Marking; +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import static de.hdm_stuttgart.mi.sd1.task1.A_TrafficLight.mustStop; + + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class A_TrafficLightTest extends ExaminationTestDefaults { + + @Test + @Marking(points = 16) + public void test_100() { + Assert.assertTrue( mustStop(true, false, false)); // Red :Stop + Assert.assertFalse(mustStop(true, true, false)); // Red + yellow :Go + + Assert.assertFalse(mustStop(false, false, true)); // Green :Go + Assert.assertTrue( mustStop(false, true, false)); // Yellow :Stop + } +} diff --git a/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task1/B_StringHelperTest.java b/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task1/B_StringHelperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..176ccc7edd646b1dfcf790344f63bda7af9fa981 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task1/B_StringHelperTest.java @@ -0,0 +1,37 @@ +package de.hdm_stuttgart.mi.sd1.task1; + +import de.hdm_stuttgart.mi.exam.unitmarking.ExaminationTestDefaults; +import de.hdm_stuttgart.mi.exam.unitmarking.Marking; +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import static de.hdm_stuttgart.mi.sd1.task1.B_StringHelper.getMaxLength; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class B_StringHelperTest extends ExaminationTestDefaults { + + @Test + @Marking(points = 2) + public void test_100_minimum() { + Assert.assertEquals(0, getMaxLength(new String[]{null})); + Assert.assertEquals(0, getMaxLength(new String[]{""})); + } + + @Test + @Marking(points = 6) + public void test_200_single() { + Assert.assertEquals(1, getMaxLength(new String[]{"a"})); + Assert.assertEquals(11, getMaxLength(new String[]{"csd wde dwe"})); + } + + @Test + @Marking(points = 6) + public void test_300_multi() { + Assert.assertEquals(1, getMaxLength(new String[]{"a", "b", "c"})); + Assert.assertEquals(5, getMaxLength(new String[]{"Eve", "Peter", "Jill", "Tom"})); + Assert.assertEquals(12, getMaxLength(new String[]{"Looooooooong", "Loooooong", null, "Looong", null})); + Assert.assertEquals(12, getMaxLength(new String[]{null, "Loooooong", "Looooooooong", "Looong", null})); + } +} diff --git a/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task1/C_ArrayHelperTest.java b/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task1/C_ArrayHelperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..bb48553fe9ee6b9b886ea513643a3dfad017603a --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task1/C_ArrayHelperTest.java @@ -0,0 +1,42 @@ +package de.hdm_stuttgart.mi.sd1.task1; + +import de.hdm_stuttgart.mi.exam.unitmarking.ExaminationTestDefaults; +import de.hdm_stuttgart.mi.exam.unitmarking.Marking; +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import static de.hdm_stuttgart.mi.sd1.task1.C_ArrayHelper.getAboveAverage; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class C_ArrayHelperTest extends ExaminationTestDefaults { + + @Test + @Marking(points = 2) + public void test_100_minimum() { + Assert.assertArrayEquals(new int[]{}, getAboveAverage(new int[]{1})); + } + + @Test + @Marking(points = 4) + public void test_200_equal() { + Assert.assertArrayEquals(new int[]{}, getAboveAverage(new int[]{20, 20})); + Assert.assertArrayEquals(new int[]{}, getAboveAverage(new int[]{7, 7, 7, 7})); + } + + @Test + @Marking(points = 4) + public void test_200_regular() { + Assert.assertArrayEquals(new int[]{1}, getAboveAverage(new int[]{1, 0})); + Assert.assertArrayEquals(new int[]{1}, getAboveAverage(new int[]{0, 1})); + Assert.assertArrayEquals(new int[]{5, 4}, getAboveAverage(new int[]{1, 2, 3, 5, 4})); + Assert.assertArrayEquals(new int[]{55, 100}, getAboveAverage(new int[]{-30, 2, 4, 55, 100, 9})); + } + + @Test + @Marking(points = 2) + public void test_200_big() { + Assert.assertArrayEquals(new int[]{Integer.MAX_VALUE, Integer.MAX_VALUE}, getAboveAverage(new int[]{Integer.MAX_VALUE, Integer.MAX_VALUE, 0})); + } +} diff --git a/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task1/D_TextFrameTest.java b/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task1/D_TextFrameTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c003f80e721e6719eb7e378e8fff83291909dcf6 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task1/D_TextFrameTest.java @@ -0,0 +1,89 @@ +package de.hdm_stuttgart.mi.sd1.task1; + +import de.hdm_stuttgart.mi.exam.unitmarking.ExaminationTestDefaults; +import de.hdm_stuttgart.mi.exam.unitmarking.Marking; +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import static de.hdm_stuttgart.mi.sd1.task1.D_TextFrame.createTextFrame; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class D_TextFrameTest extends ExaminationTestDefaults { + + @Test + @Marking(points = 2) + public void test_100_minimum() { + + final String expected = """ + **** + * * + ****"""; + + Assert.assertEquals(expected, createTextFrame(new String[]{null})); + Assert.assertEquals(expected, createTextFrame(new String[]{""})); + } + + @Test + @Marking(points = 2) + public void test_200_one() { + + { + final String expected = """ + ***** + * * + *****"""; + + Assert.assertEquals(expected, createTextFrame(new String[]{" "})); + } + { + final String expected = """ + ***** + * j * + *****"""; + + Assert.assertEquals(expected, createTextFrame(new String[]{"j"})); + } + } + + @Test + @Marking(points = 2) + public void test_300_multi() { + + { + final String expected = """ + ****************** + * This is a very * + * simple test. * + ******************"""; + + Assert.assertEquals(expected, createTextFrame(new String[]{"This is a very", "simple test."})); + } + { + final String expected = """ + ******************* + * An example * + * featuring three * + * lines * + *******************"""; + + Assert.assertEquals(expected, createTextFrame(new String[]{"An example", "featuring three", "lines"})); + } + } + + @Test + @Marking(points = 2) + public void test_400_null() { + + final String expected = """ + ********************** + * Sometimes there is * + * * + * a hole. * + * * + **********************"""; + + Assert.assertEquals(expected, createTextFrame(new String[]{"Sometimes there is", null, "a hole.", null})); + } +} diff --git a/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task2/Test_QuadratPolynom.java b/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task2/Test_QuadratPolynom.java new file mode 100644 index 0000000000000000000000000000000000000000..055651ad7c3b63499d3c38874807b674c43985a0 --- /dev/null +++ b/Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task2/Test_QuadratPolynom.java @@ -0,0 +1,226 @@ +package de.hdm_stuttgart.mi.sd1.task2; + +import de.hdm_stuttgart.mi.exam.unitmarking.ExaminationTestDefaults; +import de.hdm_stuttgart.mi.exam.unitmarking.Marking; +import de.hdm_stuttgart.mi.sd1.ignore_me.ObjectWrapper; +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) + +public class Test_QuadratPolynom extends ExaminationTestDefaults { + + @Test + @Marking(points = 5) + public void test_100_NoZero() { + final ObjectWrapper<QuadratPolynom> poly = new ObjectWrapper<>(QuadratPolynom.class,1, 1, 1); + assertNoZero(poly, composeDescription(1,2,1).toString()); + + final ObjectWrapper<QuadratPolynom> poly2 = new ObjectWrapper<>(QuadratPolynom.class,1, 2, 3); + assertNoZero(1, 6, 20, poly2); + assertNoZero(2, 13, 41, poly2); + } + + @Test + @Marking(points = 5) + public void test_200_OneZero() { + final ObjectWrapper<QuadratPolynom> poly = new ObjectWrapper<>(QuadratPolynom.class,1, 2, 1); + assertOneZero(poly, -1, composeDescription(1,2,1).toString()); + + final ObjectWrapper<QuadratPolynom> poly2 = new ObjectWrapper<>(QuadratPolynom.class,1, 2, 3); + assertOneZero(6, -84, 294, poly2, 7); + assertOneZero(21, 126, 189, poly2, -3); + } + + @Test + @Marking(points = 5) + public void test_300_twoZeroes() { + + final ObjectWrapper<QuadratPolynom> poly = new ObjectWrapper<>(QuadratPolynom.class,1, 3, 2); + assertTwoZeroes(poly, -2, -1, "x² + 3x + 2"); + + assertTwoZeroes(3, 7, 4, poly, -4./3, -1); + + assertTwoZeroes(-2, 1, 3, poly, -1, 1.5); + + assertTwoZeroes(-1, 5, 6, poly, -1, 6); + + assertTwoZeroes(7, 11, 4, poly, -1, -4./7); + + assertTwoZeroes(4, -3, -10, poly, -1.25, 2); + + assertTwoZeroes(5, 6, 1, poly, -1, -0.2); + + } + + @Test + @Marking(points = 2) + public void test_400_Exception() { + final ObjectWrapper<QuadratPolynom> poly = new ObjectWrapper<>(QuadratPolynom.class,1, -200, 2); + + final Class<ArithmeticException> expectedArithmeticException = ArithmeticException.class; + + // Coefficient ax² must not be 0 + poly.invoke(void.class, "setA", expectedArithmeticException, 0); + new ObjectWrapper<>(QuadratPolynom.class, expectedArithmeticException, 0, 88, 99); + } + + @Test + @Marking(points = 3) + public void test_500_TwoZeroExzess() { + final ObjectWrapper<QuadratPolynom> poly = new ObjectWrapper<>(QuadratPolynom.class, + 46010, 598130,-1960026000); + assertTwoZeroes(poly,-213,200, + composeDescription(46010, 598130,-1960026000).toString()); + } + + // End of tests ------------------------------------------------------------------------------------------------- + // Test helper methods + // + static private final double delta = 1.E-12; + + static private StringBuffer composeDescription(final int a, final int b, final int c) { + final StringBuffer ret = new StringBuffer(); + ret.append(a).append("x²"); + if (0 < b) { + ret.append(" + ").append(b).append("x"); + } else if (b < 0) { + ret.append(" ").append(b).append("x"); + } + // Slight code duplication avoiding a method definition. Yepp: I'm lazy sometimes! + if (0 < c) { + ret.append(" + ").append(c); + } else if (c < 0) { + ret.append(" ").append(c); + } + return ret; + } + + /** + * Testing given polynomial for no real zero value. + * + * @param poly Polynomial to be tested + * @param description E.g. "-2x² + 4x -3" + */ + static private void assertNoZero(final ObjectWrapper<QuadratPolynom> poly, final String description) { + + Assert.assertEquals("No zero expected for polynom »" + description + "«", + 0, poly.invoke(double[].class, "getZeroes").length); + } + + /** + * Testing for no real valued zero solution. + * + * @param a Square coefficient + * @param b Linear coefficient + * @param c Constant coefficient + * @param poly Square polynomial + */ + static private void assertNoZero(final int a, + final int b, + final int c, + final ObjectWrapper<QuadratPolynom> poly) { + poly.invoke(void.class, "setA", a); + poly.invoke(void.class, "setB", b); + poly.invoke(void.class, "setC", c); + Assert.assertEquals("One zero expected for polynom »" + composeDescription(a, b, c) + "«", + 0, poly.invoke(double[].class, "getZeroes").length); + + + } + + /** + * Testing given polynomial for one zeroes to be returned + * + * @param poly Polynomial to be tested + * @param expected zero value + * @param description E.g. "-2x² + 4x -3" + */ + static private void assertOneZero(final ObjectWrapper<QuadratPolynom> poly, + double expected, + final String description) { + final double[] result = poly.invoke(double[].class, "getZeroes"); + + Assert.assertEquals("One zero expected for polynom »" + description + "«", + 1, result.length); + Assert.assertEquals("Expected zero of »" + description +"« to be " + expected, expected, result[0], delta); + } + + /** + * Like {@link #assertOneZero(ObjectWrapper, double, String)} but re-setting coefficients beforehand, + * @param a Square coefficient + * @param b Linear coefficient + * @param c Constant coefficient + * @param poly Square polynomial + */ + static private void assertOneZero(final int a, + final int b, + final int c, + final ObjectWrapper<QuadratPolynom> poly, + double expected) { + poly.invoke(void.class, "setA", a); + poly.invoke(void.class, "setB", b); + poly.invoke(void.class, "setC", c); + final double[] result = poly.invoke(double[].class, "getZeroes"); + + final StringBuffer polynomDescription = composeDescription(a, b, c); + + Assert.assertEquals(2 + " zeroes expected for polynom »" + polynomDescription + "«", + 1, result.length); + Assert.assertEquals("Expected zero of »" + polynomDescription +"« to be " + expected, + expected, result[0], delta); + } + + /** + * Testing given polynomial for two zeroes to be returned + * + * @param poly Polynomial to be tested + * @param expectedLower Lower zero value + * @param expectedUpper Upper zero value + * @param description E.g. "-2x² + 4x -3" + */ + static private void assertTwoZeroes(final ObjectWrapper<QuadratPolynom> poly, + double expectedLower, + double expectedUpper, + final String description) { + final double[] result = poly.invoke(double[].class, "getZeroes"); + + Assert.assertEquals(2 + " zeroes expected for polynom »" + description + "«", + 2, result.length); + Assert.assertEquals("Expected lower zero of »" + description +"« to be " + expectedLower, + expectedLower, result[0], delta); + Assert.assertEquals("Expected upper zero of »" + description +"« to be " + expectedUpper, + expectedUpper, result[1], delta); + } + + /** + * Like {@link #assertTwoZeroes(ObjectWrapper, double, double, String)} but re-setting coeficients beforehand, + * @param a Square coefficient + * @param b Linear coefficient + * @param c Constant coefficient + * @param poly Square polynomial + * @param expectedLower Expected lower zero value + * @param expectedUpper Expected upper zero value + */ + static private void assertTwoZeroes(final int a, + final int b, + final int c, + final ObjectWrapper<QuadratPolynom> poly, + double expectedLower, + double expectedUpper) { + poly.invoke(void.class, "setA", a); + poly.invoke(void.class, "setB", b); + poly.invoke(void.class, "setC", c); + final double[] result = poly.invoke(double[].class, "getZeroes"); + + final StringBuffer polynomDescription = composeDescription(a, b, c); + + Assert.assertEquals(2 + " zeroes expected for polynom »" + polynomDescription + "«", + 2, result.length); + Assert.assertEquals("Expected lower zero of »" + polynomDescription +"« to be " + expectedLower, + expectedLower, result[0], delta); + Assert.assertEquals("Expected upper zero of »" + polynomDescription +"« to be " + expectedUpper, + expectedUpper, result[1], delta); + } +}