getting more database stuff hooked up

This commit is contained in:
2026-08-05 22:38:13 -05:00
parent ac433870c2
commit 9e96151a42
4 changed files with 163 additions and 51 deletions

View File

@@ -1,5 +1,4 @@
<rml> <rml>
<head> <head>
<title>Critterfolio</title> <title>Critterfolio</title>
<link type="text/rcss" href="styles/main.rcss" /> <link type="text/rcss" href="styles/main.rcss" />
@@ -7,7 +6,15 @@
<body data-model="app_data"> <body data-model="app_data">
<h1>{{page_title}}</h1> <h1>{{page_title}}</h1>
<p>Hello world!</p>
</body>
<h2>Critter Roster</h2>
<div class="critter-list">
<div data-for="entry : critters" class="critter-card">
<h3>#{{entry.key}} - {{entry.value.name}}</h3>
<p><strong>Species:</strong> {{entry.value.species}}</p>
<p><strong>Gender:</strong> {{entry.value.gender}}</p>
<p><strong>Notes:</strong> {{entry.value.notes}}</p>
</div>
</div>
</body>
</rml> </rml>

View File

@@ -31,4 +31,16 @@ class Critter {
int father_id; int father_id;
std::string gender; std::string gender;
std::string species; std::string species;
Critter() = default;
Critter(int id, std::string name, std::string gender, int mother_id, int father_id, std::string notes, std::string species) :
id(id), name(std::move(name)), gender(std::move(gender)),
mother_id(mother_id), father_id(father_id),
notes(std::move(notes)), species(std::move(species)) {}
};
struct CritterEntry {
int key;
Critter value;
}; };

104
src/database.hpp Normal file
View File

@@ -0,0 +1,104 @@
#include "critter.hpp"
#include <SQLiteCpp/Database.h>
#include <iostream>
#include <map>
inline static bool db_get_all_critters(std::map<int, Critter> &critters) {
try {
SQLite::Database db("./assets/local.db", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
SQLite::Statement q(db, "SELECT * FROM critters");
critters.clear();
while (q.executeStep()) {
int id = q.getColumn(0);
critters.try_emplace(
id,
id,
q.getColumn(1).getText(),
q.getColumn(2).getText(),
q.getColumn(3).getInt(),
q.getColumn(4).getInt(),
q.getColumn(5).getText(),
q.getColumn(6).getText()
);
}
}
catch (const std::exception &e) {
std::cout << "[ERROR] DB exception: " << e.what() << std::endl;
return false;
}
return true;
}
inline static void db_print_all_critters(std::map<int, Critter> &critters) {
std::cout << "Current loaded critters:";
for (auto c : critters) {
std::cout << "\nCritter " << c.first << "\n";
std::cout << "ID: " << c.second.id << std::endl;
std::cout << "Name:" << c.second.name << std::endl;
std::cout << "Gender: " << c.second.gender << std::endl;
std::cout << "Mother ID: " << c.second.mother_id << std::endl;
std::cout << "Father ID: " << c.second.father_id << std::endl;
std::cout << "Notes: " << c.second.notes << std::endl;
std::cout << "Species: " << c.second.species << std::endl;
}
std::cout << "\n";
}
inline static bool validate_critter(const Critter &c, std::map<int, Critter> &all_critters, std::string &out_error) {
if (c.mother_id != 0 && c.father_id != 0 && c.mother_id == c.father_id) {
out_error = "Mother ID and Father ID cannot be the same.";
return false;
}
// Mother Validation
if (c.mother_id != 0) {
auto it = all_critters.find(c.mother_id);
if (it == all_critters.end()) {
out_error = "Mother ID " + std::to_string(c.mother_id) + " does not exist.";
return false;
}
const Critter& mother = it->second;
if (mother.gender != "F" && mother.gender != "Female") {
out_error = "Mother must have female gender ('F' or 'Female').";
return false;
}
if (mother.species != c.species) {
out_error = "Mother species ('" + mother.species + "') must match critter species ('" + c.species + "').";
return false;
}
}
// Father Validation
if (c.father_id != 0) {
auto it = all_critters.find(c.father_id);
if (it == all_critters.end()) {
out_error = "Father ID " + std::to_string(c.father_id) + " does not exist.";
return false;
}
const Critter& father = it->second;
if (father.gender != "M" && father.gender != "Male") {
out_error = "Father must have male gender ('M' or 'Male').";
return false;
}
if (father.species != c.species) {
out_error = "Father species ('" + father.species + "') must match critter species ('" + c.species + "').";
return false;
}
}
return true;
}
inline static bool db_try_add_critter() {
}

View File

@@ -6,7 +6,6 @@
#include <RmlUi/Lua/Interpreter.h> #include <RmlUi/Lua/Interpreter.h>
#include <RmlUi/Lua/Lua.h> #include <RmlUi/Lua/Lua.h>
#include <SQLiteCpp/Database.h> #include <SQLiteCpp/Database.h>
#include <exception>
#include <iostream> #include <iostream>
#include <RmlUi/Core.h> #include <RmlUi/Core.h>
#include <RmlUi_Backend.h> #include <RmlUi_Backend.h>
@@ -15,19 +14,28 @@
#include <lua.h> #include <lua.h>
#include <RmlUi/Debugger/Debugger.h> #include <RmlUi/Debugger/Debugger.h>
#include "critter.hpp" #include "critter.hpp"
#include <ostream>
#include <SQLiteCpp/SQLiteCpp.h> #include <SQLiteCpp/SQLiteCpp.h>
#include <map> #include <map>
#include <vector>
#include "database.hpp"
static bool is_initalized = false; static bool is_initalized = false;
static bool is_running = false; static bool is_running = false;
static Rml::Context *ctx; static Rml::Context *ctx;
static std::map<int, Critter> critters = {}; static std::map<int, Critter> critters = {};
static std::vector<CritterEntry> critter_list = {};
struct AppData { struct AppData {
Rml::String page_title = "Main"; Rml::String page_title = "Main";
} app_data; } app_data;
void SyncMapToList() {
critter_list.clear();
for (const auto &[id, critter] : critters) {
critter_list.push_back({id, critter});
}
}
void Shutdown() { void Shutdown() {
Rml::Shutdown(); Rml::Shutdown();
Backend::Shutdown(); Backend::Shutdown();
@@ -40,10 +48,27 @@ bool SetupDataBinding(Rml::Context *context, Rml::DataModelHandle &model_handle)
return false; return false;
} }
if (auto handle = dmc.RegisterStruct<Critter>()) {
handle.RegisterMember("id", &Critter::id);
handle.RegisterMember("name", &Critter::name);
handle.RegisterMember("gender", &Critter::gender);
handle.RegisterMember("species", &Critter::species);
handle.RegisterMember("notes", &Critter::notes);
handle.RegisterMember("mother_id", &Critter::mother_id);
handle.RegisterMember("father_id", &Critter::father_id);
}
if (auto handle = dmc.RegisterStruct<CritterEntry>()) {
handle.RegisterMember("key", &CritterEntry::key);
handle.RegisterMember("value", &CritterEntry::value);
}
dmc.RegisterArray<std::vector<CritterEntry>>();
dmc.Bind("critters", &critter_list);
dmc.Bind("page_title", &app_data.page_title); dmc.Bind("page_title", &app_data.page_title);
model_handle = dmc.GetModelHandle(); model_handle = dmc.GetModelHandle();
return true; return true;
} }
@@ -62,53 +87,17 @@ bool Initalize() {
// TODO: Add more error handling for initalization // TODO: Add more error handling for initalization
std::cout << "[INFO] Loading local DB...\n"; std::cout << "[INFO] Loading local DB...\n";
try { bool db_result = db_get_all_critters(critters);
SQLite::Database db = SQLite::Database("./assets/local.db", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE); if (!db_result) {
std::cout << "[ERROR] Local DB failed to initalize.\n";
SQLite::Statement q(db, "SELECT * FROM critters");
while(q.executeStep()) {
int id = q.getColumn(0);
std::string name = q.getColumn(1);
std::string gender = q.getColumn(2);
int mother_id = q.getColumn(3);
int father_id = q.getColumn(4);
std::string notes = q.getColumn(5);
std::string species = q.getColumn(6);
Critter c;
c.id = id;
c.name = name;
c.gender = gender;
c.mother_id = mother_id;
c.father_id = father_id;
c.notes = notes;
c.species = species;
critters[c.id] = c;
}
std::cout << "[INFO] Loaded " << critters.size() << " critters from local db.\n";
}
catch (std::exception &e){
std::cout << "[ERROR] DB exception: " << e.what() << std::endl;
return false; return false;
} }
std::cout << "[INFO] Local DB initalized.\n"; std::cout << "[INFO] Local DB initalized.\n";
SyncMapToList();
// ------- DB TESTING // ------- DB TESTING
std::cout << "\n"; // db_print_all_critters(critters);
for (auto c : critters) {
std::cout << "\nCritter " << c.first << "\n";
std::cout << "ID: " << c.second.id << std::endl;
std::cout << "Name:" << c.second.name << std::endl;
std::cout << "Gender: " << c.second.gender << std::endl;
std::cout << "Mother ID: " << c.second.mother_id << std::endl;
std::cout << "Father ID: " << c.second.father_id << std::endl;
std::cout << "Notes: " << c.second.notes << std::endl;
std::cout << "Species: " << c.second.species << std::endl;
}
std::cout << "\n";
// ------- END DB TESTING // ------- END DB TESTING
ctx = Rml::CreateContext("main", Rml::Vector2i(800, 600)); ctx = Rml::CreateContext("main", Rml::Vector2i(800, 600));
@@ -120,7 +109,7 @@ bool Initalize() {
Rml::Debugger::Initialise(ctx); Rml::Debugger::Initialise(ctx);
// lua_State *L = Rml::Lua::Interpreter::GetLuaState(); // lua_State *L = Rml::Lua::Interpreter::GetLuaState();
return true; return true;
} }