repositories {
mavenCentral()
+ maven {
+ url "http://dl.bintray.com/kotlinx/kotlinx"
+ }
}
dependencies {
compile group: "com.fasterxml.jackson.core", name: "jackson-annotations", version: "2.1.2"
compile group: "com.fasterxml.jackson.core", name: "jackson-databind", version: "2.1.2"
compile group: "com.google.inject", name: "guice", version: "4.0"
+ compile group: "org.jetbrains.kotlinx", name: "kotlinx.html", version: "0.5.8"
+ compile group: "org.jetbrains.kotlinx", name: "kotlinx.html.jvm", version: "0.5.8"
testCompile group: "junit", name: "junit", version:"4.12"
testCompile group: "org.hamcrest", name: "hamcrest-library", version:"1.3"
--- /dev/null
+package net.pterodactylus.rhynodge.webpages.weather.wettercom
+
+import kotlinx.html.body
+import kotlinx.html.div
+import kotlinx.html.h1
+import kotlinx.html.head
+import kotlinx.html.html
+import kotlinx.html.img
+import kotlinx.html.stream.createHTML
+import kotlinx.html.style
+import net.pterodactylus.rhynodge.Reaction
+import net.pterodactylus.rhynodge.State
+import net.pterodactylus.rhynodge.Trigger
+import net.pterodactylus.rhynodge.output.DefaultOutput
+import net.pterodactylus.rhynodge.output.Output
+import java.text.DateFormat
+import java.time.temporal.ChronoUnit.HOURS
+import java.util.Locale
+
+/**
+ * TODO
+ *
+ * @author [David ‘Bombe’ Roden](mailto:bombe@pterodactylus.net)
+ */
+class WetterComTrigger : Trigger {
+
+ private val dateFormatter = DateFormat.getDateInstance(DateFormat.LONG, Locale.ENGLISH)
+ private var newState = false
+ private lateinit var currentState: WetterComState
+
+ override fun mergeStates(previousState: State, currentState: State): State? {
+ newState = previousState != currentState
+ this.currentState = currentState as WetterComState
+ return currentState
+ }
+
+ override fun triggers(): Boolean {
+ return newState
+ }
+
+ override fun output(reaction: Reaction): Output {
+ val output = DefaultOutput("The weather (according to wetter.com) on %s".format(dateFormatter.format(currentState.dateTime.toInstant().toEpochMilli())))
+ output.addText("text/html", htmlOutput())
+ return output
+ }
+
+ private fun htmlOutput(): String {
+ return createHTML().html {
+ head {
+ style("text/css") {
+ +".hour-state { display: table-row; }"
+ +".hour-state > div { display: table-cell; }"
+ }
+ }
+ body {
+ val startTime = currentState.dateTime.toInstant()
+ h1 { +"The Weather (according to wetter.com) on %s".format(dateFormatter.format(startTime.toEpochMilli())) }
+ currentState.forEach {
+ div("hour-state") {
+ div("time") { +"%tH:%<tM".format(startTime.plus(it.hourIndex.toLong(), HOURS).toEpochMilli()) }
+ div("temperature") { +"%d °C".format(it.temperature.toInt()) }
+ div("rain-probability") { +"%d%%".format((it.rainProbability * 100).toInt()) }
+ div("rain-amount") { +"%d l/m²".format(it.rainAmount.toInt()) }
+ div("wind-direction") { +it.windDirection.name }
+ div("wind-speed") { +"%d km/h".format(it.windSpeed.toInt()) }
+ div("description") { +it.description }
+ div("image") { img(src = it.image) }
+ }
+ }
+ }
+ }.toString()
+ }
+
+}
--- /dev/null
+package net.pterodactylus.rhynodge.webpages.weather.wettercom
+
+import net.pterodactylus.rhynodge.Reaction
+import org.hamcrest.MatcherAssert.assertThat
+import org.hamcrest.Matchers.`is`
+import org.hamcrest.Matchers.containsString
+import org.junit.Test
+import org.mockito.Mockito
+import java.time.ZoneId
+import java.time.ZonedDateTime
+
+/**
+ * Unit test for [WetterComTrigger].
+
+ * @author [David ‘Bombe’ Roden](mailto:bombe@pterodactylus.net)
+ */
+class WetterComTriggerTest {
+
+ private val trigger = WetterComTrigger()
+ private val now = ZonedDateTime.now()
+ private val previousState = WetterComState(now)
+
+ @Test
+ fun equalStatesAreNotMerged() {
+ val currentState = WetterComState(now)
+ val newState = trigger.mergeStates(previousState, currentState) as WetterComState
+ assertThat(newState, `is`(previousState))
+ assertThat(newState, `is`(currentState))
+ }
+
+ @Test
+ fun currentStateIsReturnedIfDifferentFromPreviousState() {
+ val currentState = WetterComState(now.minusDays(1))
+ val newState = trigger.mergeStates(previousState, currentState) as WetterComState
+ assertThat(newState, `is`(currentState))
+ }
+
+ @Test
+ fun mergingEqualStatesDoesNotTrigger() {
+ val currentState = WetterComState(now)
+ trigger.mergeStates(previousState, currentState) as WetterComState
+ assertThat(trigger.triggers(), `is`(false))
+ }
+
+ @Test
+ fun mergingDifferentStatesDoesTrigger() {
+ val currentState = WetterComState(now.minusDays(1))
+ trigger.mergeStates(previousState, currentState) as WetterComState
+ assertThat(trigger.triggers(), `is`(true))
+ }
+
+ @Test
+ fun outputSummaryContainsCorrectDate() {
+ val currentState = WetterComState(ZonedDateTime.of(2000, 1, 1, 5, 0, 0, 0, ZoneId.of("Europe/Berlin")))
+ trigger.mergeStates(previousState, currentState) as WetterComState
+ val reaction = Mockito.mock(Reaction::class.java)
+ val output = trigger.output(reaction)
+ assertThat(output.summary(), `is`("The weather (according to wetter.com) on January 1, 2000"))
+ }
+
+ @Test
+ fun outputHtmlContainsHourStates() {
+ val currentState = WetterComState(now.minusDays(1))
+ currentState.addHour(HourState(0, 10.0, 0.11, 12.0, WindDirection.NORTH, 13.0, "Rain", "http://1"))
+ currentState.addHour(HourState(1, 14.0, 0.15, 16.0, WindDirection.SOUTH, 17.0, "Sun", "http://2"))
+ trigger.mergeStates(previousState, currentState) as WetterComState
+ val reaction = Mockito.mock(Reaction::class.java)
+ val output = trigger.output(reaction)
+ val htmlText = output.text("text/html", -1)
+ assertThat(htmlText, containsString("10 °C"))
+ assertThat(htmlText, containsString("11%"))
+ assertThat(htmlText, containsString("12 l/m"))
+ assertThat(htmlText, containsString("13 km/h"))
+ assertThat(htmlText, containsString("Rain"))
+ assertThat(htmlText, containsString("http://1"))
+ assertThat(htmlText, containsString("14 °C"))
+ assertThat(htmlText, containsString("15%"))
+ assertThat(htmlText, containsString("16 l/m"))
+ assertThat(htmlText, containsString("17 km/h"))
+ assertThat(htmlText, containsString("Sun"))
+ assertThat(htmlText, containsString("http://2"))
+ }
+
+}