ProgressWeather was finished

This commit is contained in:
Robert Vokac 2024-03-23 16:31:36 +01:00
parent 7f035a931d
commit 604d2384cf
No known key found for this signature in database
GPG Key ID: 693D30BEE3329055
13 changed files with 923 additions and 307 deletions

View File

@ -1,6 +1,8 @@
package org.nanoboot.utils.timecalc.app;
import java.io.File;
import java.io.IOException;
import org.nanoboot.utils.timecalc.utils.common.FileConstants;
/**
* @author Robert Vokac
@ -9,6 +11,12 @@ import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
// for(File f:FileConstants.CLIMATE_TXT.getParentFile().listFiles()) {
// if(f.getName().contains("weather")) {
// System.out.println("Going to delete: " + f.getAbsolutePath());
// f.delete();
// }
// }
TimeCalcApp timeCalcApp = new TimeCalcApp();
timeCalcApp.start(args);
}

View File

@ -31,6 +31,7 @@ import java.awt.event.MouseMotionListener;
import java.util.List;
import java.util.Locale;
import java.util.function.Consumer;
import javax.swing.JMenuItem;
/**
* @author Robert Vokac
@ -170,7 +171,7 @@ public class Widget extends JPanel implements
private void showPopup(MouseEvent e) {
if(widgetMenu == null) {
widgetMenu = new WidgetMenu(widget, createRefreshConsumer());
List<JMenu> additionalMenus = createAdditionalMenus();
List<JMenuItem> additionalMenus = createAdditionalMenus();
if(additionalMenus != null) {
additionalMenus.forEach(m-> widgetMenu.add(m));
}
@ -191,7 +192,7 @@ public class Widget extends JPanel implements
protected Consumer<Object> createRefreshConsumer() {
return null;
}
protected List<JMenu> createAdditionalMenus() {
protected List<JMenuItem> createAdditionalMenus() {
return null;
}
@ -242,12 +243,21 @@ public class Widget extends JPanel implements
if (visibleProperty.isDisabled() || hidden) {
if(hidden) {
if(this.smileyIcon != null) {
this.remove(this.smileyIcon);
this.smileyIcon = null;
}
if(this.smileyIcon2 != null) {
this.remove(this.smileyIcon2);
this.smileyIcon2 = null;
}
if (mouseOver) {
Color currentColor = brush.getColor();
brush.setColor(VERY_LIGHT_GRAY);
brush.fillRect(1, 1, getWidth() - 2, getHeight() - 2);
brush.setColor(currentColor);
}
brush.drawString("Show", (int) (getWidth() * 0.5 - 10), (int) (getHeight() * 0.5 - 10));
}
//nothing to do
return;

View File

@ -4,7 +4,7 @@ import org.nanoboot.utils.timecalc.app.TimeCalcException;
import org.nanoboot.utils.timecalc.entity.WidgetType;
import org.nanoboot.utils.timecalc.swing.progress.AnalogClock;
import org.nanoboot.utils.timecalc.swing.progress.Battery;
import org.nanoboot.utils.timecalc.swing.progress.ProgressWeather;
import org.nanoboot.utils.timecalc.swing.progress.weather.ProgressWeather;
import javax.swing.JMenu;
import javax.swing.JMenuItem;

View File

@ -27,6 +27,7 @@ import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.function.Consumer;
import javax.swing.JMenuItem;
//https://kodejava.org/how-do-i-write-a-simple-analog-clock-using-java-2d/
public class AnalogClock extends Widget {
@ -107,7 +108,7 @@ public class AnalogClock extends Widget {
private TMenuItem secondHandMenuItem;
private TMenuItem minuteHandMenuItem;
private TMenuItem hourHandMenuItem;
private List<JMenu> menuItems = null;
private List<JMenuItem> menuItems = null;
public AnalogClock() {
typeProperty.setValue(WidgetType.DAY.name().toLowerCase(Locale.ROOT));
@ -421,7 +422,7 @@ public class AnalogClock extends Widget {
}
@Override
public List<JMenu> createAdditionalMenus() {
public List<JMenuItem> createAdditionalMenus() {
if(menuItems == null) {
menuItems = new ArrayList<>();
JMenu hands = new JMenu("Hands");

View File

@ -1,164 +0,0 @@
package org.nanoboot.utils.timecalc.swing.progress;
import org.nanoboot.utils.timecalc.app.GetProperty;
import org.nanoboot.utils.timecalc.entity.Visibility;
import org.nanoboot.utils.timecalc.entity.WidgetType;
import org.nanoboot.utils.timecalc.swing.common.SwingUtils;
import org.nanoboot.utils.timecalc.swing.common.Widget;
import org.nanoboot.utils.timecalc.swing.windows.MainWindow;
import org.nanoboot.utils.timecalc.utils.common.DateFormats;
import org.nanoboot.utils.timecalc.utils.common.FileConstants;
import org.nanoboot.utils.timecalc.utils.common.TTime;
import org.nanoboot.utils.timecalc.utils.common.Utils;
import org.nanoboot.utils.timecalc.utils.property.Property;
import javax.swing.Timer;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author Robert Vokac
* @since 21.02.2024
*/
public class ProgressWeather extends Widget implements GetProperty {
private final Time time;
public ProgressWeather(Time time) {
this.time = time;
setFont(new Font(Font.MONOSPACED, Font.PLAIN, 11));
setFocusable(false);
setForeground(Color.GRAY);
setBackground(MainWindow.BACKGROUND_COLOR);
this.typeProperty.setValue(WidgetType.DAY.name().toLowerCase(Locale.ROOT));
new Timer(100, e -> {
Visibility visibility
= Visibility.valueOf(visibilityProperty.getValue());
setForeground(
visibility.isStronglyColored()
|| mouseOver
? Color.BLACK : Color.LIGHT_GRAY);
}).start();
}
private static Map<Integer, List<WeatherForecast>> forecastsForYears = new HashMap<>();
@Override
public void paintWidget(Graphics brush) {
Visibility visibility
= Visibility.valueOf(visibilityProperty.getValue());
brush.setColor(visibility.isStronglyColored() ? Color.BLUE
: visibility.isWeaklyColored() ? Color.GRAY
: Color.LIGHT_GRAY);
brush.setFont(SwingUtils.MEDIUM_MONOSPACE_FONT);
int year = time.yearProperty.getValue();
if(!forecastsForYears.containsKey(year)) {
File weatherFile = new File(FileConstants.WEATHER_TXT.getParentFile(),
String.valueOf(year) + '_' + FileConstants.WEATHER_TXT.getName());
System.out.println(weatherFile.getAbsolutePath());
if (!weatherFile.exists()) {
List<WeatherForecast> forecasts = WeatherForecast.createForecast();
Utils.writeTextToFile(weatherFile,
forecasts.stream().map(w -> w.toCsv()).collect(
Collectors.joining("\n")));
}
List<WeatherForecast> forecasts = new ArrayList<>();
try {
Arrays.stream(Utils.readTextFromFile(weatherFile).split("\n")).filter(line -> !line.isEmpty()).forEach(line -> forecasts.add(new WeatherForecast().fromCsv(line)));
} catch (IOException e) {
System.out.println("Loading file failed: " + weatherFile + " " + e
.getMessage());
e.printStackTrace();
return;
}
forecastsForYears.put(year, forecasts);
}
List<WeatherForecast> forecasts = forecastsForYears.get(year);
int currentSecond = time.secondProperty.getValue();
Calendar cal = time.asCalendar();
int add = (currentSecond % 14);
switch (add) {
case 0:
add = 0; break;
case 1:
add = 0; break;
case 2:
add = 1; break;
case 3:
add = 1; break;
case 4:
add = 2; break;
case 5:
add = 2; break;
case 6:
add = 3; break;
case 7:
add = 3; break;
case 8:
add = 4; break;
case 9:
add = 4; break;
case 10:
add = 5; break;
case 11:
add = 5; break;
case 12:
add = 6; break;
case 13:
add = 6; break;
default:
add = 7; break;
}
add = add / 2;
if (add > 0) {
cal.add(Calendar.DAY_OF_MONTH, add);
}
int currentDayOfWeek = time.dayOfWeekProperty.getValue();
int forecastDayOfWeek = currentDayOfWeek + add;
// String dayOfWeekAsString = DayOfWeekTC.forNumber(forecastDayOfWeek).name();
// dayOfWeekAsString = dayOfWeekAsString.substring(0,1).toUpperCase(Locale.ROOT) + dayOfWeekAsString.substring(1, dayOfWeekAsString.length());
WeatherForecast weatherForecast = forecasts.stream().filter(f -> f.getDate().equals(DateFormats.DATE_TIME_FORMATTER_YYYYMMDD.format(cal.getTime()))).findFirst().orElse(new WeatherForecast());
int rowHeight = 25;
int row = 10;
brush.drawString(DateFormats.DATE_TIME_FORMATTER_YYYYMMDD.format(cal.getTime()), SwingUtils.MARGIN, SwingUtils.MARGIN + row);
row = row + rowHeight;
brush.drawString(DateFormats.DATE_TIME_FORMATTER_DAY_OF_WEEK.format(cal.getTime()), SwingUtils.MARGIN, SwingUtils.MARGIN + row);
row = row + rowHeight;
brush.drawString(weatherForecast.asPrettyString(new TTime(time.hourProperty.getValue(),
time.minuteProperty.getValue(),
time.secondProperty.getValue(),
time.millisecondProperty.getValue()).toTotalMilliseconds() / 1000d / 60d / 60d), SwingUtils.MARGIN, SwingUtils.MARGIN + row);
row = row + rowHeight;
}
@Override
public Property getVisibilityProperty() {
return visibilityProperty;
}
@Override
public Property getVisibilitySupportedColoredProperty() {
return visibilitySupportedColoredProperty;
}
}

View File

@ -1,136 +0,0 @@
package org.nanoboot.utils.timecalc.swing.progress;
import lombok.Getter;
import org.nanoboot.utils.timecalc.utils.common.FileConstants;
import org.nanoboot.utils.timecalc.utils.common.NumberFormats;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/**
* @author pc00289
* @since 22.03.2024
*/
@Getter
public class WeatherForecast {
//01:00-4:00 - minimum
//13:00-16:00 - maximum
//20240101.minTempC=
//20240101.maxTempC=
// 20240101.minTempTime=
//20240101.maxTempTime=
//20240101.wind={m/s}
//20240101.cloudiness={0.0 - 1.0}
//20240101.thunder={0.0 - 1.0}
//20240101.rain={mm}
//20240101.snow={mm}
//#20240101.sunrise=7:53
//#20240101.sunset=16:02
private String date;
private double minimumCelsius;
private double maximumCelsius;
private double minimumCelsiusTime;
private double maximumCelsiusTime;
private double wind;
private double cloudiness;
private double thunder;
private double rain;
private double snow;
public static List<WeatherForecast> createForecast() {
List<WeatherForecast> list = new ArrayList<>();
Properties climateProperties = new Properties();
if(FileConstants.CLIMATE_TXT.exists()) {
try {
climateProperties.load(new FileInputStream(FileConstants.CLIMATE_TXT));
} catch (IOException e) {
e.printStackTrace();
System.out.println("Loading file failed: " + FileConstants.WEATHER_TXT + " " + e.getMessage());
return list;
}
} else {
System.out.println("File does not exist: " + FileConstants.CLIMATE_TXT);
return list;
}
double min1= Double.valueOf(climateProperties.getProperty("1.min", "0"));
double min2= Double.valueOf(climateProperties.getProperty("2.min", "1"));
double min3= Double.valueOf(climateProperties.getProperty("3.min", "2"));
double min4= Double.valueOf(climateProperties.getProperty("4.min", "4"));
double min5= Double.valueOf(climateProperties.getProperty("5.min", "6"));
double min6= Double.valueOf(climateProperties.getProperty("6.min", "8"));
double min7= Double.valueOf(climateProperties.getProperty("7.min", "8"));
double min8= Double.valueOf(climateProperties.getProperty("8.min", "6"));
double min9= Double.valueOf(climateProperties.getProperty("9.min", "4"));
double min10= Double.valueOf(climateProperties.getProperty("10.min", "2"));
double min11= Double.valueOf(climateProperties.getProperty("11.min", "1"));
double min12= Double.valueOf(climateProperties.getProperty("12.min", "0"));
return list;
}
public String toCsv() {
StringBuilder sb = new StringBuilder();
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(minimumCelsius)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(maximumCelsius)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(minimumCelsiusTime)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(maximumCelsiusTime)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(wind)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(cloudiness)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(thunder)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(rain)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(snow));
return sb.toString();
}
public WeatherForecast fromCsv(String csv) {
String[] values = csv.split("\t");
int i = 0;
minimumCelsius = Double.valueOf(values[i++]);
maximumCelsius = Double.valueOf(values[i++]);
minimumCelsiusTime = Double.valueOf(values[i++]);
maximumCelsiusTime = Double.valueOf(values[i++]);
wind = Double.valueOf(values[i++]);
cloudiness = Double.valueOf(values[i++]);
thunder = Double.valueOf(values[i++]);
rain = Double.valueOf(values[i++]);
snow = Double.valueOf(values[i++]);
return this;
}
public String asPrettyString(double forHour) {
return "14°C, wind 7/s, rain 2mm, cloudy";
}
}
/*
climate.txt
1.max=18.8
2.max=22.0
3.max=26.2
4.max=31.8
5.max=35.0
6.max=38.9
7.max=40.2
8.max=40.4
9.max=37.4
10.max=30,3
11.max=24,0
12.max=19.8
1.min=-36.2
2.min=-42.2
3.min=-32.0
4.min=-22.0
5.min=-13.1
6.min=-8.3
7.min=-6.9
8.min=-5.0
9.min=-10.5
10.min=-19.9
11.min=-25.4
12.min=-34.0
*/

View File

@ -0,0 +1,43 @@
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package org.nanoboot.utils.timecalc.swing.progress.weather;
import lombok.Getter;
import org.nanoboot.utils.timecalc.utils.common.NumberFormats;
/**
*
* @author robertvokac
*/
public enum Cloudiness {
CLOUDY("Cloudy", 7d/8d),
MOSTLY_CLOUDY("Mostly cloudy", 5d/8d),
PARTLY_CLOUDY("Partly cloudy+sunny", 3d/8d),
MOSTLY_SUNNY("Mostly clear+sunny", 1d/8d),
SUNNY("Clear/Sunny", 0/8);
@Getter
private String description;
private double ifMoreOrEqual;
Cloudiness(String description, double ifMoreOrEqual) {
this.description = description;
this.ifMoreOrEqual = ifMoreOrEqual;
}
public static Cloudiness forValue(double value) {
for (Cloudiness c : Cloudiness.values()) {
if (value >= c.ifMoreOrEqual) {
return c;
}
}
throw new IllegalStateException("Unsupported value: " + NumberFormats.FORMATTER_TWO_DECIMAL_PLACES.format(value));
}
// Cloudy: 90-100% sky covered
// Mostly cloudy: 70-80% sky covered
// Partly Cloudy/Partly Sunny: 30-60% sky covered
// Mostly Clear/Mostly Sunny: 10-30% sky covered
// Clear/Sunny: 0-10% sky covered
}

View File

@ -0,0 +1,296 @@
package org.nanoboot.utils.timecalc.swing.progress.weather;
import org.nanoboot.utils.timecalc.app.GetProperty;
import org.nanoboot.utils.timecalc.entity.Visibility;
import org.nanoboot.utils.timecalc.entity.WidgetType;
import org.nanoboot.utils.timecalc.swing.common.SwingUtils;
import org.nanoboot.utils.timecalc.swing.common.Widget;
import org.nanoboot.utils.timecalc.swing.windows.MainWindow;
import org.nanoboot.utils.timecalc.utils.common.DateFormats;
import org.nanoboot.utils.timecalc.utils.common.FileConstants;
import org.nanoboot.utils.timecalc.utils.common.TTime;
import org.nanoboot.utils.timecalc.utils.common.Utils;
import org.nanoboot.utils.timecalc.utils.property.Property;
import javax.swing.Timer;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import javax.swing.JMenuItem;
import org.nanoboot.utils.timecalc.swing.progress.Time;
import org.nanoboot.utils.timecalc.utils.common.NumberFormats;
/**
* @author Robert Vokac
* @since 21.02.2024
*/
public class ProgressWeather extends Widget implements GetProperty {
private final Time time;
private int lastAdd = 0;
private List<JMenuItem> menuItems = null;
private boolean information;
public ProgressWeather(Time time) {
this.time = time;
setFont(new Font(Font.MONOSPACED, Font.PLAIN, 11));
setFocusable(false);
setForeground(Color.GRAY);
setBackground(MainWindow.BACKGROUND_COLOR);
this.typeProperty.setValue(WidgetType.DAY.name().toLowerCase(Locale.ROOT));
new Timer(100, e -> {
Visibility visibility
= Visibility.valueOf(visibilityProperty.getValue());
setForeground(
visibility.isStronglyColored()
|| mouseOver
? Color.BLACK : Color.LIGHT_GRAY);
}).start();
}
private static Map<Integer, List<WeatherForecast>> forecastsForYears = new HashMap<>();
@Override
public void paintWidget(Graphics brush) {
Visibility visibility
= Visibility.valueOf(visibilityProperty.getValue());
brush.setColor(visibility.isStronglyColored() ? Color.BLUE
: visibility.isWeaklyColored() ? Color.GRAY
: Color.LIGHT_GRAY);
brush.setFont(SwingUtils.MEDIUM_MONOSPACE_FONT);
int year = time.yearProperty.getValue();
if (!forecastsForYears.containsKey(year)) {
File weatherFile = new File(FileConstants.WEATHER_CSV.getParentFile(),
String.valueOf(year) + '_' + FileConstants.WEATHER_CSV.getName());
System.out.println(weatherFile.getAbsolutePath());
if (!weatherFile.exists()) {
List<WeatherForecast> forecasts = WeatherForecast.createForecast(year);
Utils.writeTextToFile(
weatherFile,
"Date\tMinC\tMaxC\tMinTime\tMaxTime\tWind\tCloudiness\tThunder\tRain\tSnow\tHumidity\tHearOrColdWave\tStartC\tEndC\n"
+ forecasts.stream().map(w -> w.toCsv()).collect(
Collectors.joining("\n")));
}
List<WeatherForecast> forecasts = new ArrayList<>();
try {
Arrays.stream(Utils.readTextFromFile(weatherFile).split("\n"))
.filter(line -> !line.startsWith("Date"))
.filter(line -> !line.isEmpty()).forEach(line -> forecasts.add(new WeatherForecast().fromCsv(line)));
} catch (IOException e) {
System.out.println("Loading file failed: " + weatherFile + " " + e
.getMessage());
e.printStackTrace();
return;
}
forecastsForYears.put(year, forecasts);
}
List<WeatherForecast> forecasts = forecastsForYears.get(year);
// if(!w){
// w= true;
// List<Double> temperature = new ArrayList<>();
// forecasts.stream().forEach(f -> {
//
// for (int hour = 0; hour < 24; hour++) {
// //for (int minute = 0; minute < 60; minute = minute + 30) {
// int minute = 0;
// double forHour = ((double)(new TTime(hour, minute).toTotalMilliseconds() / 1000d / 60d / 60d));
// temperature.add(f.getCelsiusForHour(forHour));
// //}
// }
// });
// StringBuilder sb = new StringBuilder();
// temperature.stream().forEach(t -> sb.append(NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(t)).append("\n"));
// Utils.writeTextToFile(new File("t.csv"), sb.toString());
// }
int currentSecond = time.secondProperty.getValue();
Calendar cal = time.asCalendar();
int add = (currentSecond % 21);
if (paused) {
add = lastAdd;
} else {
if (add < 3) {
add = 0;
} else if (add < 6) {
add = 1;
} else if (add < 9) {
add = 2;
} else if (add < 12) {
add = 3;
} else if (add < 15) {
add = 4;
} else if (add < 18) {
add = 5;
} else if (add < 21) {
add = 6;
}
this.lastAdd = add;
}
if (add > 0) {
cal.add(Calendar.DAY_OF_MONTH, add);
}
int currentDayOfWeek = time.dayOfWeekProperty.getValue();
int forecastDayOfWeek = currentDayOfWeek + add;
// String dayOfWeekAsString = DayOfWeekTC.forNumber(forecastDayOfWeek).name();
// dayOfWeekAsString = dayOfWeekAsString.substring(0,1).toUpperCase(Locale.ROOT) + dayOfWeekAsString.substring(1, dayOfWeekAsString.length());
WeatherForecast wf = forecasts.stream().filter(f -> f.getDate().equals(DateFormats.DATE_TIME_FORMATTER_YYYYMMDD.format(cal.getTime()))).findFirst().orElse(new WeatherForecast());
if(information) {
information = false;
StringBuilder sb = new StringBuilder();
sb.append("Date: ").append(wf.getDate()).append("\n");
sb
.append("Start: ")
.append(NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(wf.getStartCelsius()))
.append(" °C at 00:00")
.append("\n");
sb
.append("Minimum: ")
.append(NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(wf.getMinimumCelsius()))
.append(" °C at ").append(TTime.ofMilliseconds((int) (wf.getMinimumCelsiusTime() * 1000d * 60d * 60d)).toString().substring(0, 5))
.append("\n");
sb
.append("Maximum: ")
.append(NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(wf.getMaximumCelsius()))
.append(" °C at ").append(TTime.ofMilliseconds((int) (wf.getMinimumCelsiusTime() * 1000d * 60d * 60d)).toString().substring(0, 5))
.append("\n");
sb
.append("End: ")
.append(NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(wf.getEndCelsius()))
.append(" °C at 24:00")
.append("\n");
sb.append("Wind: ").append((int)wf.getWind()).append(" m/s\n");
sb.append("Cloudiness: ").append(Cloudiness.forValue(wf.getCloudiness()).getDescription().toLowerCase()).append("\n");
if(wf.getThunder() > 0d) {
sb.append("Thunder strenth: ").append(NumberFormats.FORMATTER_ZERO_DECIMAL_PLACES.format(wf.getThunder() * 100d)).append("%\n");
}
sb.append("Rain: ").append(NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(wf.getRain())).append(" mm\n");
if(wf.getSnow() > 0d) {
sb.append("Snow: ").append(NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(wf.getSnow())).append(" mm\n");
}
sb.append("Humidity: ").append((int)(wf.getHumidity() * 100d * 0.6)).append(" %\n");
if(wf.getHeatOrColdWave() < 0.5d) {
sb.append("Cold Wave: ").append(NumberFormats.FORMATTER_ZERO_DECIMAL_PLACES.format(100d - (wf.getHeatOrColdWave() * 2 * 100d))).append(" %\n");
} else {
sb.append("Heat Wave: ").append(NumberFormats.FORMATTER_ZERO_DECIMAL_PLACES.format((wf.getHeatOrColdWave() - 0.5d) * 2 * 100d)).append(" %\n");
}
WeatherForecast f1 = forecasts.get(forecasts.indexOf(wf) + 1);
WeatherForecast f2 = forecasts.get(forecasts.indexOf(wf) + 2);
WeatherForecast f3 = forecasts.get(forecasts.indexOf(wf) + 3);
WeatherForecast f4 = forecasts.get(forecasts.indexOf(wf) + 4);
WeatherForecast f5 = forecasts.get(forecasts.indexOf(wf) + 5);
WeatherForecast f6 = forecasts.get(forecasts.indexOf(wf) + 6);
sb.append("Tomorrow: ").append(NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(f1.getMaximumCelsius())).append(" °C\n");
sb.append("Day after tomorrow: ").append(NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(f2.getMaximumCelsius())).append(" °C\n");
sb.append(" 2 days after tomorrow: ").append(NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(f3.getMaximumCelsius())).append(" °C\n");
sb.append(" 3 days after tomorrow: ").append(NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(f4.getMaximumCelsius())).append(" °C\n");
sb.append(" 4 days after tomorrow: ").append(NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(f5.getMaximumCelsius())).append(" °C\n");
sb.append(" 5 days after tomorrow: ").append(NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(f6.getMaximumCelsius())).append(" °C\n");
Utils.showNotification(sb.toString(), 30000, 400);
}
String[] array = wf.asPrettyString(add > 0 ? -1 : new TTime(time.hourProperty.getValue(),
time.minuteProperty.getValue(),
time.secondProperty.getValue(),
time.millisecondProperty.getValue()).toTotalMilliseconds() / 1000d / 60d / 60d).split(WeatherForecast.DOUBLE_COLON);
List<String> list = null;
for (String a : array) {
if (a.length() >= 14) {
list = new ArrayList<>();
break;
}
}
if (list != null) {
for (String a : array) {
if (a.length() >= 14) {
list.add(a.substring(0, 14));
list.add(a.substring(14, a.length()));
} else {
list.add(a);
}
}
array = new String[list.size()];
for (int i = 0; i < list.size(); i++) {
array[i] = list.get(i);
}
}
int rowHeight = 12;
int row = 0;
brush.drawString(DateFormats.DATE_TIME_FORMATTER_YYYYMMDD.format(cal.getTime()), 0, SwingUtils.MARGIN + row);
row = row + 12;
brush.drawString(DateFormats.DATE_TIME_FORMATTER_DAY_OF_WEEK.format(cal.getTime()), 0, SwingUtils.MARGIN + row);
row = row + rowHeight + 10;
brush.drawString(array[0], 0, SwingUtils.MARGIN + row);
row = row + rowHeight;
brush.drawString(array.length < 2 ? "" : array[1], 0, SwingUtils.MARGIN + row);
row = row + rowHeight;
brush.drawString(array.length < 3 ? "" : array[2], 0, SwingUtils.MARGIN + row);
row = row + rowHeight;
if (array.length >= 4) {
brush.drawString(array[3], 0, SwingUtils.MARGIN + row);
row = row + rowHeight;
}
if (array.length >= 5) {
brush.drawString(array[4], 0, SwingUtils.MARGIN + row);
row = row + rowHeight;
}
this.setToolTipText(wf.toString());
}
//private boolean w = false;
@Override
public Property getVisibilityProperty() {
return visibilityProperty;
}
@Override
public Property getVisibilitySupportedColoredProperty() {
return visibilitySupportedColoredProperty;
}
@Override
public List<JMenuItem> createAdditionalMenus() {
if (this.menuItems == null) {
menuItems = new ArrayList<>();
JMenuItem pauseResume = new JMenuItem("Pause/Resume");
pauseResume.addActionListener(e -> paused = !paused);
menuItems.add(pauseResume);
JMenuItem now = new JMenuItem("Now");
now.addActionListener(e -> {
lastAdd = 0;
paused = true;
});
menuItems.add(now);
JMenuItem info = new JMenuItem("Info");
info.addActionListener(e -> {
information = true;
});
menuItems.add(info);
}
return this.menuItems;
}
private boolean paused = false;
}

View File

@ -0,0 +1,555 @@
package org.nanoboot.utils.timecalc.swing.progress.weather;
import lombok.Getter;
import lombok.Setter;
import org.nanoboot.utils.timecalc.utils.common.FileConstants;
import org.nanoboot.utils.timecalc.utils.common.NumberFormats;
import java.io.FileInputStream;
import java.io.IOException;
import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import lombok.ToString;
import org.nanoboot.utils.timecalc.utils.common.DateFormats;
/**
* @author pc00289
* @since 22.03.2024
*/
@Getter
@Setter
@ToString
public class WeatherForecast {
//01:00-4:00 - minimum
//13:00-16:00 - maximum
//20240101.minTempC=
//20240101.maxTempC=
// 20240101.minTempTime=
//20240101.maxTempTime=
//20240101.wind={m/s}
//20240101.cloudiness={0.0 - 1.0}
//20240101.thunder={0.0 - 1.0}
//20240101.rain={mm}
//20240101.snow={mm}
//#20240101.sunrise=7:53
//#20240101.sunset=16:02
public static final String DOUBLE_COLON = "::";
private String date;
private double minimumCelsius;
private double maximumCelsius;
private double minimumCelsiusTime;
private double maximumCelsiusTime;
private double wind;
private double cloudiness;
private double thunder;
private double rain;
private double snow;
private double humidity;
private double heatOrColdWave;
private double startCelsius;
private double endCelsius;
public static List<WeatherForecast> createForecast(int year) {
List<WeatherForecast> list = new ArrayList<>();
Properties climateProperties = new Properties();
if (FileConstants.CLIMATE_TXT.exists()) {
try {
climateProperties.load(new FileInputStream(FileConstants.CLIMATE_TXT));
} catch (IOException e) {
e.printStackTrace();
System.out.println("Loading file failed: " + FileConstants.WEATHER_CSV + " " + e.getMessage());
//return list;
}
} else {
System.out.println("File does not exist: " + FileConstants.CLIMATE_TXT);
//return list;
}
double min1 = Double.valueOf(climateProperties.getProperty("1.min", "-20")) + 10;
double min2 = Double.valueOf(climateProperties.getProperty("2.min", "-16")) + 10;
double min3 = Double.valueOf(climateProperties.getProperty("3.min", "-12")) + 10;
double min4 = Double.valueOf(climateProperties.getProperty("4.min", "-8")) + 10;
double min5 = Double.valueOf(climateProperties.getProperty("5.min", "-4")) + 10;
double min6 = Double.valueOf(climateProperties.getProperty("6.min", "-2")) + 10;
double min7 = Double.valueOf(climateProperties.getProperty("7.min", "0")) + 10;
double min8 = Double.valueOf(climateProperties.getProperty("8.min", "0")) + 10;
double min9 = Double.valueOf(climateProperties.getProperty("9.min", "-2")) + 10;
double min10 = Double.valueOf(climateProperties.getProperty("10.min", "-4")) + 10;
double min11 = Double.valueOf(climateProperties.getProperty("11.min", "-8")) + 10;
double min12 = Double.valueOf(climateProperties.getProperty("12.min", "-16")) + 10;
double max1 = Double.valueOf(climateProperties.getProperty("1.max", "20"));
double max2 = Double.valueOf(climateProperties.getProperty("2.max", "15"));
double max3 = Double.valueOf(climateProperties.getProperty("3.max", "20"));
double max4 = Double.valueOf(climateProperties.getProperty("4.max", "25"));
double max5 = Double.valueOf(climateProperties.getProperty("5.max", "30"));
double max6 = Double.valueOf(climateProperties.getProperty("6.max", "35"));
double max7 = Double.valueOf(climateProperties.getProperty("7.max", "40"));
double max8 = Double.valueOf(climateProperties.getProperty("8.max", "40"));
double max9 = Double.valueOf(climateProperties.getProperty("9.max", "35"));
double max10 = Double.valueOf(climateProperties.getProperty("10.max", "30"));
double max11 = Double.valueOf(climateProperties.getProperty("11.max", "25"));
double max12 = Double.valueOf(climateProperties.getProperty("12.max", "20"));
Map<Integer, Map<Integer, Double>> minExpected = new HashMap<>();
Map<Integer, Map<Integer, Double>> maxExpected = new HashMap<>();
Calendar cal_ = Calendar.getInstance();
cal_.set(Calendar.YEAR, 2021);
cal_.set(Calendar.MONTH, 0);
cal_.set(Calendar.DAY_OF_MONTH, 1);
while (cal_.get(Calendar.YEAR) == 2021) {
int month = cal_.get(Calendar.MONTH) + 1;
int dayOfMonth = cal_.get(Calendar.DAY_OF_MONTH);
double min = 0d;
double max = 0d;
double minStart = 0d;
double minEnd = 0d;
double maxStart = 0d;
double maxEnd = 0d;
double transition = 0d;
LocalDate today = LocalDate.of(2021, Month.of(month), dayOfMonth);
LocalDate startDay = null;
LocalDate endDay = null;
if ((month == 12 && dayOfMonth >= 16) || (month == 1 && dayOfMonth <= 15)) {
minStart = min12;
minEnd = min1;
maxStart = max12;
maxEnd = max1;
startDay = LocalDate.of(2020, Month.DECEMBER, 16);
endDay = LocalDate.of(2021, Month.JANUARY, 15);
}
if ((month == 1 && dayOfMonth >= 16) || (month == 2 && dayOfMonth <= 14)) {
minStart = min1;
minEnd = min2;
maxStart = max1;
maxEnd = max2;
startDay = LocalDate.of(2021, Month.of(1), 16);
endDay = LocalDate.of(2021, Month.of(2), 14);
}
if ((month == 2 && dayOfMonth >= 15) || (month == 3 && dayOfMonth <= 15)) {
minStart = min2;
minEnd = min3;
maxStart = max2;
maxEnd = max3;
startDay = LocalDate.of(2021, Month.of(2), 15);
endDay = LocalDate.of(2021, Month.of(3), 16);
}
if ((month == 3 && dayOfMonth >= 16) || (month == 4 && dayOfMonth <= 15)) {
minStart = min3;
minEnd = min4;
maxStart = max3;
maxEnd = max4;
startDay = LocalDate.of(2021, Month.of(3), 16);
endDay = LocalDate.of(2021, Month.of(4), 15);
}
if ((month == 4 && dayOfMonth >= 16) || (month == 5 && dayOfMonth <= 15)) {
minStart = min4;
minEnd = min5;
maxStart = max4;
maxEnd = max5;
startDay = LocalDate.of(2021, Month.of(4), 16);
endDay = LocalDate.of(2021, Month.of(5), 15);
}
if ((month == 5 && dayOfMonth >= 16) || (month == 6 && dayOfMonth <= 15)) {
minStart = min5;
minEnd = min6;
maxStart = max5;
maxEnd = max6;
startDay = LocalDate.of(2021, Month.of(5), 16);
endDay = LocalDate.of(2021, Month.of(6), 15);
}
if ((month == 6 && dayOfMonth >= 16) || (month == 7 && dayOfMonth <= 15)) {
minStart = min6;
minEnd = min7;
maxStart = max6;
maxEnd = max7;
startDay = LocalDate.of(2021, Month.of(6), 16);
endDay = LocalDate.of(2021, Month.of(7), 15);
}
if ((month == 7 && dayOfMonth >= 16) || (month == 8 && dayOfMonth <= 15)) {
minStart = min7;
minEnd = min8;
maxStart = max7;
maxEnd = max8;
startDay = LocalDate.of(2021, Month.of(7), 16);
endDay = LocalDate.of(2021, Month.of(8), 15);
}
if ((month == 8 && dayOfMonth >= 16) || (month == 9 && dayOfMonth <= 15)) {
minStart = min8;
minEnd = min9;
maxStart = max8;
maxEnd = max9;
startDay = LocalDate.of(2021, Month.of(8), 16);
endDay = LocalDate.of(2021, Month.of(9), 15);
}
if ((month == 9 && dayOfMonth >= 16) || (month == 10 && dayOfMonth <= 15)) {
minStart = min9;
minEnd = min10;
maxStart = max9;
maxEnd = max10;
startDay = LocalDate.of(2021, Month.of(9), 16);
endDay = LocalDate.of(2021, Month.of(10), 15);
}
if ((month == 10 && dayOfMonth >= 16) || (month == 11 && dayOfMonth <= 15)) {
minStart = min10;
minEnd = min11;
maxStart = max10;
maxEnd = max11;
startDay = LocalDate.of(2021, Month.of(10), 16);
endDay = LocalDate.of(2021, Month.of(11), 15);
}
if ((month == 11 && dayOfMonth >= 16) || (month == 12 && dayOfMonth <= 15)) {
minStart = min11;
minEnd = min12;
maxStart = max11;
maxEnd = max12;
startDay = LocalDate.of(2021, Month.of(11), 16);
endDay = LocalDate.of(2021, Month.of(12), 15);
}
double daysBetween = ChronoUnit.DAYS.between(startDay, endDay) + 1;
double daysDone = ChronoUnit.DAYS.between(startDay, today) + 1;
if (daysDone > 365) {
daysDone = daysDone - 365;
}
transition = daysDone / daysBetween;
if (!minExpected.containsKey(month)) {
minExpected.put(month, new HashMap<Integer, Double>());
}
if (!maxExpected.containsKey(month)) {
maxExpected.put(month, new HashMap<Integer, Double>());
}
double minDiff = Math.abs(minEnd - minStart);
double maxDiff = Math.abs(maxEnd - maxStart);
double minAdd = (minDiff * transition * (minStart < maxEnd ? 1 : (-1)));
double maxAdd = (maxDiff * transition * (maxStart < maxEnd ? 1 : (-1)));
min = minStart + minAdd;
max = maxStart + maxAdd;
// System.out.print("\n" + month + "-" + dayOfMonth + ": ");
// System.out.print(" minStart= " + NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(minStart));
// System.out.print(" minEnd= " + NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(minEnd));
// System.out.print(" maxStart= " + NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(maxStart));
// System.out.print(" maxEnd= " + NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(maxEnd));
// System.out.println(" min and max: " + NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(min) + " " + NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(max));
// System.out.println(" min and max diff: " + NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(minDiff) + " " + NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(maxDiff));
// System.out.println("transition=" + transition);
// System.out.println("daysDone=" + daysDone + " daysBetween=" + daysBetween);
// System.out.println("startDay=" + startDay.toString());
// System.out.println("endDay=" + endDay.toString());
minExpected.get(month).put(dayOfMonth, min);
maxExpected.get(month).put(dayOfMonth, max);
cal_.add(Calendar.DAY_OF_MONTH, 1);
}
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, 0);
cal.set(Calendar.DAY_OF_MONTH, 1);
double humidity = Math.random() * 0.6;
double heatOrColdWave = Math.random();
int tooMuchHumidityDays = 0;
int tooMuchHeatDays = 0;
int tooMuchColdDays = 0;
double windiness = Math.random();
List<Double> maxCLastWeekAverage = new ArrayList<Double>();
List<Double> minCLastWeekAverage = new ArrayList<Double>();
double endCelsius = Double.MIN_VALUE;
while (cal.get(Calendar.YEAR) == year) {
if (humidity > 0.7) {
++tooMuchHumidityDays;
}
if (heatOrColdWave > 0.8) {
++tooMuchHeatDays;
}
if (heatOrColdWave < 0.3) {
++tooMuchColdDays;
}
if (tooMuchHumidityDays > 5) {
if (Math.random() > 0.5) {
humidity = Math.random() * 0.15;
}
}
if (tooMuchHeatDays > 5) {
if (Math.random() > 0.5) {
heatOrColdWave = Math.random() * 0.1;
}
}
if (tooMuchColdDays > 5) {
if (Math.random() > 0.5) {
heatOrColdWave = Math.random() * 0.9;
}
}
if (Math.random() > 0.75) {
humidity = humidity + Math.random() * 0.3 * (Math.random() > 0.9 ? (-1) : 1);
if (humidity > 1.0) {
humidity = 1.0;
}
if (humidity < 0.0) {
humidity = 0.0;
}
}
if (Math.random() > 0.95) {
humidity = 0.9 + Math.random() * 0.1;
}
if (Math.random() > 0.75) {
heatOrColdWave = heatOrColdWave + Math.random() * 0.1 * (Math.random() > 0.9 ? (-1) : 1);
if (heatOrColdWave > 1.0) {
heatOrColdWave = 1.0;
}
if (heatOrColdWave < 0.0) {
heatOrColdWave = 0.0;
}
if (heatOrColdWave > 0.85 && Math.random() > 0.25) {
heatOrColdWave = 0.85;
}
if (heatOrColdWave < 0.15 && Math.random() > 0.25) {
heatOrColdWave = 0.15;
}
}
int month = cal.get(Calendar.MONTH) + 1;
int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
WeatherForecast forecast = new WeatherForecast();
list.add(forecast);
forecast.setDate(DateFormats.DATE_TIME_FORMATTER_YYYYMMDD.format(cal.getTime()));
forecast.setMaximumCelsius(maxExpected.get(month).get((month == 2 && dayOfMonth == 29) ? 28 : dayOfMonth));
forecast.setMinimumCelsius(minExpected.get(month).get((month == 2 && dayOfMonth == 29) ? 28 : dayOfMonth));
double maxE = forecast.getMaximumCelsius();
double minE = forecast.getMinimumCelsius();
double maxExpectedCelsius = forecast.getMaximumCelsius();
double minExpectedCelsius = forecast.getMinimumCelsius();
if (Math.random() > 0.4) {
if (minE < -10) {
minE = minE + 10 + 10 * Math.random();
}
if (maxE > 40) {
maxE = maxE - 10 - 10 * Math.random();
}
}
if (minE < -10 && Math.random() > 0.5) {
heatOrColdWave = 0.7 + Math.random() * 0.2;
}
if (maxE > 38 && Math.random() > 0.5) {
heatOrColdWave = 0.1 + Math.random() * 0.1;
}
if (maxExpectedCelsius - 10 > maxCLastWeekAverage.stream().mapToDouble(e -> Double.valueOf(e)).average().orElse(maxExpectedCelsius - 10)) {
heatOrColdWave = heatOrColdWave + ((1.0d - heatOrColdWave) / 2d);
} else {
heatOrColdWave = heatOrColdWave / 2d;
}
if (minExpectedCelsius + 10 > minCLastWeekAverage.stream().mapToDouble(e -> Double.valueOf(e)).average().orElse(minExpectedCelsius + 10)) {
heatOrColdWave = heatOrColdWave + ((1.0d - heatOrColdWave) / 2d);
} else {
heatOrColdWave = heatOrColdWave / 2d;
}
double mediumHalf = minE + Math.abs(maxE - minE) / 2;
forecast.setMaximumCelsius(mediumHalf + heatOrColdWave * 1.1 * mediumHalf);
forecast.setMinimumCelsius(minE + heatOrColdWave * 1.5 * mediumHalf);
windiness = Math.random();
if (Math.random() > 0.9 && windiness < 0.15) {
windiness = 0d;
}
forecast.setWind(windiness * (Math.random() > 0.95 ? 40 : Math.random() * 150));
forecast.setCloudiness(Math.random() > 0.3 ? humidity : Math.random());
if (forecast.getMaximumCelsius() > 25 && Math.random() > 0.9) {
forecast.setThunder(Math.random());
}
if (humidity > 0.2) {
if (forecast.getMinimumCelsius() > 3) {
forecast.setRain(humidity * Math.random() * 50 * (Math.random() > 0.90 ? Math.random() * 10 : 1));
}
if (forecast.getMinimumCelsius() < 0) {
forecast.setSnow(humidity * Math.random() * 50 * (Math.random() > 0.90 ? Math.random() * 10 : 1));
}
if (forecast.getMinimumCelsius() > 0 && forecast.getMinimumCelsius() < 3) {
if (Math.random() > 0.5) {
forecast.setRain(humidity * Math.random() * 50 * (Math.random() > 0.90 ? Math.random() * 10 : 1));
} else {
forecast.setSnow(humidity * Math.random() * 50 * (Math.random() > 0.90 ? Math.random() * 10 : 1));
}
}
}
forecast.setHumidity(humidity);
forecast.setHeatOrColdWave(heatOrColdWave);
forecast.setMaximumCelsiusTime(12.0 + Math.random() * 5);
forecast.setMinimumCelsiusTime(02.0 + Math.random() * 4);
maxCLastWeekAverage.add(forecast.getMaximumCelsius());
minCLastWeekAverage.add(forecast.getMinimumCelsius());
while (maxCLastWeekAverage.size() > 7) {
maxCLastWeekAverage.remove(0);
}
while (minCLastWeekAverage.size() > 7) {
minCLastWeekAverage.remove(0);
}
if(endCelsius == Double.MIN_VALUE) {
forecast.setStartCelsius(forecast.getMinimumCelsius() + Math.random() * 8);
} else {
forecast.setStartCelsius(endCelsius);
}
forecast.setEndCelsius(forecast.getMinimumCelsius() + Math.random() * 5);
endCelsius = forecast.getEndCelsius();
// private String date;
// private double minimumCelsius;
// private double maximumCelsius;
// private double minimumCelsiusTime;
// private double maximumCelsiusTime;
// private double wind;
// private double cloudiness;
// private double thunder;
// private double rain;
// private double snow;
cal.add(Calendar.DAY_OF_MONTH, 1);
}
return list;
}
public String toCsv() {
StringBuilder sb = new StringBuilder();
sb.append(date).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(minimumCelsius)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(maximumCelsius)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(minimumCelsiusTime)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(maximumCelsiusTime)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(wind)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(cloudiness)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(thunder)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(rain)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(snow)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(humidity)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(heatOrColdWave)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(startCelsius)).append('\t');
sb.append(NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(endCelsius));
return sb.toString();
}
public WeatherForecast fromCsv(String csv) {
String[] values = csv.split("\t");
int i = 0;
date = values[i++];
minimumCelsius = Double.valueOf(values[i++]);
maximumCelsius = Double.valueOf(values[i++]);
minimumCelsiusTime = Double.valueOf(values[i++]);
maximumCelsiusTime = Double.valueOf(values[i++]);
wind = Double.valueOf(values[i++]);
cloudiness = Double.valueOf(values[i++]);
thunder = Double.valueOf(values[i++]);
rain = Double.valueOf(values[i++]);
snow = Double.valueOf(values[i++]);
humidity = Double.valueOf(values[i++]);
heatOrColdWave = Double.valueOf(values[i++]);
startCelsius = Double.valueOf(values[i++]);
endCelsius = Double.valueOf(values[i++]);
return this;
}
public String asPrettyString() {
return asPrettyString(-1);
}
public String asPrettyString(double forHour) {
StringBuilder sb = new StringBuilder();
sb.append(NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(maximumCelsius)).append("°C/").append(NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(minimumCelsius)).append("°C").append(DOUBLE_COLON);
if (forHour >= 0d) {
double value = getCelsiusForHour(forHour);
sb.append("Now: " + NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(value)).append("°C").append(DOUBLE_COLON);
}
//
sb
.append((int) Math.floor(this.wind))
.append("m/s");
if (snow == 0d) {
sb
.append("🌧")
.append(NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(rain))
.append("mm").append(DOUBLE_COLON);
} else {
sb
.append("")
.append(NumberFormats.FORMATTER_ONE_DECIMAL_PLACE.format(snow))
.append("mm").append(DOUBLE_COLON);
}
sb
.append(Cloudiness.forValue(cloudiness).getDescription().toLowerCase())
.append(DOUBLE_COLON);
return sb.toString();
// return "14°C::wind 7/s::rain 2mm::cloudy";
}
public Double getCelsiusForHour(double forHour) {
if(forHour > 24) {
throw new UnsupportedOperationException("Hour must less than 24: " + NumberFormats.FORMATTER_FIVE_DECIMAL_PLACES.format(forHour));
}
double minTime = this.minimumCelsiusTime;
double maxTime = this.maximumCelsiusTime;
if (maxTime < minTime) {
minTime = 4d;
maxTime = 14d;
}
double endTime = 24d;
double value = 0d;
if (forHour < minTime) {
return this.startCelsius - ((this.startCelsius - this.minimumCelsius) * forHour / minTime);
}
if (forHour >= minTime && forHour <= maxTime) {
return minimumCelsius + ((forHour - minTime) / (maxTime - minTime)) * (maximumCelsius - minimumCelsius);
}
if (forHour > maxTime) {
return maximumCelsius - (((forHour - maxTime) / (endTime - maxTime)) * (maximumCelsius - this.endCelsius));
}
throw new IllegalStateException();
}
}
/*
climate.txt
1.max=18.8
2.max=22.0
3.max=26.2
4.max=31.8
5.max=35.0
6.max=38.9
7.max=40.2
8.max=40.4
9.max=37.4
10.max=30.3
11.max=24.0
12.max=19.8
1.min=-36.2
2.min=-42.2
3.min=-32.0
4.min=-22.0
5.min=-13.1
6.min=-8.3
7.min=-6.9
8.min=-5.0
9.min=-10.5
10.min=-19.9
11.min=-25.4
12.min=-34.0
*/

View File

@ -37,7 +37,7 @@ import org.nanoboot.utils.timecalc.swing.progress.ProgressLife;
import org.nanoboot.utils.timecalc.swing.progress.ProgressMoney;
import org.nanoboot.utils.timecalc.swing.progress.ProgressSquare;
import org.nanoboot.utils.timecalc.swing.progress.ProgressSwing;
import org.nanoboot.utils.timecalc.swing.progress.ProgressWeather;
import org.nanoboot.utils.timecalc.swing.progress.weather.ProgressWeather;
import org.nanoboot.utils.timecalc.swing.progress.Time;
import org.nanoboot.utils.timecalc.swing.progress.WalkingHumanProgress;
import org.nanoboot.utils.timecalc.swing.progress.WeekBattery;

View File

@ -18,7 +18,7 @@ public class FileConstants {
public static final File JOKES_TXT = new File(TC_DIRECTORY, "time-calc-jokes.txt");
public static final File DB_FILE = new File(FileConstants.TC_DIRECTORY.getAbsolutePath() + "/" + "time-calc.sqlite3");
public static final File CLIMATE_TXT = new File(TC_DIRECTORY, "climate.txt");
public static final File WEATHER_TXT = new File(TC_DIRECTORY, "weather.txt");
public static final File WEATHER_CSV = new File(TC_DIRECTORY, "weather.csv");
private FileConstants() {
//Not meant to be instantiated.
}

View File

@ -11,6 +11,8 @@ public class NumberFormats {
public static final NumberFormat FORMATTER_ZERO_DECIMAL_PLACES
= new DecimalFormat("#00");
public static final NumberFormat FORMATTER_ONE_DECIMAL_PLACE
= new DecimalFormat("#0.0");
public static final NumberFormat FORMATTER_TWO_DECIMAL_PLACES
= new DecimalFormat("#0.00");
public static final NumberFormat FORMATTER_FIVE_DECIMAL_PLACES

View File

@ -225,6 +225,7 @@ public class Utils {
if (height != 0) {
toaster.setToasterHeight(height);
}
toaster.setToasterWidth(400);
toaster.showToaster(message);
}