Newer
Older
weather-servlet / src / main / scala / uk / org / floop / msc / comet / WeatherActor.scala
package uk.org.floop.msc.comet

import scala.collection.mutable.HashMap

import net.liftweb.http._
import net.liftweb.http.js.JsCmds._
import net.liftweb.util._

import uk.org.floop.msc.rrd._
import uk.org.floop.msc.wview.Forecast

class WeatherActor extends CometActor {
  
  override def defaultPrefix = Full("weather")
  def COMPASS_ROSE = List("N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE",
                          "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW")
  
  var currentWeather: List[Pair[String, Any]] = Nil
  val currentWeatherMap = new HashMap[String, Any]()
  
  def direction(d: Option[Any]) = d match {
    case Some(angle: Short) => COMPASS_ROSE((angle / 22.5 + 0.5).toInt % 16)
    case None => "unknown"
  }
  
  def knots(s: Option[Any]): String = s match {
    case Some(mph: Short) =>
      val k = (mph / 1.15077945 + 0.5).toInt
      if (k == 1) {
        "1 knot"
      } else {
        k + " knots"
      }
    case None => "unknown"
  }
  
  def temp(t: Option[Any]): String = t match {
    case Some(f: Float) =>
      val c = (f - 32) * 5 / 9;
      c.toDouble.formatted("%.1f")
    case None => "unknown"
  }
  
  def pressure(p: Option[Any]): String = p match {
    case Some(inchesMercury: Float) =>
      val millibar = (inchesMercury * 33.86389).toInt
      millibar + " mb"
    case None => "unknown"
  }
  
  def humidity(h: Option[Any]): String = h match {
    case Some(p: Short) => p + "%"
    case None => "unknown"
  }
  
  def rain(r: Option[Any]): String = r match {
    case Some(inHr: Float) => (inHr * 25.4).toInt + " mm/hr"
    case None => "unknown"
  }
  
  def forecast(f: Option[Any]): String = f match {
    case Some(rule: Short) => Forecast.getRule(rule)
    case None => "unknown"
  } 
  
  def render: RenderOut = {
    new RenderOut(bind("view" ->
      <table>
        <tr><td>Wind Direction:</td><td>{direction(currentWeatherMap.get("windDir"))}</td></tr>
        <tr><td>Wind Speed:</td><td>{knots(currentWeatherMap.get("windSpeed"))}</td></tr>
        <tr><td>Temperature:</td><td>{temp(currentWeatherMap.get("outTemp"))} &deg;C</td></tr>
        <tr><td>Air Pressure:</td><td>{pressure(currentWeatherMap.get("barometer"))}</td></tr>
        <tr><td>Relative Humidity:</td><td>{humidity(currentWeatherMap.get("outHumidity"))}</td></tr>
        <tr><td>Rain Rate:</td><td>{rain(currentWeatherMap.get("rainRate"))}</td></tr>
        <tr><td>Forecast:</td><td>{forecast(currentWeatherMap.get("forecastRule"))}</td></tr>                                                                             
      </table>),
      currentWeatherMap.get("windDir") match {
        case Some(angle) => Run("drawWind(" + angle + ")")
        case None => Noop
      }
    )      
  }
  
  override def localSetup {
    DataStore !? AddWeatherListener(this) match {
      case CurrentWeather(w) =>
        currentWeather = w
        w.foreach(pair => currentWeatherMap(pair._1) = pair._2)
    }
  }
  
  override def localShutdown {
    DataStore ! RemoveWeatherListener(this)
  }
  
  override def lowPriority: PartialFunction[Any, Unit] = {
    case CurrentWeather(w) =>
      val diff = w -- currentWeather
      diff.foreach(pair => currentWeatherMap(pair._1) = pair._2)
      currentWeather = w
      reRender(false)
  }
}