:3333
This commit is contained in:
parent
1926ef4a92
commit
bedf45b831
|
@ -1,55 +1,8 @@
|
||||||
|
#include <util/macros.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
// -------------
|
|
||||||
// -- General --
|
|
||||||
// -------------
|
|
||||||
DEFINE_GETTER(General, const std::string, Name)
|
|
||||||
|
|
||||||
General::General(std::string name) : m_Name(std::move(name)) {}
|
|
||||||
|
|
||||||
fn GeneralImpl::from_class(const General& instance) noexcept -> GeneralImpl {
|
|
||||||
return { instance.getName() };
|
|
||||||
}
|
|
||||||
|
|
||||||
fn GeneralImpl::to_class() const -> General { return General { name }; }
|
|
||||||
// -------------
|
|
||||||
|
|
||||||
// ----------------
|
|
||||||
// -- NowPlaying --
|
|
||||||
// ----------------
|
|
||||||
DEFINE_GETTER(NowPlaying, bool, Enabled)
|
|
||||||
|
|
||||||
NowPlaying::NowPlaying(bool enabled) : m_Enabled(enabled) {}
|
|
||||||
|
|
||||||
fn NowPlayingImpl::from_class(const NowPlaying& instance) noexcept -> NowPlayingImpl {
|
|
||||||
return { .enabled = instance.getEnabled() };
|
|
||||||
}
|
|
||||||
|
|
||||||
fn NowPlayingImpl::to_class() const -> NowPlaying { return NowPlaying { enabled.value_or(false) }; }
|
|
||||||
// ----------------
|
|
||||||
|
|
||||||
// ------------
|
|
||||||
// -- Config --
|
|
||||||
// ------------
|
|
||||||
DEFINE_GETTER(Config, const General, General)
|
|
||||||
DEFINE_GETTER(Config, const NowPlaying, NowPlaying)
|
|
||||||
DEFINE_GETTER(Config, const Weather, Weather)
|
|
||||||
|
|
||||||
Config::Config(General general, NowPlaying now_playing, Weather weather)
|
|
||||||
: m_General(std::move(general)), m_NowPlaying(now_playing), m_Weather(std::move(weather)) {}
|
|
||||||
|
|
||||||
fn Config::getInstance() -> const Config& {
|
fn Config::getInstance() -> const Config& {
|
||||||
static const auto* INSTANCE = new Config(rfl::toml::load<Config>("./config.toml").value());
|
static const Config* INSTANCE = new Config(rfl::toml::load<Config>("./config.toml").value());
|
||||||
return *INSTANCE;
|
return *INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ConfigImpl::from_class(const Config& instance) noexcept -> ConfigImpl {
|
|
||||||
return {
|
|
||||||
instance.getGeneral(),
|
|
||||||
instance.getNowPlaying(),
|
|
||||||
instance.getWeather(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ConfigImpl::to_class() const -> Config { return { general, now_playing, weather }; }
|
|
||||||
// ------------
|
|
||||||
|
|
|
@ -1,76 +1,36 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
#include <rfl.hpp>
|
#include <rfl.hpp>
|
||||||
|
#include <rfl/Field.hpp>
|
||||||
|
#include <rfl/default.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <util/macros.h>
|
||||||
|
|
||||||
#include "util/macros.h"
|
|
||||||
#include "weather.h"
|
#include "weather.h"
|
||||||
|
|
||||||
// TODO: Make config values optional and supply defaults
|
using Location = std::variant<std::string, Coords>;
|
||||||
|
|
||||||
class General {
|
struct General {
|
||||||
private:
|
rfl::Field<"name", std::string> name = "user";
|
||||||
std::string m_Name;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit General(std::string name);
|
|
||||||
|
|
||||||
[[nodiscard]] fn getName() const -> const std::string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class NowPlaying {
|
struct NowPlaying {
|
||||||
private:
|
bool enabled = false;
|
||||||
bool m_Enabled;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit NowPlaying(bool enabled);
|
|
||||||
|
|
||||||
[[nodiscard]] fn getEnabled() const -> bool;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Config {
|
struct Weather {
|
||||||
private:
|
Location location;
|
||||||
General m_General;
|
std::string api_key;
|
||||||
NowPlaying m_NowPlaying;
|
std::string units;
|
||||||
Weather m_Weather;
|
|
||||||
|
|
||||||
public:
|
fn getWeatherInfo() const -> WeatherOutput;
|
||||||
/**
|
};
|
||||||
* @brief Creates a new Config instance.
|
|
||||||
*
|
struct Config {
|
||||||
* @param general The general section of the configuration.
|
rfl::Field<"general", General> general = General { .name = "user" };
|
||||||
* @param now_playing The now playing section of the configuration.
|
rfl::Field<"now_playing", NowPlaying> now_playing = NowPlaying();
|
||||||
* @param weather The weather section of the configuration.
|
rfl::Field<"weather", Weather> weather = Weather();
|
||||||
*/
|
|
||||||
Config(General general, NowPlaying now_playing, Weather weather);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Gets the current (read-only) configuration.
|
|
||||||
*
|
|
||||||
* @return The current Config instance.
|
|
||||||
*/
|
|
||||||
static fn getInstance() -> const Config&;
|
static fn getInstance() -> const Config&;
|
||||||
|
|
||||||
[[nodiscard]] fn getWeather() const -> const Weather;
|
|
||||||
[[nodiscard]] fn getGeneral() const -> const General;
|
|
||||||
[[nodiscard]] fn getNowPlaying() const -> const NowPlaying;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// reflect-cpp Stuff
|
|
||||||
DEF_IMPL(General, std::string name)
|
|
||||||
DEF_IMPL(NowPlaying, std::optional<bool> enabled)
|
|
||||||
DEF_IMPL(Config, General general; NowPlaying now_playing; Weather weather)
|
|
||||||
|
|
||||||
namespace rfl::parsing {
|
|
||||||
template <class ReaderType, class WriterType, class ProcessorsType>
|
|
||||||
struct Parser<ReaderType, WriterType, General, ProcessorsType>
|
|
||||||
: CustomParser<ReaderType, WriterType, ProcessorsType, General, GeneralImpl> {};
|
|
||||||
|
|
||||||
template <class ReaderType, class WriterType, class ProcessorsType>
|
|
||||||
struct Parser<ReaderType, WriterType, NowPlaying, ProcessorsType>
|
|
||||||
: CustomParser<ReaderType, WriterType, ProcessorsType, NowPlaying, NowPlayingImpl> {};
|
|
||||||
|
|
||||||
template <class ReaderType, class WriterType, class ProcessorsType>
|
|
||||||
struct Parser<ReaderType, WriterType, Config, ProcessorsType>
|
|
||||||
: CustomParser<ReaderType, WriterType, ProcessorsType, Config, ConfigImpl> {};
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,27 +5,9 @@
|
||||||
|
|
||||||
#include "weather.h"
|
#include "weather.h"
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
#include "util/result.h"
|
#include "util/result.h"
|
||||||
|
|
||||||
using WeatherOutput = Weather::WeatherOutput;
|
|
||||||
|
|
||||||
DEFINE_GETTER(Weather, const Weather::Location, Location)
|
|
||||||
DEFINE_GETTER(Weather, const std::string, ApiKey)
|
|
||||||
DEFINE_GETTER(Weather, const std::string, Units)
|
|
||||||
|
|
||||||
Weather::Weather(Location location, std::string api_key, std::string units)
|
|
||||||
: m_Location(std::move(location)), m_ApiKey(std::move(api_key)), m_Units(std::move(units)) {}
|
|
||||||
|
|
||||||
fn WeatherImpl::from_class(const Weather& weather) noexcept -> WeatherImpl {
|
|
||||||
return {
|
|
||||||
weather.getLocation(),
|
|
||||||
weather.getApiKey(),
|
|
||||||
weather.getUnits(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn WeatherImpl::to_class() const -> Weather { return { location, api_key, units }; }
|
|
||||||
|
|
||||||
// Function to read cache from file
|
// Function to read cache from file
|
||||||
fn ReadCacheFromFile() -> Result<WeatherOutput> {
|
fn ReadCacheFromFile() -> Result<WeatherOutput> {
|
||||||
std::ifstream ifs("/tmp/weather_cache.json");
|
std::ifstream ifs("/tmp/weather_cache.json");
|
||||||
|
@ -91,6 +73,7 @@ fn MakeApiRequest(const std::string& url) -> Result<WeatherOutput> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt::println("Received response from API. Response size: {}", responseBuffer.size());
|
fmt::println("Received response from API. Response size: {}", responseBuffer.size());
|
||||||
|
fmt::println("Response: {}", responseBuffer);
|
||||||
|
|
||||||
WeatherOutput output = rfl::json::read<WeatherOutput>(responseBuffer).value();
|
WeatherOutput output = rfl::json::read<WeatherOutput>(responseBuffer).value();
|
||||||
|
|
||||||
|
@ -104,10 +87,6 @@ fn MakeApiRequest(const std::string& url) -> Result<WeatherOutput> {
|
||||||
fn Weather::getWeatherInfo() const -> WeatherOutput {
|
fn Weather::getWeatherInfo() const -> WeatherOutput {
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
|
||||||
const Location loc = m_Location;
|
|
||||||
const std::string apiKey = m_ApiKey;
|
|
||||||
const std::string units = m_Units;
|
|
||||||
|
|
||||||
// Check if cache is valid
|
// Check if cache is valid
|
||||||
if (Result<WeatherOutput> data = ReadCacheFromFile(); data.isOk()) {
|
if (Result<WeatherOutput> data = ReadCacheFromFile(); data.isOk()) {
|
||||||
WeatherOutput dataVal = data.value();
|
WeatherOutput dataVal = data.value();
|
||||||
|
@ -126,24 +105,24 @@ fn Weather::getWeatherInfo() const -> WeatherOutput {
|
||||||
|
|
||||||
WeatherOutput result;
|
WeatherOutput result;
|
||||||
|
|
||||||
if (holds_alternative<std::string>(loc)) {
|
if (holds_alternative<std::string>(location)) {
|
||||||
const std::string city = get<std::string>(loc);
|
const std::string city = get<std::string>(location);
|
||||||
|
|
||||||
const char* location = curl_easy_escape(nullptr, city.c_str(), static_cast<int>(city.length()));
|
const char* loc = curl_easy_escape(nullptr, city.c_str(), static_cast<int>(city.length()));
|
||||||
|
|
||||||
fmt::println("City: {}", location);
|
fmt::println("City: {}", loc);
|
||||||
|
|
||||||
const std::string apiUrl = fmt::format(
|
const std::string apiUrl = fmt::format(
|
||||||
"https://api.openweathermap.org/data/2.5/"
|
"https://api.openweathermap.org/data/2.5/"
|
||||||
"weather?q={}&appid={}&units={}",
|
"weather?q={}&appid={}&units={}",
|
||||||
location,
|
loc,
|
||||||
apiKey,
|
api_key,
|
||||||
units
|
units
|
||||||
);
|
);
|
||||||
|
|
||||||
result = MakeApiRequest(apiUrl).value();
|
result = MakeApiRequest(apiUrl).value();
|
||||||
} else {
|
} else {
|
||||||
const auto [lat, lon] = get<Coords>(loc);
|
const auto [lat, lon] = get<Coords>(location);
|
||||||
|
|
||||||
fmt::println("Coordinates: lat = {:.3f}, lon = {:.3f}", lat, lon);
|
fmt::println("Coordinates: lat = {:.3f}, lon = {:.3f}", lat, lon);
|
||||||
|
|
||||||
|
@ -152,7 +131,7 @@ fn Weather::getWeatherInfo() const -> WeatherOutput {
|
||||||
"weather?lat={:.3f}&lon={:.3f}&appid={}&units={}",
|
"weather?lat={:.3f}&lon={:.3f}&appid={}&units={}",
|
||||||
lat,
|
lat,
|
||||||
lon,
|
lon,
|
||||||
apiKey,
|
api_key,
|
||||||
units
|
units
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -4,99 +4,73 @@
|
||||||
#include <rfl.hpp>
|
#include <rfl.hpp>
|
||||||
#include <rfl/toml.hpp>
|
#include <rfl/toml.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
#include <util/macros.h>
|
||||||
|
|
||||||
#include "util/macros.h"
|
|
||||||
#include "util/numtypes.h"
|
#include "util/numtypes.h"
|
||||||
|
|
||||||
class Weather {
|
using degrees = rfl::Validator<u16, rfl::Minimum<0>, rfl::Maximum<360>>;
|
||||||
public:
|
using percentage = rfl::Validator<i8, rfl::Minimum<0>, rfl::Maximum<100>>;
|
||||||
using degrees = rfl::Validator<u16, rfl::Minimum<0>, rfl::Maximum<360>>;
|
|
||||||
using percentage = rfl::Validator<i8, rfl::Minimum<0>, rfl::Maximum<100>>;
|
|
||||||
|
|
||||||
struct Condition {
|
struct Condition {
|
||||||
std::string description;
|
std::string description;
|
||||||
std::string icon;
|
std::string icon;
|
||||||
std::string main;
|
std::string main;
|
||||||
usize id;
|
usize id;
|
||||||
};
|
|
||||||
|
|
||||||
struct Main {
|
|
||||||
f64 feels_like;
|
|
||||||
f64 temp;
|
|
||||||
f64 temp_max;
|
|
||||||
f64 temp_min;
|
|
||||||
isize pressure;
|
|
||||||
percentage humidity;
|
|
||||||
std::optional<isize> grnd_level;
|
|
||||||
std::optional<isize> sea_level;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Wind {
|
|
||||||
degrees deg;
|
|
||||||
f64 speed;
|
|
||||||
std::optional<f64> gust;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Precipitation {
|
|
||||||
rfl::Rename<"1h", f64> one_hour;
|
|
||||||
rfl::Rename<"3h", f64> three_hours;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Sys {
|
|
||||||
std::string country;
|
|
||||||
usize id;
|
|
||||||
usize sunrise;
|
|
||||||
usize sunset;
|
|
||||||
usize type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Clouds {
|
|
||||||
percentage all;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Coords {
|
|
||||||
double lat;
|
|
||||||
double lon;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WeatherOutput {
|
|
||||||
Clouds clouds;
|
|
||||||
isize timezone;
|
|
||||||
isize visibility;
|
|
||||||
Main main;
|
|
||||||
rfl::Rename<"coord", Coords> coords;
|
|
||||||
std::optional<Precipitation> rain;
|
|
||||||
std::optional<Precipitation> snow;
|
|
||||||
std::string base;
|
|
||||||
std::string name;
|
|
||||||
std::vector<Condition> weather;
|
|
||||||
Sys sys;
|
|
||||||
usize cod;
|
|
||||||
usize dt;
|
|
||||||
usize id;
|
|
||||||
Wind wind;
|
|
||||||
};
|
|
||||||
|
|
||||||
using Location = std::variant<std::string, Coords>;
|
|
||||||
|
|
||||||
Weather(Location location, std::string api_key, std::string units);
|
|
||||||
|
|
||||||
[[nodiscard]] fn getWeatherInfo() const -> WeatherOutput;
|
|
||||||
[[nodiscard]] fn getLocation() const -> const Location;
|
|
||||||
[[nodiscard]] fn getApiKey() const -> const std::string;
|
|
||||||
[[nodiscard]] fn getUnits() const -> const std::string;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Location m_Location;
|
|
||||||
std::string m_ApiKey;
|
|
||||||
std::string m_Units;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DEF_IMPL(Weather, Weather::Location location; std::string api_key; std::string units)
|
struct Main {
|
||||||
|
f64 feels_like;
|
||||||
|
f64 temp;
|
||||||
|
f64 temp_max;
|
||||||
|
f64 temp_min;
|
||||||
|
isize pressure;
|
||||||
|
percentage humidity;
|
||||||
|
std::optional<isize> grnd_level;
|
||||||
|
std::optional<isize> sea_level;
|
||||||
|
};
|
||||||
|
|
||||||
namespace rfl::parsing {
|
struct Wind {
|
||||||
template <class ReaderType, class WriterType, class ProcessorsType>
|
degrees deg;
|
||||||
struct Parser<ReaderType, WriterType, Weather, ProcessorsType>
|
f64 speed;
|
||||||
: CustomParser<ReaderType, WriterType, ProcessorsType, Weather, WeatherImpl> {};
|
std::optional<f64> gust;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
struct Precipitation {
|
||||||
|
rfl::Rename<"1h", f64> one_hour;
|
||||||
|
rfl::Rename<"3h", f64> three_hours;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Sys {
|
||||||
|
std::string country;
|
||||||
|
usize id;
|
||||||
|
usize sunrise;
|
||||||
|
usize sunset;
|
||||||
|
usize type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Clouds {
|
||||||
|
percentage all;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Coords {
|
||||||
|
double lat;
|
||||||
|
double lon;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WeatherOutput {
|
||||||
|
Clouds clouds;
|
||||||
|
isize timezone;
|
||||||
|
isize visibility;
|
||||||
|
Main main;
|
||||||
|
rfl::Rename<"coord", Coords> coords;
|
||||||
|
std::optional<Precipitation> rain;
|
||||||
|
std::optional<Precipitation> snow;
|
||||||
|
std::string base;
|
||||||
|
std::string name;
|
||||||
|
std::vector<Condition> weather;
|
||||||
|
Sys sys;
|
||||||
|
usize cod;
|
||||||
|
usize dt;
|
||||||
|
usize id;
|
||||||
|
Wind wind;
|
||||||
|
};
|
||||||
|
|
11
src/main.cpp
11
src/main.cpp
|
@ -48,16 +48,14 @@ fn GetDate() -> string {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> int {
|
fn main() -> int {
|
||||||
using WeatherOutput = Weather::WeatherOutput;
|
|
||||||
|
|
||||||
const Config& config = Config::getInstance();
|
const Config& config = Config::getInstance();
|
||||||
|
|
||||||
auto weatherFuture =
|
auto weatherFuture =
|
||||||
std::async(std::launch::async, [&config]() { return config.getWeather().getWeatherInfo(); });
|
std::async(std::launch::async, [&config]() { return config.weather.get().getWeatherInfo(); });
|
||||||
|
|
||||||
auto osVersionFuture = std::async(std::launch::async, GetOSVersion);
|
auto osVersionFuture = std::async(std::launch::async, GetOSVersion);
|
||||||
auto nowPlayingEnabledFuture =
|
auto nowPlayingEnabledFuture =
|
||||||
std::async(std::launch::async, [&config]() { return config.getNowPlaying().getEnabled(); });
|
std::async(std::launch::async, [&config]() { return config.now_playing.get().enabled; });
|
||||||
|
|
||||||
auto dateFuture = std::async(std::launch::async, GetDate);
|
auto dateFuture = std::async(std::launch::async, GetDate);
|
||||||
auto memInfoFuture = std::async(std::launch::async, GetMemInfo);
|
auto memInfoFuture = std::async(std::launch::async, GetMemInfo);
|
||||||
|
@ -66,8 +64,9 @@ fn main() -> int {
|
||||||
const long temp = std::lround(json.main.temp);
|
const long temp = std::lround(json.main.temp);
|
||||||
const std::string townName = json.name;
|
const std::string townName = json.name;
|
||||||
|
|
||||||
const char* version = osVersionFuture.get();
|
const char* version = osVersionFuture.get();
|
||||||
const std::string name = config.getGeneral().getName();
|
|
||||||
|
const std::string name = config.general.value().name.get();
|
||||||
const bool nowPlayingEnabled = nowPlayingEnabledFuture.get();
|
const bool nowPlayingEnabled = nowPlayingEnabledFuture.get();
|
||||||
|
|
||||||
fmt::println("Hello {}!", name);
|
fmt::println("Hello {}!", name);
|
||||||
|
|
Loading…
Reference in a new issue