diff --git a/src/main/api/APIcaller.java b/src/main/api/APIcaller.java index 8974837..519e806 100644 --- a/src/main/api/APIcaller.java +++ b/src/main/api/APIcaller.java @@ -11,9 +11,9 @@ public abstract class APIcaller { - public static final String googleApiKey = "AIzaSyDQQdJfzFRriSqWDsik4B3gOfC09RUmIEY"; + public static final String googleApiKey = System.getenv("GOOGLE_API_KEY"); - public static final String darkSkyApiKey = "a44d0775e4a62974499471b90c274895"; + public static final String darkSkyApiKey = System.getenv("OPENWEATHER_API_KEY"); public String errorMessage; diff --git a/src/main/api/DarkSky.java b/src/main/api/DarkSky.java index 1363197..380fc2b 100644 --- a/src/main/api/DarkSky.java +++ b/src/main/api/DarkSky.java @@ -32,14 +32,14 @@ public DarkSky(Location location) { this.location = location; String units; if (User.getCurrentUser().isMetric()) { - units = "ca"; + units = "metric"; } else { - units = "us"; + units = "imperial"; } try { - setURL(new URL("https://api.darksky.net/forecast/" + darkSkyApiKey + "/" - + this.location.getLatitude() + "," + this.location.getLongitude() - + "?exclude=minutely,flags&units=" + units)); + setURL(new URL("https://api.openweathermap.org/data/3.0/onecall?lat=" + + this.location.getLatitude() + "&lon=" + this.location.getLongitude() + + "&exclude=minutely&units=" + units + "&appid=" + darkSkyApiKey)); } catch (MalformedURLException e) { e.printStackTrace(); } @@ -59,17 +59,17 @@ public void parse(String responseBody) throws ParseException { throw new ParseException(); } else { JSONObject obj = new JSONObject(responseBody); - currently = getConditions(obj.getJSONObject("currently")); + currently = getConditions(obj.getJSONObject("current")); - setHourly(obj.getJSONObject("hourly")); - setDaily(obj.getJSONObject("daily")); + setHourly(obj.getJSONArray("hourly")); + setDaily(obj.getJSONArray("daily")); if (obj.has("alerts")) { System.out.println("ALERT DETECTED"); JSONArray alerts = obj.getJSONArray("alerts"); JSONObject alert = alerts.getJSONObject(0); - Alert warning = new Alert(alert.getString("title"), alert.getInt("time"), - alert.getInt("expires"), alert.getString("description"), alert.getString("uri")); + Alert warning = new Alert(alert.getString("event"), alert.getInt("start"), + alert.getInt("end"), alert.getString("description")); this.location.setAlert(warning); } else { System.out.println("NO ALERTS"); @@ -78,17 +78,18 @@ public void parse(String responseBody) throws ParseException { } } - private void setDaily(JSONObject daily) { - JSONArray data = daily.getJSONArray("data"); + private void setDaily(JSONArray daily) { DateFormat dateFormat = new SimpleDateFormat("E dd"); - for (int i = 1; i < data.length(); i++) { - JSONObject day = data.getJSONObject(i); - dailyHigh.add(day.getDouble("temperatureHigh")); - dailyLow.add(day.getDouble("temperatureLow")); - dailyTimes.add(dateFormat.format(new Date((long)day.getInt("time") * 1000))); - dailyIcons.add(day.getString("icon")); - System.out.println(dateFormat.format(new Date((long)day.getInt("time") * 1000))); + for (int i = 1; i < daily.length(); i++) { + JSONObject day = daily.getJSONObject(i); + JSONObject temp = day.getJSONObject("temp"); + dailyHigh.add(temp.getDouble("max")); + dailyLow.add(temp.getDouble("min")); + dailyTimes.add(dateFormat.format(new Date((long)day.getInt("dt") * 1000))); + JSONObject weatherObj = day.getJSONArray("weather").getJSONObject(0); + dailyIcons.add(weatherObj.getString("icon")); + System.out.println(dateFormat.format(new Date((long)day.getInt("dt") * 1000))); } } @@ -108,16 +109,15 @@ public ArrayList getDailyIcons() { return dailyIcons; } - private void setHourly(JSONObject hourly) { - JSONArray data = hourly.getJSONArray("data"); + private void setHourly(JSONArray hourly) { DateFormat dateFormat = new SimpleDateFormat("HH"); - for (int i = 0; i < data.length(); i++) { - JSONObject hour = data.getJSONObject(i); - int hourInt = Integer.parseInt(dateFormat.format(new Date((long)hour.getInt("time") * 1000))); + for (int i = 0; i < hourly.length(); i++) { + JSONObject hour = hourly.getJSONObject(i); + int hourInt = Integer.parseInt(dateFormat.format(new Date((long)hour.getInt("dt") * 1000))); if (!hourlyTimes.contains(hourInt)) { - hourlyTemps.add(hour.getDouble("temperature")); - hourlyApparentTemps.add(hour.getDouble("apparentTemperature")); + hourlyTemps.add(hour.getDouble("temp")); + hourlyApparentTemps.add(hour.getDouble("feels_like")); hourlyTimes.add(hourInt); } } @@ -136,12 +136,27 @@ public ArrayList getHourlyTimes() { } private Conditions getConditions(JSONObject obj) { - return new Conditions(obj.getInt("time"), obj.getString("summary"), - obj.getString("icon"), obj.getDouble("precipIntensity"), - obj.getDouble("precipProbability"), obj.getDouble("temperature"), - obj.getDouble("apparentTemperature"), obj.getDouble("dewPoint"), - obj.getDouble("humidity"), obj.getDouble("pressure"), - obj.getDouble("windSpeed"), obj.getInt("windBearing")); + JSONObject weatherObj = obj.getJSONArray("weather").getJSONObject(0); + JSONObject rainObj = obj.optJSONObject("rain"); + double rain1h = 0.0; + + if (rainObj != null) { + rain1h = rainObj.optDouble("1h", 0.0); + } + + return new Conditions( + obj.getInt("dt"), + weatherObj.getString("description"), + weatherObj.getString("icon"), + rain1h, + obj.getDouble("uvi"), + obj.getDouble("temp"), + obj.getDouble("feels_like"), + obj.getDouble("dew_point"), + obj.getInt("humidity"), + obj.getInt("pressure"), + obj.getDouble("wind_speed"), + obj.getInt("wind_deg")); } public Conditions getCurrently() { diff --git a/src/main/api/Email.java b/src/main/api/Email.java index be10240..21e85dd 100644 --- a/src/main/api/Email.java +++ b/src/main/api/Email.java @@ -14,7 +14,7 @@ // Reference: based on video by Genuine Coder (https://www.youtube.com/watch?v=A7HAB5whD6I) public class Email { private static String appEmail = "ubcweatherapp@gmail.com"; - private static String appPassword = "javaiscool"; + private static String appPassword = System.getenv("APP_PASS"); public static void sendMail(User recipient, Location alertedLocation) throws Exception { System.out.println("Preparing to send email..."); @@ -53,8 +53,7 @@ private static Message generateMessage(Session session, String recipientEmail, L message.setText(alert.getTitle() + "\n" + "Time: " + alert.getTime() + "\n" + "Expires: " + alert.getExpires() + "\n\n" - + alert.getDescription() + "\n" - + "For more information: " + alert.getUri()); + + alert.getDescription() + "\n"); return message; } catch (Exception e) { Logger.getLogger(Email.class.getName()).log(Level.SEVERE, null, e); diff --git a/src/main/model/Alert.java b/src/main/model/Alert.java index 2a30616..ae9221f 100644 --- a/src/main/model/Alert.java +++ b/src/main/model/Alert.java @@ -9,17 +9,15 @@ public class Alert { private String time; private String expires; private String description; - private String uri; private Boolean notified; - public Alert(String title, int time, int expires, String description, String uri) { + public Alert(String title, int time, int expires, String description) { this.title = title; DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); this.time = dateFormat.format(new Date((long)time * 1000)); this.expires = dateFormat.format(new Date((long)expires * 1000)); this.description = description.replaceAll("\\*", "\n*"); - this.uri = uri; this.notified = false; } @@ -46,8 +44,4 @@ public String getExpires() { public String getDescription() { return description; } - - public String getUri() { - return uri; - } } diff --git a/src/main/model/Conditions.java b/src/main/model/Conditions.java index 36f679b..1a6d4f5 100644 --- a/src/main/model/Conditions.java +++ b/src/main/model/Conditions.java @@ -10,18 +10,18 @@ public class Conditions { private String summary; private String icon; private double precipIntensity; - private double precipProbability; + private double uvIndex; private double temperature; private double apparentTemperature; private double dewPoint; - private double humidity; - private double pressure; + private int humidity; + private int pressure; private double windSpeed; private double windBearing; - public Conditions(int time, String summary, String icon, double precipIntensity, double precipProbability, - double temperature, double apparentTemperature, double dewPoint, double humidity, - double pressure, double windSpeed, int windBearing) { + public Conditions(int time, String summary, String icon, double precipIntensity, double uvIndex, + double temperature, double apparentTemperature, double dewPoint, int humidity, + int pressure, double windSpeed, int windBearing) { this.timeUnix = time; DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @@ -30,7 +30,7 @@ public Conditions(int time, String summary, String icon, double precipIntensity, this.summary = summary; this.icon = icon; this.precipIntensity = precipIntensity; - this.precipProbability = precipProbability; + this.uvIndex = uvIndex; this.temperature = temperature; this.apparentTemperature = apparentTemperature; this.dewPoint = dewPoint; @@ -52,8 +52,8 @@ public double getPrecipIntensity() { return precipIntensity; } - public double getPrecipProbability() { - return precipProbability; + public double getUvIndex() { + return uvIndex; } public double getTemperature() { @@ -68,11 +68,11 @@ public double getDewPoint() { return dewPoint; } - public double getHumidity() { + public int getHumidity() { return humidity; } - public double getPressure() { + public int getPressure() { return pressure; } diff --git a/src/main/ui/controllers/DashboardController.java b/src/main/ui/controllers/DashboardController.java index e7a5c71..ed92aa6 100644 --- a/src/main/ui/controllers/DashboardController.java +++ b/src/main/ui/controllers/DashboardController.java @@ -13,9 +13,8 @@ import javafx.scene.control.TabPane; import javafx.scene.image.Image; import javafx.scene.image.ImageView; -import javafx.scene.layout.BorderPane; -import javafx.scene.layout.HBox; -import javafx.scene.layout.VBox; +import javafx.scene.layout.*; +import javafx.scene.paint.Color; import javafx.scene.text.Font; import model.Conditions; import model.Location; @@ -71,10 +70,10 @@ public void initialize() { if (User.getCurrentUser().isMetric()) { tempUnits = "°C"; precipUnits = "mm/hr"; - windUnits = "km/hr"; + windUnits = "kph"; } else { tempUnits = "°F"; - precipUnits = "in/hr"; + precipUnits = "mm/hr"; windUnits = "mph"; } } @@ -107,13 +106,22 @@ private void fillTab(String locationName) { private void openDarkSky() { try { Desktop desktop = java.awt.Desktop.getDesktop(); - URI url = new URI("https://darksky.net/poweredby/"); + URI url = new URI("https://openweathermap.org/api"); desktop.browse(url); } catch (Exception e) { e.printStackTrace(); } + } - + @FXML + private void openGithub() { + try { + Desktop desktop = java.awt.Desktop.getDesktop(); + URI url = new URI("https://github.com/yaseenmustapha"); + desktop.browse(url); + } catch (Exception e) { + e.printStackTrace(); + } } private void instantiateLayouts() { @@ -133,15 +141,21 @@ private void setDailyConditions() { VBox day = new VBox(10); day.setStyle("-fx-padding: 10;" + "-fx-border-style: solid inside;" + "-fx-border-width: 0.5;" + "-fx-border-insets: 5;" + "-fx-border-radius: 2;" + "-fx-border-color: grey;"); - ImageView dailyImage = new ImageView(new Image("ui/images/" + dailyIcons.get(i) + ".png", - 40, 40, false, false)); + + ImageView dailyImage = new ImageView(new Image("https://openweathermap.org/img/wn/" + dailyIcons.get(i) + "@2x.png")); + Pane imageContainer = new Pane(); + imageContainer.getChildren().add(dailyImage); + imageContainer.setBackground(new Background(new BackgroundFill(Color.DARKGRAY, null, null))); + imageContainer.setStyle("-fx-background-color: lightgray; -fx-background-radius: 10;"); + // ImageView dailyImage = new ImageView(new Image("ui/images/" + dailyIcons.get(i) + ".png", + // 40, 40, false, false)); Label timeLabel = new Label(dailyTimes.get(i)); timeLabel.setFont(Font.font("Segoe UI", 20)); Label highLabel = new Label(Math.round(dailyHigh.get(i)) + tempUnits); highLabel.setFont(Font.font("Segoe UI", 16)); Label lowLabel = new Label(Math.round(dailyLow.get(i)) + tempUnits); lowLabel.setFont(Font.font("Segoe UI", 16)); - day.getChildren().addAll(timeLabel, highLabel, lowLabel, dailyImage); + day.getChildren().addAll(timeLabel, highLabel, lowLabel, imageContainer); dailyConditions.getChildren().add(day); } @@ -155,6 +169,14 @@ private void setupDay() { dailyIcons = darkSky.getDailyIcons(); } + private static String capitalizeFirstCharacter(String input) { + if (input == null || input.isEmpty()) { + return input; + } + + return Character.toUpperCase(input.charAt(0)) + input.substring(1); + } + private void setCurrentConditions() { Label tempLabel = new Label(Math.round(current.getTemperature()) + tempUnits); tempLabel.setFont(Font.font("Segoe UI", 40)); @@ -165,12 +187,17 @@ private void setCurrentConditions() { temps.getChildren().addAll(tempLabel, apparentTempLabel); temps.setMaxHeight(10); - Label summaryLabel = new Label(current.getSummary()); + Label summaryLabel = new Label(capitalizeFirstCharacter(current.getSummary())); summaryLabel.setFont(Font.font("Segoe UI", 26)); - ImageView currentImage = new ImageView(new Image("ui/images/" + current.getIcon() + ".png")); + ImageView currentImage = new ImageView(new Image("https://openweathermap.org/img/wn/" + current.getIcon() + "@2x.png")); + Pane imageContainer = new Pane(); + imageContainer.getChildren().add(currentImage); + imageContainer.setBackground(new Background(new BackgroundFill(Color.DARKGRAY, null, null))); + imageContainer.setStyle("-fx-background-color: lightgray; -fx-background-radius: 10;"); + // ImageView currentImage = new ImageView(new Image("ui/images/" + current.getIcon() + ".png")); - currentConditions.getChildren().addAll(currentImage, temps, summaryLabel, details); + currentConditions.getChildren().addAll(imageContainer, temps, summaryLabel, details); currentConditions.setPadding(new Insets(10, 10, 0, 120)); currentConditions.setAlignment(Pos.CENTER_LEFT); } @@ -179,27 +206,27 @@ private void setDetailsLeft() { Label humidityLabel = new Label("Humidity: " + current.getHumidity() + "%"); humidityLabel.setFont(Font.font("Segoe UI", 16)); - Label precipLabel = new Label("Precip. Intensity: " + current.getPrecipIntensity() + " " + Label precipLabel = new Label("Precip. intensity: " + current.getPrecipIntensity() + " " + precipUnits); precipLabel.setFont(Font.font("Segoe UI", 16)); - Label precipProbabilityLabel = new Label("Precip. Probability: " + current.getPrecipProbability()); - precipProbabilityLabel.setFont(Font.font("Segoe UI", 16)); + Label uvLabel = new Label("UV index: " + current.getUvIndex()); + uvLabel.setFont(Font.font("Segoe UI", 16)); - detailsLeft.getChildren().addAll(humidityLabel, precipLabel, precipProbabilityLabel); + detailsLeft.getChildren().addAll(humidityLabel, precipLabel, uvLabel); detailsLeft.setPadding(new Insets(0, 0, 0, 50)); detailsLeft.setMaxHeight(10); } private void setDetailsRight() { - Label dewPointLabel = new Label("Dew Point: " + current.getDewPoint() + tempUnits); + Label dewPointLabel = new Label("Dew point: " + current.getDewPoint() + tempUnits); dewPointLabel.setFont(Font.font("Segoe UI", 16)); - Label windLabel = new Label("Wind Speed: " + current.getWindSpeed() + " " + windUnits + Label windLabel = new Label("Wind speed: " + current.getWindSpeed() + " " + windUnits + " at " + current.getWindBearing() + "°"); windLabel.setFont(Font.font("Segoe UI", 16)); - Label pressureLabel = new Label("Pressure: " + current.getPressure() + " Pa"); + Label pressureLabel = new Label("Pressure: " + current.getPressure() + " hPa"); pressureLabel.setFont(Font.font("Segoe UI", 16)); @@ -224,7 +251,7 @@ private void setGraph() { seriesTemp = new XYChart.Series(); seriesTemp.setName("Temperature"); seriesApparentTemp = new XYChart.Series(); - seriesApparentTemp.setName("Feels Like (if available)"); + seriesApparentTemp.setName("Feels like"); ArrayList hourlyTemps = darkSky.getHourlyTemps(); ArrayList hourlyApparentTemps = darkSky.getHourlyApparentTemps(); diff --git a/src/main/ui/fxml/Dashboard.fxml b/src/main/ui/fxml/Dashboard.fxml index 182cc2f..3eeeba8 100644 --- a/src/main/ui/fxml/Dashboard.fxml +++ b/src/main/ui/fxml/Dashboard.fxml @@ -23,11 +23,6 @@ - - - - - @@ -54,11 +49,16 @@ + -