getting more database stuff hooked up
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
<rml>
|
||||
|
||||
<head>
|
||||
<title>Critterfolio</title>
|
||||
<link type="text/rcss" href="styles/main.rcss" />
|
||||
@@ -7,7 +6,15 @@
|
||||
|
||||
<body data-model="app_data">
|
||||
<h1>{{page_title}}</h1>
|
||||
<p>Hello world!</p>
|
||||
|
||||
<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>
|
||||
@@ -31,4 +31,16 @@ class Critter {
|
||||
int father_id;
|
||||
std::string gender;
|
||||
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
104
src/database.hpp
Normal 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() {
|
||||
|
||||
}
|
||||
83
src/main.cpp
83
src/main.cpp
@@ -6,7 +6,6 @@
|
||||
#include <RmlUi/Lua/Interpreter.h>
|
||||
#include <RmlUi/Lua/Lua.h>
|
||||
#include <SQLiteCpp/Database.h>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <RmlUi/Core.h>
|
||||
#include <RmlUi_Backend.h>
|
||||
@@ -15,19 +14,28 @@
|
||||
#include <lua.h>
|
||||
#include <RmlUi/Debugger/Debugger.h>
|
||||
#include "critter.hpp"
|
||||
#include <ostream>
|
||||
#include <SQLiteCpp/SQLiteCpp.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "database.hpp"
|
||||
|
||||
static bool is_initalized = false;
|
||||
static bool is_running = false;
|
||||
static Rml::Context *ctx;
|
||||
static std::map<int, Critter> critters = {};
|
||||
static std::vector<CritterEntry> critter_list = {};
|
||||
|
||||
struct AppData {
|
||||
Rml::String page_title = "Main";
|
||||
} app_data;
|
||||
|
||||
void SyncMapToList() {
|
||||
critter_list.clear();
|
||||
for (const auto &[id, critter] : critters) {
|
||||
critter_list.push_back({id, critter});
|
||||
}
|
||||
}
|
||||
|
||||
void Shutdown() {
|
||||
Rml::Shutdown();
|
||||
Backend::Shutdown();
|
||||
@@ -40,10 +48,27 @@ bool SetupDataBinding(Rml::Context *context, Rml::DataModelHandle &model_handle)
|
||||
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);
|
||||
|
||||
model_handle = dmc.GetModelHandle();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -62,53 +87,17 @@ bool Initalize() {
|
||||
// TODO: Add more error handling for initalization
|
||||
|
||||
std::cout << "[INFO] Loading local DB...\n";
|
||||
try {
|
||||
SQLite::Database db = SQLite::Database("./assets/local.db", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
|
||||
|
||||
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;
|
||||
bool db_result = db_get_all_critters(critters);
|
||||
if (!db_result) {
|
||||
std::cout << "[ERROR] Local DB failed to initalize.\n";
|
||||
return false;
|
||||
}
|
||||
std::cout << "[INFO] Local DB initalized.\n";
|
||||
|
||||
SyncMapToList();
|
||||
|
||||
// ------- DB TESTING
|
||||
std::cout << "\n";
|
||||
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";
|
||||
// db_print_all_critters(critters);
|
||||
// ------- END DB TESTING
|
||||
|
||||
ctx = Rml::CreateContext("main", Rml::Vector2i(800, 600));
|
||||
@@ -120,7 +109,7 @@ bool Initalize() {
|
||||
|
||||
Rml::Debugger::Initialise(ctx);
|
||||
|
||||
// lua_State *L = Rml::Lua::Interpreter::GetLuaState();
|
||||
// lua_State *L = Rml::Lua::Interpreter::GetLuaState();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user