grades can be digested

This commit is contained in:
2025-12-17 17:39:46 -06:00
parent a953f2d303
commit fc02524fc1
3 changed files with 52 additions and 7 deletions

View File

@@ -1,3 +1,4 @@
#include "nlohmann/json_fwd.hpp"
#include "skwyward-api-utils.hpp"
#include "spdlog/spdlog.h"
@@ -13,5 +14,8 @@ int main (int argc, char *argv[]) {
api_utils::ErrorResponse test_login = api_methods::get_auth_status(base_uri, test_username, test_password);
spdlog::info("Auth attempt response : {}", test_login.success);
api_utils::GradesResponse test_grades = api_methods::get_grades(base_uri, test_username, test_password);
spdlog::info("Grades: {}", nlohmann::json {test_grades}.dump());
return 0;
}

View File

@@ -1,4 +1,5 @@
#include "skwyward-api-utils.hpp"
#include "nlohmann/json_fwd.hpp"
#include <cpr/cpr.h>
#include <algorithm>
@@ -9,20 +10,50 @@ using nlohmann::json;
// ---------- Helpers ----------
static double parse_percent_score(const json& j) {
static double parse_percent_score(const nlohmann::json& j) {
// Case 1: real number already
if (j.is_number()) {
return j.get<double>();
}
// Case 2: string input
if (j.is_string()) {
std::string s = j.get<std::string>();
s.erase(std::remove(s.begin(), s.end(), '%'), s.end());
return std::stod(s);
// Trim whitespace
s.erase(0, s.find_first_not_of(" \t\n\r"));
s.erase(s.find_last_not_of(" \t\n\r") + 1);
// Empty or known non-values
if (s.empty() || s == "N/A" || s == "--") {
return std::numeric_limits<double>::quiet_NaN();
}
return 0.0;
// Remove trailing %
if (!s.empty() && s.back() == '%') {
s.pop_back();
}
// Fast numeric parse (no exceptions)
double value{};
auto [ptr, ec] = std::from_chars(
s.data(),
s.data() + s.size(),
value
);
if (ec == std::errc()) {
return value;
}
return std::numeric_limits<double>::quiet_NaN();
}
// Everything else (null, object, etc.)
return std::numeric_limits<double>::quiet_NaN();
}
// ---------- Login ----------
void to_json(json& j, const Login& r) {
@@ -149,7 +180,7 @@ api_utils::ErrorResponse get_auth_status(
std::string username,
std::string password
) {
api_utils::Login login{username, password};
api_utils::Login login = api_utils::Login{username, password};
cpr::Response r = cpr::Post(
cpr::Url{url + "/check-auth"},
@@ -160,6 +191,15 @@ api_utils::ErrorResponse get_auth_status(
return nlohmann::json::parse(r.text)
.get<api_utils::ErrorResponse>();
}
api_utils::GradesResponse get_grades(std::string url, std::string username, std::string password) {
api_utils::Login login = api_utils::Login{username, password};
cpr::Response r = cpr::Post(
cpr::Url{url + "/fetch-grades"},
cpr::Body{nlohmann::json(login).dump()},
cpr::Header{{"Content-Type", "application/json"}}
);
return nlohmann::json::parse(r.text).get<api_utils::GradesResponse>();
}
} // namespace api_methods

View File

@@ -31,7 +31,7 @@ struct StatusResponse {
struct AssignmentGrade {
std::string name;
std::string dueDate;
double score; // <-- parsed from "72.00%"
double score;
std::string attempts;
bool isMajorGrade;
};
@@ -80,5 +80,6 @@ namespace api_methods {
std::string username,
std::string password
);
api_utils::GradesResponse get_grades( std::string url, std::string username, std::string password);
}