A lot #1

Merged
Vulpovile merged 2 commits from feature/current_conditions into master 2025-04-27 04:30:38 +00:00
5 changed files with 306 additions and 85 deletions

View File

@@ -67,9 +67,23 @@ public class CanadaDatamartProvider extends ForecastProvider {
String code = data[0].trim(); String code = data[0].trim();
String town = data[1].trim(); String town = data[1].trim();
String province = data[2].trim(); String province = data[2].trim();
String supportedDisplaysString = propertyManager.getStringNoSet("displays-enabled.code."+code, "");
if(supportedDisplaysString.trim().length() <= 0)
supportedDisplaysString = propertyManager.getString("displays-enabled.town."+town.toLowerCase().replaceAll("\\s", "_")+"."+province.toLowerCase().replace("\\s", "_"), "");
float latitude = Float.parseFloat(data[3].trim().substring(0, data[3].length()-1)); float latitude = Float.parseFloat(data[3].trim().substring(0, data[3].length()-1));
float longitude = Float.parseFloat(data[4].trim().substring(0, data[4].length()-1)); float longitude = Float.parseFloat(data[4].trim().substring(0, data[4].length()-1));
towns.add(new TownInfo(code, town, province, latitude, longitude, priority)); TownInfo townInfo = new TownInfo(code, town, province, latitude, longitude, priority);
if(supportedDisplaysString.trim().length() > 0)
{
String[] displays = supportedDisplaysString.split(",");
for(int i = 0; i < displays.length; i++)
{
displays[i] = displays[i].trim();
}
townInfo.setSupportedDisplays(displays);
}
towns.add(townInfo);
} }
} }
} }

View File

@@ -4,6 +4,7 @@ import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
import com.flaremicro.util.Util; import com.flaremicro.util.Util;
import com.flaremicro.visualforecast.icons.IconProvider; import com.flaremicro.visualforecast.icons.IconProvider;
@@ -12,6 +13,7 @@ public class DatamartTranslation {
private HashMap<Integer, Byte> iconTranslation = new HashMap<Integer, Byte>(); private HashMap<Integer, Byte> iconTranslation = new HashMap<Integer, Byte>();
private HashMap<String, WeatherLines> stringTranslation = new HashMap<String, WeatherLines>(); private HashMap<String, WeatherLines> stringTranslation = new HashMap<String, WeatherLines>();
private HashMap<String, WeatherLines> fallBacks = new HashMap<String, WeatherLines>();
public DatamartTranslation() { public DatamartTranslation() {
iconTranslation.put(0, IconProvider.SUN.id); iconTranslation.put(0, IconProvider.SUN.id);
@@ -65,16 +67,18 @@ public class DatamartTranslation {
{ {
reader = new BufferedReader(new InputStreamReader(this.getClass().getResourceAsStream("/translation.csv"))); reader = new BufferedReader(new InputStreamReader(this.getClass().getResourceAsStream("/translation.csv")));
String line; String line;
while((line = reader.readLine()) != null) while ((line = reader.readLine()) != null)
{ {
String[] info = line.split(","); String[] info = line.split(",");
if(info.length == 2) if (info.length == 2)
{ {
stringTranslation.put(info[0].toLowerCase(), new WeatherLines(info[1], "")); stringTranslation.put(info[0].toLowerCase(), new WeatherLines(info[1], ""));
fallBacks.put(info[1], new WeatherLines(info[1], ""));
} }
else if(info.length == 3) else if (info.length == 3)
{ {
stringTranslation.put(info[0].toLowerCase(), new WeatherLines(info[1], info[2])); stringTranslation.put(info[0].toLowerCase(), new WeatherLines(info[1], info[2]));
fallBacks.put(info[1] + " " + info[2], new WeatherLines(info[1], info[2]));
} }
} }
} }
@@ -90,20 +94,164 @@ public class DatamartTranslation {
} }
public byte icon(int icon) { public byte icon(int icon) {
if(!iconTranslation.containsKey(icon)) if (!iconTranslation.containsKey(icon))
return IconProvider.INVALID.id; return IconProvider.INVALID.id;
return iconTranslation.get(icon); return iconTranslation.get(icon);
} }
public WeatherLines weatherName(String desc) { public WeatherLines weatherName(String desc) {
WeatherLines lines = stringTranslation.get(desc.toLowerCase()); WeatherLines lines = stringTranslation.get(desc.toLowerCase());
if(lines == null) if (lines == null)
{ {
System.out.println("FAILED:"+desc.toLowerCase()); System.out.println("FAILED:" + desc.toLowerCase());
return new WeatherLines("TRANSLAT.", "FAILURE"); return getClosestMatching(desc);
} }
else return lines; else return lines;
} }
public WeatherLines getClosestMatching(String desc) {
WeatherLines bestMatch = new WeatherLines("TRANSLAT.", "FAILURE");
desc = desc.toLowerCase();
double bestRatio = Integer.MAX_VALUE;
for (Map.Entry<String, WeatherLines> set : fallBacks.entrySet())
{
double ratio2 = getLevenshteinDistance(desc, set.getKey());
if (ratio2 < bestRatio)
{
bestRatio = ratio2;
bestMatch = set.getValue();
}
}
System.out.println("Got " + bestMatch.line1 + " " + bestMatch.line2 + " for desc " + desc);
return bestMatch;
}
public static int getLevenshteinDistance(CharSequence s, CharSequence t) {
if (s == null || t == null)
{
throw new IllegalArgumentException("Strings must not be null");
}
int n = s.length();
int m = t.length();
if (n == 0)
{
return m;
}
else if (m == 0)
{
return n;
}
if (n > m)
{
// swap the input strings to consume less memory
final CharSequence tmp = s;
s = t;
t = tmp;
n = m;
m = t.length();
}
final int[] p = new int[n + 1];
// indexes into strings s and t
int i; // iterates through s
int j; // iterates through t
int upper_left;
int upper;
char t_j; // jth character of t
int cost;
for (i = 0; i <= n; i++)
{
p[i] = i;
}
for (j = 1; j <= m; j++)
{
upper_left = p[0];
t_j = t.charAt(j - 1);
p[0] = j;
for (i = 1; i <= n; i++)
{
upper = p[i];
cost = s.charAt(i - 1) == t_j ? 0 : 1;
// minimum of cell to the left+1, to the top+1, diagonally left and up +cost
p[i] = Math.min(Math.min(p[i - 1] + 1, p[i] + 1), upper_left + cost);
upper_left = upper;
}
}
return p[n];
}
double findSimilarityRatio(String sentence1, String sentence2) {
HashMap<String, Integer> firstSentenceMap = new HashMap<String, Integer>();
HashMap<String, Integer> secondSentenceMap = new HashMap<String, Integer>();
String[] firstSentenceWords = sentence1.split(" ");
String[] secondSentenceWords = sentence2.split(" ");
for (String word : firstSentenceWords)
{
if (firstSentenceMap.containsKey(word))
{
firstSentenceMap.put(word, firstSentenceMap.get(word) + 1);
}
else
{
firstSentenceMap.put(word, 1);
}
}
for (String word : secondSentenceWords)
{
if (secondSentenceMap.containsKey(word))
{
secondSentenceMap.put(word, secondSentenceMap.get(word) + 1);
}
else
{
secondSentenceMap.put(word, 1);
}
}
double totalWords = 0;
double totalHits = 0;
if (firstSentenceWords.length >= secondSentenceWords.length)
{
totalWords = firstSentenceWords.length;
for (Map.Entry<String, Integer> entry : firstSentenceMap.entrySet())
{
String key = entry.getKey();
if (secondSentenceMap.containsKey(key))
{
totalHits = totalHits + Math.min(secondSentenceMap.get(key), firstSentenceMap.get(key));
}
}
}
else
{
totalWords = secondSentenceWords.length;
for (Map.Entry<String, Integer> entry : secondSentenceMap.entrySet())
{
String key = entry.getKey();
if (firstSentenceMap.containsKey(key))
{
totalHits = totalHits + Math.min(secondSentenceMap.get(key), firstSentenceMap.get(key));
}
}
}
return totalHits / totalWords;
}
} }
class WeatherLines { class WeatherLines {

View File

@@ -11,7 +11,6 @@ import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.Locale; import java.util.Locale;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import javax.xml.XMLConstants; import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
@@ -26,6 +25,7 @@ import org.xml.sax.SAXException;
import com.flaremicro.util.Util; import com.flaremicro.util.Util;
import com.flaremicro.visualforecast.forecast.DayForecast; import com.flaremicro.visualforecast.forecast.DayForecast;
import com.flaremicro.visualforecast.forecast.DetailedForecast;
import com.flaremicro.visualforecast.forecast.ForecastDetails; import com.flaremicro.visualforecast.forecast.ForecastDetails;
import com.flaremicro.visualforecast.forecast.HourlyForecast; import com.flaremicro.visualforecast.forecast.HourlyForecast;
import com.flaremicro.visualforecast.forecast.TownForecast; import com.flaremicro.visualforecast.forecast.TownForecast;
@@ -77,7 +77,7 @@ public class ForecastProcessor implements Runnable {
return -1; return -1;
} }
public void processHourlyForecast(TownForecast forecast, Document doc) { public HourlyForecast[] processHourlyForecast(Document doc) {
DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmm"); DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmm");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
NodeList hourlyForecast = doc.getElementsByTagName("hourlyForecast"); NodeList hourlyForecast = doc.getElementsByTagName("hourlyForecast");
@@ -106,7 +106,7 @@ public class ForecastProcessor implements Runnable {
} }
} }
} }
forecast.setHourlyForecast(hourlyForecastArray.toArray(new HourlyForecast[0])); return hourlyForecastArray.toArray(new HourlyForecast[0]);
} }
public void processForecasts() { public void processForecasts() {
@@ -115,7 +115,6 @@ public class ForecastProcessor implements Runnable {
ArrayList<TownForecast> townForecasts = new ArrayList<TownForecast>(); ArrayList<TownForecast> townForecasts = new ArrayList<TownForecast>();
for (TownInfo townInfo : towns) for (TownInfo townInfo : towns)
{ {
DayForecast[] dayForecasts = new DayForecast[8];
InputStream is = null; InputStream is = null;
Document doc = null; Document doc = null;
try try
@@ -145,6 +144,41 @@ public class ForecastProcessor implements Runnable {
if (doc != null) if (doc != null)
{ {
TownForecast tf = new TownForecast(townInfo.townName + ", " + townInfo.province, process7DayForecast(doc));
townForecasts.add(tf);
tf.setHourlyForecast(this.processHourlyForecast(doc));
tf.setDetailedForecast(process36HourForecast(doc));
tf.setSupportedDisplays(townInfo.getSupportedDisplays());
}
}
forecastDetails.setTownForecast(townForecasts.toArray(new TownForecast[0]));
setMostRecentForecast(forecastDetails);
}
private DetailedForecast[] process36HourForecast(Document doc)
{
DetailedForecast[] detailedForecast = new DetailedForecast[3];
NodeList nodeList = doc.getElementsByTagName("forecast");
for (int i = 0; i < Math.min(detailedForecast.length, nodeList.getLength()); i++)
{
if (nodeList.item(1).getNodeType() == Node.ELEMENT_NODE)
{
if (nodeList.item(1).getNodeType() == Node.ELEMENT_NODE)
{
Element node = (Element) nodeList.item(i);
String title = XMLUtils.getStringFromTagAttribute(node, "period", "textForecastName");
String textForecast = XMLUtils.getStringFromTag(node, "textSummary");
detailedForecast[i] = new DetailedForecast(title, textForecast);
}
}
}
return detailedForecast;
}
private DayForecast[] process7DayForecast(Document doc)
{
DayForecast[] dayForecasts = new DayForecast[8];
NodeList nodeList = doc.getElementsByTagName("forecast"); NodeList nodeList = doc.getElementsByTagName("forecast");
for (int i = 0; i < nodeList.getLength(); i++) for (int i = 0; i < nodeList.getLength(); i++)
{ {
@@ -224,25 +258,21 @@ public class ForecastProcessor implements Runnable {
dayForecasts[i] = new DayForecast(); dayForecasts[i] = new DayForecast();
} }
} }
TownForecast tf = new TownForecast(townInfo.townName + ", " + townInfo.province, dayForecasts); return dayForecasts;
townForecasts.add(tf);
this.processHourlyForecast(tf, doc);
}
}
forecastDetails.setTownForecast(townForecasts.toArray(new TownForecast[0]));
setMostRecentForecast(forecastDetails);
} }
public void begin() { public void begin() {
if (!running) if (!running)
{ {
running = true; running = true;
new Thread(this).start(); self = new Thread(this);
self.start();
} }
} }
public void end() { public void end() {
running = false; running = false;
if(self != null)
self.interrupt(); self.interrupt();
} }
@@ -262,7 +292,6 @@ public class ForecastProcessor implements Runnable {
@Override @Override
public void run() { public void run() {
self = Thread.currentThread();
while (running) while (running)
{ {
try try

View File

@@ -1,5 +1,11 @@
package com.flaremicro.visualforecast.datamart; package com.flaremicro.visualforecast.datamart;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class TownInfo implements Comparable<TownInfo> { public class TownInfo implements Comparable<TownInfo> {
public final String code; public final String code;
public final String townName; public final String townName;
@@ -7,6 +13,7 @@ public class TownInfo implements Comparable<TownInfo> {
public final float northLat; public final float northLat;
public final float westLong; public final float westLong;
public final int priority; public final int priority;
private Set<String> displays = new HashSet<String>();
public TownInfo(String code, String townName, String province, float northLat, float westLong, int priority) { public TownInfo(String code, String townName, String province, float northLat, float westLong, int priority) {
this.code = code; this.code = code;
@@ -21,4 +28,24 @@ public class TownInfo implements Comparable<TownInfo> {
public int compareTo(TownInfo o) { public int compareTo(TownInfo o) {
return priority - o.priority; return priority - o.priority;
} }
public void addSupportedDisplay(String display)
{
this.displays.add(display);
}
public void setSupportedDisplays(String ... displays){
setSupportedDisplays(Arrays.asList(displays));
}
public void setSupportedDisplays(Collection<String> displays){
this.displays.clear();
this.displays.addAll(displays);
}
public Set<String> getSupportedDisplays()
{
return Collections.unmodifiableSet(displays);
}
} }

View File

@@ -14,10 +14,11 @@ partly cloudy,Partly,Cloudy,
showers or drizzle,Showers/,Drizzle showers or drizzle,Showers/,Drizzle
Chance of showers,Chance,Showers Chance of showers,Chance,Showers
A few showers,Few,Showers A few showers,Few,Showers
chance of drizzle,Chance,Drizzle
Chance of drizzle or rain,Chance,Drizzle Chance of drizzle or rain,Chance,Drizzle
A few flurries or rain showers,Flurries/,Showers A few flurries or rain showers,Flurries/,Showers
Chance of flurries or rain showers,Flurries/,Showers Chance of flurries or rain showers,Flurries/,Showers
Chance of rain showers or flurries,Showers/Flurries Chance of rain showers or flurries,Showers/,Flurries
chance of rain showers or wet flurries,Showers/,Flurries chance of rain showers or wet flurries,Showers/,Flurries
A few flurries,Flurries, A few flurries,Flurries,
Chance of flurries,Chance,Flurries Chance of flurries,Chance,Flurries
@@ -34,6 +35,7 @@ Overcast,Overcast,
Showers,Showers, Showers,Showers,
Chance of showers,Chance,Showers Chance of showers,Chance,Showers
Periods of rain,Scattered,Rain Periods of rain,Scattered,Rain
Periods of drizzle,Scattered,Rain
Mostly Cloudy,Mostly,Cloudy Mostly Cloudy,Mostly,Cloudy
Rain at times heavy,Heavy,Rain Rain at times heavy,Heavy,Rain
A few showers or drizzle,Drizzle A few showers or drizzle,Drizzle
@@ -102,3 +104,4 @@ Snow and blowing snow,Blowing,Snow
Windy,Windy Windy,Windy
Smoke,Smoke Smoke,Smoke
rain showers or flurries,Showers/,Flurries rain showers or flurries,Showers/,Flurries
chance of wet flurries,Wet,Flurries
Can't render this file because it has a wrong number of fields in line 13.