before parsing grades

This commit is contained in:
2025-12-17 17:16:37 -06:00
parent 314cb65843
commit a953f2d303
10 changed files with 276 additions and 2 deletions

2
.gitignore vendored
View File

@@ -1 +1,3 @@
build/**
config.toml
.cache/**

3
.gitmodules vendored
View File

@@ -13,3 +13,6 @@
[submodule "external/tomlplusplus"]
path = external/tomlplusplus
url = https://github.com/marzer/tomlplusplus
[submodule "external/json"]
path = external/json
url = https://github.com/nlohmann/json

View File

@@ -13,7 +13,7 @@ endif()
# -----------------------------
# Project setup
# -----------------------------
project(mainframe LANGUAGES CXX)
project(skyward LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
@@ -27,6 +27,7 @@ add_subdirectory(external/spdlog)
add_subdirectory(external/cpr)
add_subdirectory(external/clickhouse-cpp)
add_subdirectory(external/tomlplusplus)
add_subdirectory(external/json)
# -----------------------------
# Executable
# -----------------------------
@@ -63,6 +64,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
cpr::cpr
clickhouse-cpp-lib
tomlplusplus::tomlplusplus
nlohmann_json::nlohmann_json
)
# -----------------------------

1
external/json vendored Submodule

Submodule external/json added at 9f35919110

17
src/main.cpp Normal file
View File

@@ -0,0 +1,17 @@
#include "skwyward-api-utils.hpp"
#include "spdlog/spdlog.h"
#include <string_view>
#include <toml++/toml.h>
int main (int argc, char *argv[]) {
auto config = toml::parse_file("config.toml");
std::string base_uri = config["host"].value_or("");
std::string test_username = config["test_username"].value_or("");
std::string test_password = config["test_password"].value_or("");
api_utils::StatusResponse health_check = api_methods::get_status(base_uri);
spdlog::info("Status response output: {}", health_check.status);
api_utils::ErrorResponse test_login = api_methods::get_auth_status(base_uri, test_username, test_password);
spdlog::info("Auth attempt response : {}", test_login.success);
return 0;
}

165
src/skwyward-api-utils.cpp Normal file
View File

@@ -0,0 +1,165 @@
#include "skwyward-api-utils.hpp"
#include <cpr/cpr.h>
#include <algorithm>
#include <nlohmann/json.hpp>
namespace api_utils {
using nlohmann::json;
// ---------- Helpers ----------
static double parse_percent_score(const json& j) {
if (j.is_number()) {
return j.get<double>();
}
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);
}
return 0.0;
}
// ---------- Login ----------
void to_json(json& j, const Login& r) {
j = json{
{"username", r.username},
{"password", r.password}
};
}
void from_json(const json& j, Login& r) {
j.at("username").get_to(r.username);
j.at("password").get_to(r.password);
}
// ---------- ErrorResponse ----------
void from_json(const json& j, ErrorResponse& r) {
j.at("success").get_to(r.success);
if (j.contains("error") && !j.at("error").is_null()) {
r.error = j.at("error").get<std::string>();
} else {
r.error.reset();
}
}
void to_json(json& j, const ErrorResponse& r) {
j = json{{"success", r.success}};
if (r.error) {
j["error"] = *r.error;
}
}
// ---------- StatusResponse ----------
void to_json(json& j, const StatusResponse& r) {
j = json{
{"status", r.status},
{"message", r.message}
};
}
void from_json(const json& j, StatusResponse& r) {
j.at("status").get_to(r.status);
j.at("message").get_to(r.message);
}
// ---------- AssignmentGrade ----------
void to_json(json& j, const AssignmentGrade& g) {
j = json{
{"name", g.name},
{"dueDate", g.dueDate},
{"score", g.score},
{"attempts", g.attempts},
{"isMajorGrade", g.isMajorGrade}
};
}
void from_json(const json& j, AssignmentGrade& g) {
j.at("name").get_to(g.name);
j.at("dueDate").get_to(g.dueDate);
g.score = parse_percent_score(j.at("score"));
j.at("attempts").get_to(g.attempts);
j.at("isMajorGrade").get_to(g.isMajorGrade);
}
// ---------- ClassGrades ----------
void to_json(json& j, const ClassGrades& c) {
j = json{
{"className", c.className},
{"teacher", c.teacher},
{"period", c.period},
{"category", c.category},
{"grades", c.grades}
};
}
void from_json(const json& j, ClassGrades& c) {
j.at("className").get_to(c.className);
j.at("teacher").get_to(c.teacher);
j.at("period").get_to(c.period);
j.at("category").get_to(c.category);
j.at("grades").get_to(c.grades);
}
// ---------- GradesResponse ----------
void to_json(json& j, const GradesResponse& r) {
j = json{
{"success", r.success},
{"totalClasses", r.totalClasses},
{"grades", r.grades}
};
}
void from_json(const json& j, GradesResponse& r) {
j.at("success").get_to(r.success);
j.at("totalClasses").get_to(r.totalClasses);
j.at("grades").get_to(r.grades);
}
} // namespace api_utils
// ================= API METHODS =================
namespace api_methods {
api_utils::StatusResponse get_status(std::string url) {
cpr::Response r = cpr::Get(
cpr::Url{url + "/health"}
);
return nlohmann::json::parse(r.text)
.get<api_utils::StatusResponse>();
}
api_utils::ErrorResponse get_auth_status(
std::string url,
std::string username,
std::string password
) {
api_utils::Login login{username, password};
cpr::Response r = cpr::Post(
cpr::Url{url + "/check-auth"},
cpr::Body{nlohmann::json(login).dump()},
cpr::Header{{"Content-Type", "application/json"}}
);
return nlohmann::json::parse(r.text)
.get<api_utils::ErrorResponse>();
}
} // namespace api_methods

View File

@@ -0,0 +1,84 @@
#pragma once
#include <optional>
#include <string>
#include <vector>
#include <nlohmann/json.hpp>
namespace api_utils {
// ---------- Auth ----------
struct Login {
std::string username;
std::string password;
};
// ---------- Simple responses ----------
struct ErrorResponse {
bool success{};
std::optional<std::string> error;
};
struct StatusResponse {
std::string status;
std::string message;
};
// ---------- Grades ----------
struct AssignmentGrade {
std::string name;
std::string dueDate;
double score; // <-- parsed from "72.00%"
std::string attempts;
bool isMajorGrade;
};
struct ClassGrades {
std::string className;
std::string teacher;
std::string period;
std::string category;
std::vector<AssignmentGrade> grades;
};
struct GradesResponse {
bool success;
int totalClasses;
std::vector<ClassGrades> grades;
};
// ---------- nlohmann::json hooks ----------
void to_json(nlohmann::json& j, const Login& r);
void from_json(const nlohmann::json& j, Login& r);
void to_json(nlohmann::json& j, const ErrorResponse& r);
void from_json(const nlohmann::json& j, ErrorResponse& r);
void to_json(nlohmann::json& j, const StatusResponse& r);
void from_json(const nlohmann::json& j, StatusResponse& r);
void to_json(nlohmann::json& j, const AssignmentGrade& g);
void from_json(const nlohmann::json& j, AssignmentGrade& g);
void to_json(nlohmann::json& j, const ClassGrades& c);
void from_json(const nlohmann::json& j, ClassGrades& c);
void to_json(nlohmann::json& j, const GradesResponse& r);
void from_json(const nlohmann::json& j, GradesResponse& r);
} // namespace api_utils
namespace api_methods {
api_utils::StatusResponse get_status(std::string url);
api_utils::ErrorResponse get_auth_status(
std::string url,
std::string username,
std::string password
);
}

0
src/types.cpp Normal file
View File

0
src/types.hpp Normal file
View File