From 94cffe139a6c0fb837eb4483f626e30a089c4828 Mon Sep 17 00:00:00 2001 From: Martin Goik <goik@hdm-stuttgart.de> Date: Mon, 31 Jan 2022 16:41:30 +0100 Subject: [PATCH] Exam winter 2021/22 --- Doc/Sd1/Exam/2021/Winter/exam.xml | 481 ++++++++++++++++++ Doc/Sd1/appendix.xml | 4 + Klausuren/Sd1/2021winter/Exam/pom.xml | 130 +++++ .../Exam/src/main/assembly/assembly.xml | 36 ++ .../mi/sd1/task1/A_TrafficLight.java | 66 +++ .../mi/sd1/task1/B_StringHelper.java | 44 ++ .../mi/sd1/task1/C_ArrayHelper.java | 42 ++ .../mi/sd1/task1/D_TextFrame.java | 69 +++ .../mi/sd1/task1/package-info.java | 17 + .../mi/sd1/task2/QuadratPolynom.java | 142 ++++++ .../mi/sd1/task4_no_unit_test/Mathextend.java | 31 ++ .../main/javadoc/resources/fonts/dejavu.css | 3 + .../main/javadoc/resources/jdocSupplement.css | 68 +++ .../main/javadoc/resources/jdocSupplement.js | 7 + .../Exam/src/main/resources/log4j2.xml | 21 + .../mi/sd1/ShowReachedPoints.java | 22 + .../mi/sd1/ignore_me/ObjectWrapper.java | 231 +++++++++ .../mi/sd1/task1/A_TrafficLightTest.java | 25 + .../mi/sd1/task1/B_StringHelperTest.java | 37 ++ .../mi/sd1/task1/C_ArrayHelperTest.java | 42 ++ .../mi/sd1/task1/D_TextFrameTest.java | 89 ++++ .../mi/sd1/task2/Test_QuadratPolynom.java | 226 ++++++++ Klausuren/Sd1/2021winter/Solve/Doc/wurzel.ods | Bin 0 -> 16802 bytes Klausuren/Sd1/2021winter/Solve/pom.xml | 130 +++++ .../Solve/src/main/assembly/assembly.xml | 36 ++ .../mi/sd1/task1/A_TrafficLight.java | 66 +++ .../mi/sd1/task1/B_StringHelper.java | 49 ++ .../mi/sd1/task1/C_ArrayHelper.java | 61 +++ .../mi/sd1/task1/D_TextFrame.java | 77 +++ .../mi/sd1/task1/package-info.java | 17 + .../mi/sd1/task2/QuadratPolynom.java | 241 +++++++++ .../mi/sd1/task4_no_unit_test/Mathextend.java | 31 ++ .../main/javadoc/resources/fonts/dejavu.css | 3 + .../main/javadoc/resources/jdocSupplement.css | 68 +++ .../main/javadoc/resources/jdocSupplement.js | 7 + .../Solve/src/main/resources/log4j2.xml | 21 + .../mi/sd1/ShowReachedPoints.java | 22 + .../mi/sd1/ignore_me/ObjectWrapper.java | 231 +++++++++ .../mi/sd1/task1/A_TrafficLightTest.java | 25 + .../mi/sd1/task1/B_StringHelperTest.java | 37 ++ .../mi/sd1/task1/C_ArrayHelperTest.java | 42 ++ .../mi/sd1/task1/D_TextFrameTest.java | 89 ++++ .../mi/sd1/task2/Test_QuadratPolynom.java | 226 ++++++++ 43 files changed, 3312 insertions(+) create mode 100644 Doc/Sd1/Exam/2021/Winter/exam.xml create mode 100644 Klausuren/Sd1/2021winter/Exam/pom.xml create mode 100644 Klausuren/Sd1/2021winter/Exam/src/main/assembly/assembly.xml create mode 100644 Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/A_TrafficLight.java create mode 100644 Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/B_StringHelper.java create mode 100644 Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/C_ArrayHelper.java create mode 100644 Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/D_TextFrame.java create mode 100644 Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task1/package-info.java create mode 100644 Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task2/QuadratPolynom.java create mode 100644 Klausuren/Sd1/2021winter/Exam/src/main/java/de/hdm_stuttgart/mi/sd1/task4_no_unit_test/Mathextend.java create mode 100644 Klausuren/Sd1/2021winter/Exam/src/main/javadoc/resources/fonts/dejavu.css create mode 100644 Klausuren/Sd1/2021winter/Exam/src/main/javadoc/resources/jdocSupplement.css create mode 100644 Klausuren/Sd1/2021winter/Exam/src/main/javadoc/resources/jdocSupplement.js create mode 100644 Klausuren/Sd1/2021winter/Exam/src/main/resources/log4j2.xml create mode 100644 Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/ShowReachedPoints.java create mode 100644 Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/ignore_me/ObjectWrapper.java create mode 100644 Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task1/A_TrafficLightTest.java create mode 100644 Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task1/B_StringHelperTest.java create mode 100644 Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task1/C_ArrayHelperTest.java create mode 100644 Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task1/D_TextFrameTest.java create mode 100644 Klausuren/Sd1/2021winter/Exam/src/test/java/de/hdm_stuttgart/mi/sd1/task2/Test_QuadratPolynom.java create mode 100644 Klausuren/Sd1/2021winter/Solve/Doc/wurzel.ods create mode 100644 Klausuren/Sd1/2021winter/Solve/pom.xml create mode 100644 Klausuren/Sd1/2021winter/Solve/src/main/assembly/assembly.xml create mode 100644 Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/A_TrafficLight.java create mode 100644 Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/B_StringHelper.java create mode 100644 Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/C_ArrayHelper.java create mode 100644 Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/D_TextFrame.java create mode 100644 Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task1/package-info.java create mode 100644 Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task2/QuadratPolynom.java create mode 100644 Klausuren/Sd1/2021winter/Solve/src/main/java/de/hdm_stuttgart/mi/sd1/task4_no_unit_test/Mathextend.java create mode 100644 Klausuren/Sd1/2021winter/Solve/src/main/javadoc/resources/fonts/dejavu.css create mode 100644 Klausuren/Sd1/2021winter/Solve/src/main/javadoc/resources/jdocSupplement.css create mode 100644 Klausuren/Sd1/2021winter/Solve/src/main/javadoc/resources/jdocSupplement.js create mode 100644 Klausuren/Sd1/2021winter/Solve/src/main/resources/log4j2.xml create mode 100644 Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/ShowReachedPoints.java create mode 100644 Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/ignore_me/ObjectWrapper.java create mode 100644 Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task1/A_TrafficLightTest.java create mode 100644 Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task1/B_StringHelperTest.java create mode 100644 Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task1/C_ArrayHelperTest.java create mode 100644 Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task1/D_TextFrameTest.java create mode 100644 Klausuren/Sd1/2021winter/Solve/src/test/java/de/hdm_stuttgart/mi/sd1/task2/Test_QuadratPolynom.java diff --git a/Doc/Sd1/Exam/2021/Winter/exam.xml b/Doc/Sd1/Exam/2021/Winter/exam.xml new file mode 100644 index 000000000..fa895dcca --- /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 1d59125f4..164b17ff4 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 000000000..0c0738ff7 --- /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 000000000..85268e296 --- /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 000000000..c94ac78bd --- /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 000000000..642a280e8 --- /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 000000000..dc6226838 --- /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 000000000..7441a36e7 --- /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 000000000..fb7bb58c2 --- /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 000000000..6d7026006 --- /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 000000000..f254528aa --- /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 000000000..4fec2b593 --- /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 000000000..9f39b10d8 --- /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 000000000..97911e558 --- /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 000000000..130f87a14 --- /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 000000000..ae8720eb0 --- /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 000000000..85ea78ca4 --- /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 000000000..fae220dd2 --- /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 000000000..176ccc7ed --- /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 000000000..bb48553fe --- /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 000000000..c003f80e7 --- /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 000000000..055651ad7 --- /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 GIT binary patch literal 16802 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 V3>@P3V@SU~fM1IaDaY^J{{dpJjp+aY literal 0 HcmV?d00001 diff --git a/Klausuren/Sd1/2021winter/Solve/pom.xml b/Klausuren/Sd1/2021winter/Solve/pom.xml new file mode 100644 index 000000000..d447ccb00 --- /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 000000000..85268e296 --- /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 000000000..fff60a3b2 --- /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 000000000..7b3910a4d --- /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 000000000..5997a5dc4 --- /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 000000000..d6cb4dd86 --- /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 000000000..fb7bb58c2 --- /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 000000000..954eb1529 --- /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 000000000..f254528aa --- /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 000000000..4fec2b593 --- /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 000000000..9f39b10d8 --- /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 000000000..97911e558 --- /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 000000000..130f87a14 --- /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 000000000..ae8720eb0 --- /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 000000000..85ea78ca4 --- /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 000000000..fae220dd2 --- /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 000000000..176ccc7ed --- /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 000000000..bb48553fe --- /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 000000000..c003f80e7 --- /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 000000000..055651ad7 --- /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); + } +} -- GitLab