diff --git a/Doc/Sd1/Ref/Projects/WeatherSkeleton/.gitignore b/Doc/Sd1/Ref/Projects/WeatherSkeleton/.gitignore index a4ae8fc231be86fbcf2081f6b5957d129334fa9c..7447d278a416709be02d67a386cd6ea75a10be47 100644 --- a/Doc/Sd1/Ref/Projects/WeatherSkeleton/.gitignore +++ b/Doc/Sd1/Ref/Projects/WeatherSkeleton/.gitignore @@ -1,56 +1,5 @@ /target/ -/.settings/ -.classpath -.project A1.log src/main/resources/weather.properties - -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff: -.idea/**/workspace.xml -.idea/**/tasks.xml -.idea/dictionaries - -# Sensitive or high-churn files: -.idea/**/dataSources/ -.idea/**/dataSources.ids -.idea/**/dataSources.xml -.idea/**/dataSources.local.xml -.idea/**/sqlDataSources.xml -.idea/**/dynamic.xml -.idea/**/uiDesigner.xml - -# Gradle: -.idea/**/gradle.xml -.idea/**/libraries - -# CMake -cmake-build-debug/ - -# Mongo Explorer plugin: -.idea/**/mongoSettings.xml - -## File-based project format: -*.iws - -## Plugin-specific files: - -# IntelliJ -out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Cursive Clojure plugin -.idea/replstate.xml - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties \ No newline at end of file +.idea +*.iml diff --git a/Doc/Sd1/Ref/Projects/weather.webm b/Doc/Sd1/Ref/Projects/weather.webm new file mode 100644 index 0000000000000000000000000000000000000000..d951f1188b0b6d9abeff5f86e1a532ace5aae40a Binary files /dev/null and b/Doc/Sd1/Ref/Projects/weather.webm differ diff --git a/Doc/Sd1/appendix.xml b/Doc/Sd1/appendix.xml index 323252cd60c85680a7a6feaed5c612d8880637b4..57b533713cf076d342273fbe28100ddbd0ed3de0 100644 --- a/Doc/Sd1/appendix.xml +++ b/Doc/Sd1/appendix.xml @@ -384,6 +384,16 @@ public void test_400() { <para>In this project you'll implement a terminal based weather forecast application. Consider the following invocation:</para> + <figure xml:id="sd1_weather_fig_invocationVideo"> + <title>Sample forecast session</title> + + <mediaobject> + <videoobject> + <videodata fileref="Ref/Projects/weather.webm"/> + </videoobject> + </mediaobject> + </figure> + <figure xml:id="sd1_weather_fig_invocationExample"> <title>Sample forecast invocation</title> @@ -439,6 +449,8 @@ Mittwoch, 16.05 </callout> </calloutlist> + <para>The actual weather data is being provided by a web service:</para> + <figure xml:id="sd1_weather_fig_underlyingData"> <title>Underlying data provider</title> @@ -464,7 +476,59 @@ APPID=7cufdhdcgdhsgdhgfcgsdss67b3&units=metric&<emphasis role="red">id=3 <callout arearefs="sd1_weather_fig_underlyingData-1-co" xml:id="sd1_weather_fig_underlyingData-1"> <para>An <xref linkend="glo_URL"/> containing an id value - corresponding to a uniquely defined town or region.</para> + corresponding to a uniquely defined town or region. We identify + the following components:</para> + + <glosslist> + <glossentry> + <glossterm><code>lang=de</code></glossterm> + + <glossdef> + <para>Provide German localization e.g. »<foreignphrase + xml:lang="de">Leichter Regen</foreignphrase>« in favour of + »light rain«.</para> + </glossdef> + </glossentry> + + <glossentry> + <glossterm><abbrev>APPID</abbrev>=7cufdhdcgdhsgdhgfcgsdss67b3</glossterm> + + <glossdef> + <para>This parameter allows for accessing the service: + »7cufdhdcgdhsgdhgfcgsdss67b3« is actually a fake value. Your + project requires <link + xlink:href="https://openweathermap.org/appid">obtaining an + APPID token</link>.</para> + </glossdef> + </glossentry> + + <glossentry> + <glossterm>units=metric</glossterm> + + <glossdef> + <para>Favour metric over imperial units.</para> + </glossdef> + </glossentry> + + <glossentry> + <glossterm>id=3214105</glossterm> + + <glossdef> + <para>»3214105« identifies »<foreignphrase + xml:lang="de">Regierungsbezirk Stuttgart</foreignphrase>«, + see line 262703 in <filename + xlink:href="https://gitlab.mi.hdm-stuttgart.de/goik/GoikLectures/blob/master/Doc/Sd1/Ref/Projects/WeatherSkeleton/src/main/resources/cities.list.json">cities.list.json</filename>:</para> + + <programlisting language="json">"id": 3214105, +"name": "Regierungsbezirk Stuttgart", +"country": "DE", +"coord": { + "lon": 9.66667, + "lat": 49.083328 +}</programlisting> + </glossdef> + </glossentry> + </glosslist> </callout> <callout arearefs="sd1_weather_fig_underlyingData-2-co" @@ -475,6 +539,134 @@ APPID=7cufdhdcgdhsgdhgfcgsdss67b3&units=metric&<emphasis role="red">id=3 </callout> </calloutlist> </figure> + + <figure xml:id="sd1_weather_fig_citiesFile"> + <title><filename + xlink:href="http://bulk.openweathermap.org/sample">cities.list.json.gz</filename> + providing cities</title> + + <programlisting language="json">[ + { + "id": 2886241, + "name": "Regierungsbezirk Köln", + "country": "DE", + "coord": { + "lon": 7.16667, + "lat": 50.833328 + } + }, + { + "id": 3247452, + "name": "Kreis Euskirchen", +... +]</programlisting> + </figure> + + <figure xml:id="sd1_weather_fig_urlToFileHelper"> + <title>ma/Copy URL result to file</title> + + <programlisting language="java">FileUtils.<link + xlink:href="https://commons.apache.org/proper/commons-io/javadocs/api-2.6/org/apache/commons/io/FileUtils.html#copyURLToFile-java.net.URL-java.io.File-">copyURLToFile</link>( + "https://api.openweathermap.org/data/2.5/forecast...", + new File("weatherData.json"));</programlisting> + + <programlisting language="xml"><dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>2.6</version> +</dependency></programlisting> + </figure> + + <figure xml:id="sd1_weather_fig_parseCityData"> + <title>Parse city data</title> + + <programlisting language="java"><link + xlink:href="https://gitlab.mi.hdm-stuttgart.de/goik/GoikLectures/blob/master/Doc/Sd1/Ref/Projects/WeatherSkeleton/src/main/java/de/hdm_stuttgart/mi/sd1/weather/cities/Cities.java">public class Cities</link> { + static public final City[] cities; + ... +}</programlisting> + + <programlisting language="java">@Test <link + xlink:href="https://gitlab.mi.hdm-stuttgart.de/goik/GoikLectures/blob/master/Doc/Sd1/Ref/Projects/WeatherSkeleton/src/test/java/de/hdm_stuttgart/mi/sd1/weather/CityParserTest.java">public void testParsedCityCount()</link> { + Assert.assertEquals(209579, Cities.cities.length); +}</programlisting> + </figure> + + <figure xml:id="sd1_weather_fig_parseWeatherData"> + <title>Parse weather data</title> + + <programlisting language="java"><link + xlink:href="https://gitlab.mi.hdm-stuttgart.de/goik/GoikLectures/blob/master/Doc/Sd1/Ref/Projects/WeatherSkeleton/src/main/java/de/hdm_stuttgart/mi/sd1/weather/WeatherDataParser.java">public class WeatherDataParser</link> { + + static public final <link + xlink:href="https://gitlab.mi.hdm-stuttgart.de/goik/GoikLectures/blob/master/Doc/Sd1/Ref/Projects/WeatherSkeleton/src/main/java/de/hdm_stuttgart/mi/sd1/weather/model/Weather.java">Weather</link> parse(final String jsonWeatherDataFilename) + throws IOException { + return ...; + } +}</programlisting> + + <programlisting language="java">@Test <link + xlink:href="https://gitlab.mi.hdm-stuttgart.de/goik/GoikLectures/blob/master/Doc/Sd1/Ref/Projects/WeatherSkeleton/src/test/java/de/hdm_stuttgart/mi/sd1/weather/WeatherDataParseTest.java">public void testParseWeatherData()</link> { +... + Weather weather = WeatherDataParser.parse( + "src/main/resources/stuttgart.weather.json"); +...</programlisting> + </figure> + + <figure xml:id="sd1_weather_fig_weatherRequirements"> + <title>Requirements</title> + + <orderedlist> + <listitem> + <para>The application shall accept a command line parameter like + e.g. »Stuttgart« to filter matching cities from <filename + xlink:href="https://gitlab.mi.hdm-stuttgart.de/goik/GoikLectures/blob/master/Doc/Sd1/Ref/Projects/WeatherSkeleton/src/main/resources/cities.list.json">cities.list.json</filename>.</para> + </listitem> + + <listitem> + <para>If a given filter matches multiple locations the user shall + have an option for choosing the desired one.</para> + </listitem> + + <listitem> + <para>The most recent city id value shall be cached in a file. + Subsequent invocations without command line parameter shall + provide a current forecast corresponding to this value.</para> + </listitem> + + <listitem> + <para>Weather data belonging to a given id value shall be cached + locally for 10 minutes. Subsequent weather queries within this + period shall be read from cache rather than by accessing + <uri>https://api.openweathermap.org/...</uri> .</para> + + <para>Provide logging to a file rather than to the console to + avoid cluttering the user interface. Log cache handling.</para> + </listitem> + </orderedlist> + </figure> + + <figure xml:id="sd1_weather_fig_weatherLogging"> + <title>Logging</title> + + <itemizedlist> + <listitem> + <para>Provide logging to a file rather than to the console to + avoid cluttering the user interface.</para> + </listitem> + + <listitem> + <para>Log cache handling.</para> + </listitem> + </itemizedlist> + + <screen>main INFO weather.Forecast - Re-using cache file + '/ma/goik/Forecast/6930414.json' from 196 seconds ago</screen> + </figure> + + <section xml:id="sd1_sect_projectWeatherForecastRequirements"> + <title>Requirements</title> + </section> </section> <section xml:id="sd1_sect_projectRpnCalculator">