2022-10-25 17:08:36 -03:00
|
|
|
#include "knowledge_base.h"
|
2022-11-29 00:06:35 -03:00
|
|
|
#include "models/error.h"
|
2022-10-25 17:08:36 -03:00
|
|
|
|
2022-11-29 00:06:35 -03:00
|
|
|
#include <cstring>
|
2022-11-01 01:04:41 -03:00
|
|
|
#include <filesystem>
|
2022-10-25 17:08:36 -03:00
|
|
|
#include <iostream>
|
2022-11-29 00:06:35 -03:00
|
|
|
#include <string>
|
2022-10-25 17:08:36 -03:00
|
|
|
|
|
|
|
obelisk::KnowledgeBase::KnowledgeBase(const char* filename, int flags)
|
|
|
|
{
|
|
|
|
filename_ = std::move(filename);
|
|
|
|
flags_ = std::move(flags);
|
|
|
|
|
2022-11-01 01:04:41 -03:00
|
|
|
std::filesystem::path path {filename};
|
|
|
|
auto dbExists = std::filesystem::exists(path);
|
|
|
|
|
2022-10-25 17:08:36 -03:00
|
|
|
auto result = sqlite3_open_v2(filename, &dbConnection_, flags, NULL);
|
|
|
|
if (result != SQLITE_OK)
|
|
|
|
{
|
2022-12-09 21:13:18 -03:00
|
|
|
throw new KnowledgeBaseException("database could not be opened");
|
2022-10-25 17:08:36 -03:00
|
|
|
}
|
|
|
|
|
2022-11-29 00:06:35 -03:00
|
|
|
enableForeignKeys();
|
|
|
|
|
2022-11-01 01:04:41 -03:00
|
|
|
if (!dbExists)
|
2022-10-25 17:08:36 -03:00
|
|
|
{
|
2022-11-01 01:04:41 -03:00
|
|
|
createTable(obelisk::Action::createTable);
|
|
|
|
createTable(obelisk::Entity::createTable);
|
|
|
|
createTable(obelisk::Verb::createTable);
|
|
|
|
createTable(obelisk::Fact::createTable);
|
|
|
|
createTable(obelisk::Rule::createTable);
|
|
|
|
createTable(obelisk::SuggestAction::createTable);
|
2022-10-25 17:08:36 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
obelisk::KnowledgeBase::~KnowledgeBase()
|
|
|
|
{
|
2022-11-03 15:36:08 -03:00
|
|
|
if (dbConnection_)
|
|
|
|
{
|
|
|
|
sqlite3_close_v2(dbConnection_);
|
|
|
|
}
|
2022-10-25 17:08:36 -03:00
|
|
|
}
|
|
|
|
|
2022-11-29 00:06:35 -03:00
|
|
|
void obelisk::KnowledgeBase::enableForeignKeys()
|
|
|
|
{
|
|
|
|
char* errmsg;
|
2023-02-20 22:05:57 -03:00
|
|
|
int result = sqlite3_exec(dbConnection_,
|
|
|
|
"PRAGMA foreign_keys = ON;",
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
&errmsg);
|
2022-11-29 00:06:35 -03:00
|
|
|
if (result != SQLITE_OK)
|
|
|
|
{
|
|
|
|
if (errmsg)
|
|
|
|
{
|
|
|
|
throw obelisk::KnowledgeBaseException(errmsg);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw obelisk::KnowledgeBaseException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-01 01:04:41 -03:00
|
|
|
void obelisk::KnowledgeBase::createTable(std::function<const char*()> function)
|
|
|
|
{
|
2022-11-29 00:06:35 -03:00
|
|
|
char* errmsg;
|
|
|
|
int result = sqlite3_exec(dbConnection_, function(), NULL, NULL, &errmsg);
|
2022-11-01 01:04:41 -03:00
|
|
|
if (result != SQLITE_OK)
|
|
|
|
{
|
2022-11-29 00:06:35 -03:00
|
|
|
if (errmsg)
|
2022-11-01 01:17:45 -03:00
|
|
|
{
|
|
|
|
throw obelisk::KnowledgeBaseException(errmsg);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw obelisk::KnowledgeBaseException();
|
|
|
|
}
|
2022-11-01 01:04:41 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-29 00:06:35 -03:00
|
|
|
void obelisk::KnowledgeBase::addEntities(std::vector<obelisk::Entity>& entities)
|
2022-11-26 00:32:06 -03:00
|
|
|
{
|
|
|
|
for (auto& entity : entities)
|
|
|
|
{
|
2022-11-29 00:06:35 -03:00
|
|
|
try
|
|
|
|
{
|
2023-02-16 00:40:43 -03:00
|
|
|
entity.insert(dbConnection_);
|
2022-11-29 00:06:35 -03:00
|
|
|
}
|
2022-12-10 21:11:39 -03:00
|
|
|
catch (obelisk::DatabaseConstraintException& exception)
|
2022-11-29 00:06:35 -03:00
|
|
|
{
|
|
|
|
// ignore unique constraint error
|
2023-02-20 22:05:57 -03:00
|
|
|
if (std::strcmp(exception.what(),
|
|
|
|
"UNIQUE constraint failed: entity.name")
|
|
|
|
!= 0)
|
2022-11-29 00:06:35 -03:00
|
|
|
{
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
2022-11-26 00:32:06 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-29 00:06:35 -03:00
|
|
|
void obelisk::KnowledgeBase::addVerbs(std::vector<obelisk::Verb>& verbs)
|
2022-11-26 00:32:06 -03:00
|
|
|
{
|
|
|
|
for (auto& verb : verbs)
|
|
|
|
{
|
2022-11-29 00:06:35 -03:00
|
|
|
try
|
|
|
|
{
|
2023-02-16 00:40:43 -03:00
|
|
|
verb.insert(dbConnection_);
|
2022-11-29 00:06:35 -03:00
|
|
|
}
|
2022-12-10 21:11:39 -03:00
|
|
|
catch (obelisk::DatabaseConstraintException& exception)
|
2022-11-29 00:06:35 -03:00
|
|
|
{
|
|
|
|
// ignore unique constraint error
|
2023-02-20 22:05:57 -03:00
|
|
|
if (std::strcmp(exception.what(),
|
|
|
|
"UNIQUE constraint failed: verb.name")
|
|
|
|
!= 0)
|
2022-11-29 00:06:35 -03:00
|
|
|
{
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
2022-11-26 00:32:06 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-18 21:06:42 -03:00
|
|
|
void obelisk::KnowledgeBase::addActions(std::vector<obelisk::Action>& actions)
|
|
|
|
{
|
|
|
|
for (auto& action : actions)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
action.insert(dbConnection_);
|
|
|
|
}
|
|
|
|
catch (obelisk::DatabaseConstraintException& exception)
|
|
|
|
{
|
|
|
|
// ignore unique constraint error
|
2023-02-20 22:05:57 -03:00
|
|
|
if (std::strcmp(exception.what(),
|
|
|
|
"UNIQUE constraint failed: action.name")
|
|
|
|
!= 0)
|
2023-02-18 21:06:42 -03:00
|
|
|
{
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-29 00:06:35 -03:00
|
|
|
void obelisk::KnowledgeBase::addFacts(std::vector<obelisk::Fact>& facts)
|
2022-11-26 00:32:06 -03:00
|
|
|
{
|
|
|
|
for (auto& fact : facts)
|
|
|
|
{
|
2022-11-29 00:06:35 -03:00
|
|
|
try
|
|
|
|
{
|
2023-02-16 00:40:43 -03:00
|
|
|
fact.insert(dbConnection_);
|
2022-11-29 00:06:35 -03:00
|
|
|
}
|
2022-12-10 21:11:39 -03:00
|
|
|
catch (obelisk::DatabaseConstraintException& exception)
|
2022-11-29 00:06:35 -03:00
|
|
|
{
|
|
|
|
// ignore unique constraint error
|
|
|
|
if (std::strcmp(exception.what(),
|
|
|
|
"UNIQUE constraint failed: fact.left_entity, fact.right_entity, fact.verb")
|
|
|
|
!= 0)
|
|
|
|
{
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
2022-11-26 00:32:06 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-20 22:05:57 -03:00
|
|
|
void obelisk::KnowledgeBase::addSuggestActions(
|
|
|
|
std::vector<obelisk::SuggestAction>& suggestActions)
|
2023-02-18 21:32:05 -03:00
|
|
|
{
|
|
|
|
for (auto& suggestAction : suggestActions)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
suggestAction.insert(dbConnection_);
|
|
|
|
}
|
|
|
|
catch (obelisk::DatabaseConstraintException& exception)
|
|
|
|
{
|
|
|
|
// ignore unique constraint error
|
|
|
|
if (std::strcmp(exception.what(),
|
|
|
|
"UNIQUE constraint failed: suggest_action.fact, suggest_action.true_action, suggest_action.false_action")
|
|
|
|
!= 0)
|
|
|
|
{
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-19 01:03:35 -03:00
|
|
|
void obelisk::KnowledgeBase::addRules(std::vector<obelisk::Rule>& rules)
|
|
|
|
{
|
|
|
|
for (auto& rule : rules)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
rule.insert(dbConnection_);
|
|
|
|
}
|
|
|
|
catch (obelisk::DatabaseConstraintException& exception)
|
|
|
|
{
|
|
|
|
// ignore unique constraint error
|
2023-02-20 22:05:57 -03:00
|
|
|
if (std::strcmp(exception.what(),
|
|
|
|
"UNIQUE constraint failed: rule.fact, rule.reason")
|
|
|
|
!= 0)
|
2023-02-19 01:03:35 -03:00
|
|
|
{
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-29 00:06:35 -03:00
|
|
|
void obelisk::KnowledgeBase::getEntity(obelisk::Entity& entity)
|
2022-11-27 23:58:40 -03:00
|
|
|
{
|
2023-02-16 00:44:32 -03:00
|
|
|
entity.selectByName(dbConnection_);
|
2022-11-27 23:58:40 -03:00
|
|
|
}
|
|
|
|
|
2022-11-29 00:06:35 -03:00
|
|
|
void obelisk::KnowledgeBase::getVerb(obelisk::Verb& verb)
|
2022-11-27 23:58:40 -03:00
|
|
|
{
|
2023-02-16 00:44:32 -03:00
|
|
|
verb.selectByName(dbConnection_);
|
2022-11-27 23:58:40 -03:00
|
|
|
}
|
|
|
|
|
2023-02-18 21:06:42 -03:00
|
|
|
void obelisk::KnowledgeBase::getAction(obelisk::Action& action)
|
|
|
|
{
|
|
|
|
action.selectByName(dbConnection_);
|
|
|
|
}
|
|
|
|
|
2022-11-29 00:06:35 -03:00
|
|
|
void obelisk::KnowledgeBase::getFact(obelisk::Fact& fact)
|
2022-11-27 23:58:40 -03:00
|
|
|
{
|
2023-02-18 21:06:42 -03:00
|
|
|
fact.selectById(dbConnection_);
|
2022-11-27 23:58:40 -03:00
|
|
|
}
|
|
|
|
|
2023-02-20 22:05:57 -03:00
|
|
|
void obelisk::KnowledgeBase::getSuggestAction(
|
|
|
|
obelisk::SuggestAction& suggestAction)
|
2023-02-18 21:32:05 -03:00
|
|
|
{
|
|
|
|
suggestAction.selectById(dbConnection_);
|
|
|
|
}
|
|
|
|
|
2023-02-19 01:03:35 -03:00
|
|
|
void obelisk::KnowledgeBase::getRule(obelisk::Rule& rule)
|
|
|
|
{
|
|
|
|
rule.selectById(dbConnection_);
|
|
|
|
}
|
|
|
|
|
2023-02-20 09:11:10 -03:00
|
|
|
void obelisk::KnowledgeBase::checkRule(obelisk::Fact& fact)
|
|
|
|
{
|
|
|
|
std::vector<obelisk::Rule> rules;
|
|
|
|
obelisk::Rule::selectByReason(dbConnection_, fact.getId(), rules);
|
|
|
|
for (auto& rule : rules)
|
|
|
|
{
|
|
|
|
auto reason = rule.getReason();
|
|
|
|
getFact(reason);
|
2023-02-22 00:42:40 -03:00
|
|
|
if (reason.getIsTrue() > 0)
|
2023-02-20 09:11:10 -03:00
|
|
|
{
|
|
|
|
auto updateFact = rule.getFact();
|
2023-02-22 00:42:40 -03:00
|
|
|
updateFact.setIsTrue(1.0);
|
2023-02-20 09:11:10 -03:00
|
|
|
updateFact.updateIsTrue(dbConnection_);
|
2023-03-05 23:04:17 -03:00
|
|
|
checkRule(updateFact);
|
2023-02-20 09:11:10 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void obelisk::KnowledgeBase::updateIsTrue(obelisk::Fact& fact)
|
|
|
|
{
|
|
|
|
fact.updateIsTrue(dbConnection_);
|
|
|
|
}
|
|
|
|
|
2023-02-22 00:42:40 -03:00
|
|
|
void obelisk::KnowledgeBase::queryFact(obelisk::Fact& fact)
|
|
|
|
{
|
|
|
|
fact.selectByName(dbConnection_);
|
|
|
|
}
|
|
|
|
|
2023-02-23 01:07:44 -03:00
|
|
|
void obelisk::KnowledgeBase::querySuggestAction(obelisk::Fact& fact,
|
|
|
|
obelisk::Action& action)
|
|
|
|
{
|
|
|
|
fact.selectActionByFact(dbConnection_, action);
|
|
|
|
}
|
|
|
|
|
2023-02-20 22:05:57 -03:00
|
|
|
void obelisk::KnowledgeBase::getFloat(float& result1,
|
|
|
|
float& result2,
|
|
|
|
double var)
|
2022-10-25 17:08:36 -03:00
|
|
|
{
|
2022-11-01 01:04:41 -03:00
|
|
|
result1 = (float) var;
|
|
|
|
result2 = (float) (var - (double) result1);
|
2022-10-25 17:08:36 -03:00
|
|
|
}
|
|
|
|
|
2022-11-01 01:04:41 -03:00
|
|
|
void obelisk::KnowledgeBase::getDouble(double& result, float var1, float var2)
|
2022-10-25 17:08:36 -03:00
|
|
|
{
|
2022-11-01 01:04:41 -03:00
|
|
|
result = (double) ((double) var2 + (double) var1);
|
2022-10-25 17:08:36 -03:00
|
|
|
}
|