Compare commits

...

9 Commits

7 changed files with 355 additions and 23 deletions

3
assets/README.md Normal file
View File

@ -0,0 +1,3 @@
# Assets
Images and other media for Buddy.

4
bin/README.md Normal file
View File

@ -0,0 +1,4 @@
# bin
Helper scripts forthose new to Flutter or for myself if I take a break and need
reminders. ;D

View File

@ -4,25 +4,36 @@ import '/var/config.dart';
import '/var/secrets.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
//import 'dart:convert';
// Generic method to hit a GET request and return the response.
Future<String> hitAPI(String url) async {
if (debug) debugPrint(url);
if (debug) debugPrint("DEBUG: URL is '$url'.");
http.Response response = await http.get(Uri.parse(url));
try {
http.Response response = await http.get(Uri.parse(url));
String data = "";
if (response.statusCode == 200) {
data = response.body;
var decodedData = jsonDecode(data);
if (debugVerbose) debugPrint(decodedData.toString());
data = decodedData.toString();
} else {
if (debug) debugPrint(response.statusCode.toString());
String data = "";
if (response.statusCode == 200) {
data = response.body;
//var decodedData = jsonDecode(data);
//data = decodedData.toString();
//data = jsonEncode(decodedData);
if (debugVerbose) {
debugPrint("DEBUG-VERBOSE: Response data: \n\n$data\n");
}
} else {
if (debug) {
debugPrint(
"DEBUG: Response failed with code '${response.statusCode.toString()}'",
);
}
}
return data;
} catch (e) {
return "Sorry! It seems we have an issue: '${e.toString()}'.";
}
return data;
}
// How to guide: https://openweathermap.org/current#zip
@ -38,8 +49,3 @@ Future<String> hitOpenWeatherZip(String zipCode, String? countryCode) async {
String data = await hitAPI(url);
return data;
}
// Convert the Future value into a usable value.
loadWeather() async {
return await hitOpenWeatherZip("47630", "US");
}

View File

@ -1 +1,177 @@
// Functions related to parsing JSON strings and objects.
import '/var/config.dart';
import 'package:flutter/material.dart';
import 'dart:math';
String formatOpenWeatherData(var data) {
String location = pullOpenWeatherCity(data),
temp = pullOpenWeatherTemp(data),
conditions = pullOpenWeatherConditions(data),
windSpeed = pullOpenWeatherWind(data),
humidity = pullOpenWeatherHumidity(data);
String windChill = getWindChill(temp, windSpeed),
heatIndex = getHeatIndex(temp, humidity),
windAnnoyance = getWindAnnoyance(temp, windSpeed),
feelsLike = getUniversalThermalClimateIndex();
String comfort = "";
String text =
"$location is $temp$tempUnits and $conditions"
" with a wind speed of $windSpeed$windUnits"
" and humidity of $humidity$humidityUnits."
" $windChill"
" $heatIndex"
" $windAnnoyance"
" $feelsLike"
" $comfort";
final String doubleSpace = " ", singleSpace = " ";
while (text.contains(doubleSpace)) {
text = text.replaceAll(doubleSpace, singleSpace);
}
return text;
}
String pullOpenWeatherCity(var data) {
String location = "${data['city']['name']} (${data['city']['country']})";
if (debug) {
debugPrint("DEBUG: location = '$location'");
}
return location;
}
String pullOpenWeatherTemp(var data) {
String temp = data['list'][0]['main']['temp'].toString();
if (debug) {
debugPrint("DEBUG: temp = '$temp'");
}
return temp;
}
String pullOpenWeatherConditions(var data) {
String conditions = data['list'][0]['weather'][0]['description'].toString();
if (debug) {
debugPrint("DEBUG: conditions = '$conditions'");
}
return conditions;
}
String pullOpenWeatherWind(var data) {
String wind = data['list'][0]['wind']['speed'].toString();
if (debug) {
debugPrint("DEBUG: wind = '$wind'");
}
return wind;
}
String pullOpenWeatherHumidity(var data) {
String humidity = data['list'][0]['main']['humidity'].toString();
if (debug) {
debugPrint("DEBUG: humidity = '$humidity'");
}
return humidity;
}
double calcWindChill(double temp, double windSpeed) {
// ## Wind Chill ##
// # Wind speed as noted in: https://answers.yahoo.com/question/index?qid=20091020183148AAHm3kB&guccounter=1
// # More official source: https://www.weather.gov/media/epz/wxcalc/windChill.pdf
double windChill =
35.74 +
(0.6215 * temp) -
(35.75 * pow(windSpeed, 0.16)) +
(0.4275 * temp * pow(windSpeed, 0.16));
if (debug) {
debugPrint("DEBUG: windChill = '$windChill'");
}
return windChill;
}
String getWindChill(String temp, String windSpeed) {
double temperature = double.parse(temp);
double wind = double.parse(windSpeed);
if ((temperature < 50 && wind > 5) || debug) {
double windChill = calcWindChill((temperature), (wind));
return "My guess is that's a wind chill of $windChill$tempUnits.";
}
return "";
}
double calcHeatIndex(double temp, double humidity) {
// ## Heat Index ##
// # Official formula: https://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml
double heatIndex =
-42.379 +
2.04901523 * temp +
10.14333127 * humidity -
0.22475541 * temp * humidity -
0.00683783 * temp * temp -
0.05481717 * humidity * humidity +
0.00122874 * temp * temp * humidity +
0.00085282 * temp * humidity * humidity -
0.00000199 * temp * temp * humidity * humidity;
if (humidity < 13 && temp >= 80 && temp <= 112) {
heatIndex -= ((13 - humidity) / 4) * sqrt((17 - (temp - 95.0).abs()) / 17);
}
if (humidity > 85 && temp >= 80 && temp <= 87) {
heatIndex += ((humidity - 85) / 10) * ((87 - temp) / 5);
}
if (heatIndex < 80) {
heatIndex =
0.5 * (temp + 61.0 + ((temp - 68.0) * 1.2) + (humidity * 0.094));
heatIndex = (heatIndex + temp) / 2;
}
if (debug) {
debugPrint("DEBUG: heatIndex = '$heatIndex'");
}
return heatIndex;
}
String getHeatIndex(String temp, String humidity) {
double temperature = double.parse(temp);
double humid = double.parse(humidity);
if (temperature > 80 || debug) {
double heatIndex = calcHeatIndex((temperature), (humid));
return "My guess is that's a heat index of $heatIndex$tempUnits.";
}
return "";
}
double calcWindAnnoyance(double temp, double windSpeed) {
double windAnnoyance = (temp / (windSpeed * (windSpeed * 0.05)));
if (debug) {
debugPrint("DEBUG: windAnnoyance = '$windAnnoyance'");
}
return windAnnoyance;
}
String getWindAnnoyance(String temp, String windSpeed) {
double temperature = double.parse(temp);
double wind = double.parse(windSpeed);
double windAnnoyance = calcWindAnnoyance(temperature, wind);
if (windAnnoyance < 3) {
return "Wind may be a bit much for the temperature.";
}
return "";
}
double calcUniversalThermalClimateIndex() {
return 0;
}
String getUniversalThermalClimateIndex() {
return "";
}

View File

@ -1,7 +1,10 @@
// Local
import '/var/secrets.dart';
import 'dart:convert';
//import '/var/secrets.dart';
import '/var/config.dart';
import 'helpers/http.dart';
import 'helpers/json.dart';
// Flutter / Dart
import 'package:flutter/material.dart';
@ -20,6 +23,12 @@ class MainApp extends StatefulWidget {
}
class _MainAppState extends State<MainApp> {
final _formKey = GlobalKey<FormState>();
String _zipcode = "";
String _city = "";
String _country = "";
String _latlong = "";
String weather = loadText;
bool keepLoading = false;
DateTime lastLoadTime = DateTime.now().subtract(
@ -39,6 +48,80 @@ class _MainAppState extends State<MainApp> {
@override
Widget build(BuildContext context) {
Widget form = Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
height: 20,
width: 100,
child: TextFormField(
initialValue: _zipcode,
validator: (value) {
return null;
},
onSaved: (value) {
_zipcode = value!;
},
),
),
SizedBox(
height: 20,
width: 100,
child: TextFormField(
initialValue: _city,
validator: (value) {
return null;
},
onSaved: (value) {
_city = value!;
},
),
),
SizedBox(
height: 20,
width: 100,
child: TextFormField(
initialValue: _country,
validator: (value) {
return null;
},
onSaved: (value) {
_country = value!;
},
),
),
],
),
SizedBox(
height: 20,
width: 300,
child: TextFormField(
initialValue: _latlong,
validator: (value) {
return null;
},
onSaved: (value) {
_latlong = value!;
},
),
),
TextButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
}
},
child: Text("Save"),
),
],
),
);
Widget weatherLayout = Column(
children: [Text(weather), CircularProgressIndicator()],
);
@ -68,16 +151,67 @@ class _MainAppState extends State<MainApp> {
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(children: [Text('Weather Today!'), weatherLayout]),
child: Column(
children: [
Text('Weather Today!'),
form,
Expanded(child: weatherLayout),
],
),
),
),
);
}
// Call the
// Convert the Future value into a usable value.
pullWeather({
String? country,
String? zip,
String? city,
String? lat,
String? long,
}) async {
country ??= "US";
if (lat != null && long != null) {
weather = "Lat / Long Not Yet Implemented";
} else if (zip != null) {
weather = await hitOpenWeatherZip(zip, country);
} else if (city != null) {
weather = "City Weather Not Yet Implemented";
} else {
weather = "Please enter a location.";
}
if (weather.toString().contains("Sorry!")) {
return weather;
}
if (weather != loadText) {
if (debug) {
debugPrint("DEBUG: Formatting text.");
}
var weatherObject = jsonDecode(weather);
String weatherString = formatOpenWeatherData(weatherObject);
weather = weatherString;
if (debug) {
debugPrint("DEBUG: Set to formatted weather string.");
}
} else {
if (debug) {
debugPrint("DEBUG: Skipping text formatting.");
}
}
}
// Call the API and put the desired information into the screen variable.
_refreshWeather() {
var lastReloadSeconds = DateTime.now().difference(lastLoadTime).inSeconds;
if (debug) debugPrint("DEBUG: Refresh was $lastReloadSeconds seconds ago.");
if (debug) {
debugPrint("DEBUG: Refresh was '$lastReloadSeconds' seconds ago.");
}
if (lastReloadSeconds < limitRefreshSeconds) {
debugPrint("DEBUG: Skipping reload.");
@ -86,8 +220,14 @@ class _MainAppState extends State<MainApp> {
return;
}
if (debug) {
debugPrint("DEBUG: Pulling weather...");
}
weather = loadText;
weather = loadWeather();
pullWeather(country: "US", zip: "47630");
lastLoadTime = DateTime.now();
if (debug) {
debugPrint("DEBUG: Weather pulled and date is set.");
}
}
}

3
notes/README.md Normal file
View File

@ -0,0 +1,3 @@
# Notes
Any calculations, tests, or general ideas for functionality within Buddy. :)

Binary file not shown.