ProgressWeather was finished
This commit is contained in:
parent
7f035a931d
commit
604d2384cf
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
||||
*/
|
@ -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
|
||||
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
@ -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
|
||||
*/
|
@ -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;
|
||||
|
@ -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.
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -225,6 +225,7 @@ public class Utils {
|
||||
if (height != 0) {
|
||||
toaster.setToasterHeight(height);
|
||||
}
|
||||
toaster.setToasterWidth(400);
|
||||
toaster.showToaster(message);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user