Initial Commit

This commit is contained in:
Flare Microsystems
2024-03-07 14:15:34 -08:00
commit 37c506249a
12 changed files with 669 additions and 0 deletions

View File

@@ -0,0 +1,213 @@
package com.flaremicro.visualforecast.datamart;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import com.flaremicro.util.Util;
import com.flaremicro.visualforecast.forecast.DayForecast;
import com.flaremicro.visualforecast.forecast.ForecastDetails;
import com.flaremicro.visualforecast.forecast.TownForecast;
import com.flaremicro.visualforecast.forecast.ValueCheck;
public class ForecastProcessor implements Runnable {
private final TownInfo[] towns;
private ForecastDetails mostRecentForecast = null;
private boolean running = false;
private Thread self;
private DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
private DatamartTranslation dmt = new DatamartTranslation();
public ForecastProcessor(TownInfo[] towns) {
this.towns = towns;
try
{
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
}
catch (ParserConfigurationException e)
{
e.printStackTrace();
}
}
public void stringToOffset(String dayString) {
}
public int getDayIndex(String dayString) {
dayString = dayString.trim();
if (dayString.equalsIgnoreCase("today") || dayString.equalsIgnoreCase("tonight"))
return 0;
dayString = dayString.toLowerCase().replace("night", "").trim();
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
for (int i = 1; i < 8; i++)
{
calendar.add(Calendar.HOUR, 24);
if (calendar.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.US).equalsIgnoreCase(dayString))
return i;
}
return -1;
}
public void processForecasts() {
ForecastDetails forecastDetails = new ForecastDetails();
ArrayList<TownForecast> townForecasts = new ArrayList<TownForecast>();
for (TownInfo townInfo : towns)
{
DayForecast[] dayForecasts = new DayForecast[8];
InputStream is = null;
try
{
URL url = new URL("https://dd.weather.gc.ca/citypage_weather/xml/BC/" + townInfo.code + "_e.xml");
DocumentBuilder db = dbf.newDocumentBuilder();
is = url.openStream();
Document doc = db.parse(is);
NodeList nodeList = doc.getElementsByTagName("forecast");
for (int i = 0; i < nodeList.getLength(); i++)
{
if (nodeList.item(1).getNodeType() == Node.ELEMENT_NODE)
{
Element node = (Element) nodeList.item(i);
int dayIndex = getDayIndex(XMLUtils.getStringFromTagAttribute(node, "period", "textForecastName"));
Element abbForecast = XMLUtils.getFistElement(node, "abbreviatedForecast");
int iconIndex = XMLUtils.getIntFromTag(abbForecast, "iconCode", 0);
String textForecast = XMLUtils.getStringFromTag(abbForecast, "textSummary");
WeatherLines lines = dmt.weatherName(textForecast);
byte icon = dmt.icon(iconIndex);
byte lo = ValueCheck.NO_DATA_BYTE;
byte hi = ValueCheck.NO_DATA_BYTE;
Element element = XMLUtils.getFistElement(node, "temperatures");
NodeList temps = element.getElementsByTagName("temperature");
for (int j = 0; j < temps.getLength(); j++)
{
Node n = temps.item(j);
try
{
byte val = Byte.parseByte(n.getTextContent().trim());
if(XMLUtils.getStringFromAttribute(n, "class").trim().equalsIgnoreCase("high"))
{
hi = val;
}
else if(XMLUtils.getStringFromAttribute(n, "class").trim().equalsIgnoreCase("low"))
{
lo = val;
}
}
catch (NumberFormatException ex)
{
}
}
if (dayIndex >= 0 && dayIndex <= 7)
{
if (dayForecasts[dayIndex] != null)
{
if (lo != ValueCheck.NO_DATA_BYTE && dayForecasts[dayIndex].loTemp == ValueCheck.NO_DATA_BYTE)
{
dayForecasts[dayIndex].loTemp = lo;
}
if (hi != ValueCheck.NO_DATA_BYTE && dayForecasts[dayIndex].hiTemp == ValueCheck.NO_DATA_BYTE)
{
dayForecasts[dayIndex].hiTemp = hi;
}
}
else
{
dayForecasts[dayIndex] = new DayForecast(hi, lo, icon, lines.line1, lines.line2, ValueCheck.NO_DATA_FLOAT);
}
}
}
}
}
catch (IOException e)
{
e.printStackTrace();
}
catch (ParserConfigurationException e)
{
e.printStackTrace();
}
catch (SAXException e)
{
e.printStackTrace();
}
finally
{
Util.cleanClose(is);
}
for (int i = 0; i < dayForecasts.length; i++)
{
if (dayForecasts[i] == null)
{
dayForecasts[i] = new DayForecast();
}
}
townForecasts.add(new TownForecast(townInfo.townName + ", " + townInfo.province, dayForecasts));
}
forecastDetails.setTownForecast(townForecasts.toArray(new TownForecast[0]));
setMostRecentForecast(forecastDetails);
}
public void end() {
running = false;
self.interrupt();
}
public ForecastDetails getMostRecentForecast() {
synchronized (this)
{
return mostRecentForecast;
}
}
private void setMostRecentForecast(ForecastDetails forecast) {
synchronized (this)
{
mostRecentForecast = forecast;
}
}
@Override
public void run() {
self = Thread.currentThread();
while (running)
{
try
{
Thread.sleep(TimeUnit.MILLISECONDS.convert(1, TimeUnit.HOURS));
processForecasts();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}