diff --git a/src/lib/include/obelisk.h b/src/lib/include/obelisk.h index afa02ad..b078614 100644 --- a/src/lib/include/obelisk.h +++ b/src/lib/include/obelisk.h @@ -1,6 +1,9 @@ #ifndef OBELISK_INCLUDE_OBELISK_H #define OBELISK_INCLUDE_OBELISK_H +#include "knowledge_base.h" + +#include #include /** @@ -17,12 +20,15 @@ namespace obelisk */ class Obelisk { + private: + std::unique_ptr kb_; + public: /** * @brief Construct a new Obelisk object. * */ - Obelisk() = default; + Obelisk(std::string filename); /** * @brief Destroy the Obelisk object. @@ -45,14 +51,14 @@ namespace obelisk int getLibVersion(); /** - * @brief Query the Obelisk KnowledgeBase to see if the Fact is true + * @brief Query the obelisk KnowledgeBase to see if a Fact is true * or not. * - * @param[in] leftEntity The left entity. + * @param[in] p_obelisk The obelisk object pointer. + * @param[in] left_entity The left entity. * @param[in] verb The verb. - * @param[in] rightEntity The right entity. - * @return double Returns a value between 0 and 1 depending on - * whether it is true or false. + * @param[in] right_entity The right entity. + * @return double Returns whether or not the Fact is true. */ double query(const std::string& leftEntity, const std::string& verb, diff --git a/src/lib/include/obelisk_c.h b/src/lib/include/obelisk_c.h index 437d088..fa5ab83 100644 --- a/src/lib/include/obelisk_c.h +++ b/src/lib/include/obelisk_c.h @@ -15,9 +15,10 @@ extern "C" /** * @brief Create an obelisk object. * + * @param[in] filename The obelisk KnowledgeBase file to use. * @return CObelisk* Returns an obelisk object. */ - extern CObelisk* obelisk_open(); + extern CObelisk* obelisk_open(const char* filename); /** * @brief Delete an obelisk object. @@ -35,6 +36,20 @@ extern "C" */ extern char* obelisk_get_version(CObelisk* obelisk); + /** + * @brief Query the obelisk KnowledgeBase to see if a Fact is true or false. + * + * @param[in] obelisk The obelisk object. + * @param[in] left_entity The left entity. + * @param[in] verb The verb. + * @param[in] right_entity The right entity. + * @return double Returns whether the Fact is true or false. + */ + extern double obelisk_query(CObelisk* obelisk, + const char* left_entity, + const char* verb, + const char* right_entity); + /** * @brief Get the obelisk library so version. * diff --git a/src/lib/knowledge_base.cpp b/src/lib/knowledge_base.cpp index 52fa521..ec345df 100644 --- a/src/lib/knowledge_base.cpp +++ b/src/lib/knowledge_base.cpp @@ -245,10 +245,10 @@ void obelisk::KnowledgeBase::checkRule(obelisk::Fact& fact) { auto reason = rule.getReason(); getFact(reason); - if (reason.getIsTrue()) + if (reason.getIsTrue() > 0) { auto updateFact = rule.getFact(); - updateFact.setIsTrue(true); + updateFact.setIsTrue(1.0); updateFact.updateIsTrue(dbConnection_); } } @@ -259,6 +259,11 @@ void obelisk::KnowledgeBase::updateIsTrue(obelisk::Fact& fact) fact.updateIsTrue(dbConnection_); } +void obelisk::KnowledgeBase::queryFact(obelisk::Fact& fact) +{ + fact.selectByName(dbConnection_); +} + void obelisk::KnowledgeBase::getFloat(float& result1, float& result2, double var) diff --git a/src/lib/knowledge_base.h b/src/lib/knowledge_base.h index 4fe6b6a..24ae8bf 100644 --- a/src/lib/knowledge_base.h +++ b/src/lib/knowledge_base.h @@ -200,6 +200,8 @@ namespace obelisk */ void updateIsTrue(obelisk::Fact& fact); + void queryFact(obelisk::Fact& fact); + /** * @brief Take a float and divide it into 2 floats. * diff --git a/src/lib/models/fact.cpp b/src/lib/models/fact.cpp index ed6dad5..5bfc1ca 100644 --- a/src/lib/models/fact.cpp +++ b/src/lib/models/fact.cpp @@ -157,6 +157,125 @@ void obelisk::Fact::selectById(sqlite3* dbConnection) } } +void obelisk::Fact::selectByName(sqlite3* dbConnection) +{ + if (dbConnection == nullptr) + { + throw obelisk::DatabaseException("database isn't open"); + } + + sqlite3_stmt* ppStmt = nullptr; + + auto result = sqlite3_prepare_v2(dbConnection, + "SELECT fact.id, fact.left_entity, fact.right_entity, fact.verb, fact.is_true FROM fact LEFT JOIN entity le ON le.id = fact.left_entity LEFT JOIN entity re ON re.id = fact.right_entity LEFT JOIN verb v ON fact.verb = v.id WHERE (le.name=? AND v.name=? AND re.name=?)", + -1, + &ppStmt, + nullptr); + if (result != SQLITE_OK) + { + throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection)); + } + + result = sqlite3_bind_text(ppStmt, + 1, + getLeftEntity().getName().c_str(), + -1, + SQLITE_STATIC); + switch (result) + { + case SQLITE_OK : + break; + case SQLITE_TOOBIG : + throw obelisk::DatabaseSizeException(); + break; + case SQLITE_RANGE : + throw obelisk::DatabaseRangeException(); + break; + case SQLITE_NOMEM : + throw obelisk::DatabaseMemoryException(); + break; + default : + throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection)); + break; + } + + result = sqlite3_bind_text(ppStmt, + 2, + getVerb().getName().c_str(), + -1, + SQLITE_STATIC); + switch (result) + { + case SQLITE_OK : + break; + case SQLITE_TOOBIG : + throw obelisk::DatabaseSizeException(); + break; + case SQLITE_RANGE : + throw obelisk::DatabaseRangeException(); + break; + case SQLITE_NOMEM : + throw obelisk::DatabaseMemoryException(); + break; + default : + throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection)); + break; + } + + result = sqlite3_bind_text(ppStmt, + 3, + getRightEntity().getName().c_str(), + -1, + SQLITE_STATIC); + switch (result) + { + case SQLITE_OK : + break; + case SQLITE_TOOBIG : + throw obelisk::DatabaseSizeException(); + break; + case SQLITE_RANGE : + throw obelisk::DatabaseRangeException(); + break; + case SQLITE_NOMEM : + throw obelisk::DatabaseMemoryException(); + break; + default : + throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection)); + break; + } + + result = sqlite3_step(ppStmt); + switch (result) + { + case SQLITE_DONE : + // no rows in the database + break; + case SQLITE_ROW : + setId(sqlite3_column_int(ppStmt, 0)); + getLeftEntity().setId(sqlite3_column_int(ppStmt, 1)); + getRightEntity().setId(sqlite3_column_int(ppStmt, 2)); + getVerb().setId(sqlite3_column_int(ppStmt, 3)); + setIsTrue(sqlite3_column_int(ppStmt, 4)); + break; + case SQLITE_BUSY : + throw obelisk::DatabaseBusyException(); + break; + case SQLITE_MISUSE : + throw obelisk::DatabaseMisuseException(); + break; + default : + throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection)); + break; + } + + result = sqlite3_finalize(ppStmt); + if (result != SQLITE_OK) + { + throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection)); + } +} + void obelisk::Fact::insert(sqlite3* dbConnection) { if (dbConnection == nullptr) @@ -404,12 +523,12 @@ void obelisk::Fact::setVerb(obelisk::Verb verb) verb_ = verb; } -bool& obelisk::Fact::getIsTrue() +double& obelisk::Fact::getIsTrue() { return isTrue_; } -void obelisk::Fact::setIsTrue(bool isTrue) +void obelisk::Fact::setIsTrue(double isTrue) { isTrue_ = isTrue; } diff --git a/src/lib/models/fact.h b/src/lib/models/fact.h index 6f8c7a6..f920ef4 100644 --- a/src/lib/models/fact.h +++ b/src/lib/models/fact.h @@ -46,7 +46,7 @@ namespace obelisk * @brief Whether or not the fact is considered true or not. * */ - bool isTrue_; + double isTrue_; public: /** @@ -89,7 +89,7 @@ namespace obelisk Fact(obelisk::Entity leftEntity, obelisk::Entity rightEntity, obelisk::Verb verb, - bool isTrue = false) : + double isTrue = 0) : id_(0), leftEntity_(leftEntity), rightEntity_(rightEntity), @@ -113,7 +113,7 @@ namespace obelisk obelisk::Entity leftEntity, obelisk::Entity rightEntity, obelisk::Verb verb, - bool isTrue = false) : + double isTrue = 0) : id_(id), leftEntity_(leftEntity), rightEntity_(rightEntity), @@ -191,14 +191,14 @@ namespace obelisk * @return true If the Fact is considered true. * @return false If the Fact is considered false. */ - bool& getIsTrue(); + double& getIsTrue(); /** * @brief Set the Fact as true or false. * * @param[in] isTrue Whether or not the Fact is true. */ - void setIsTrue(bool isTrue); + void setIsTrue(double isTrue); /** * @brief Select the Fact from the KnowledgeBase by IDs of the @@ -208,6 +208,14 @@ namespace obelisk */ void selectById(sqlite3* dbConnection); + /** + * @brief Select the Fact from the KnowledgeBase by the name's of + * the entities and verb. + * + * @param[in] dbConnection The database connection to use. + */ + void selectByName(sqlite3* dbConnection); + /** * @brief Insert the Fact into the KnowledgeBase. * diff --git a/src/lib/obelisk.c b/src/lib/obelisk.c index 5d959b7..9de3ded 100644 --- a/src/lib/obelisk.c +++ b/src/lib/obelisk.c @@ -4,9 +4,9 @@ #include #include -CObelisk* obelisk_open() +CObelisk* obelisk_open(const char* filename) { - return create_obelisk(); + return create_obelisk(filename); } void obelisk_close(CObelisk* obelisk) @@ -23,3 +23,11 @@ int obelisk_get_lib_version(CObelisk* obelisk) { return call_obelisk_getLibVersion(obelisk); } + +double obelisk_query(CObelisk* obelisk, + const char* left_entity, + const char* verb, + const char* right_entity) +{ + return call_obelisk_query(obelisk, left_entity, verb, right_entity); +} diff --git a/src/lib/obelisk.cpp b/src/lib/obelisk.cpp index c0eb5bf..289e22d 100644 --- a/src/lib/obelisk.cpp +++ b/src/lib/obelisk.cpp @@ -1,6 +1,12 @@ #include "include/obelisk.h" #include "version.h" +obelisk::Obelisk::Obelisk(std::string filename) +{ + kb_ = std::unique_ptr { + new obelisk::KnowledgeBase(filename.c_str())}; +} + std::string obelisk::Obelisk::getVersion() { return obelisk::version; @@ -15,10 +21,18 @@ double obelisk::Obelisk::query(const std::string& leftEntity, const std::string& verb, const std::string& rightEntity) { + obelisk::Fact fact = obelisk::Fact(obelisk::Entity(leftEntity), + obelisk::Entity(rightEntity), + obelisk::Verb(verb)); + + kb_->queryFact(fact); + + return fact.getIsTrue(); } std::string obelisk::Obelisk::query_action(const std::string& leftEntity, const std::string& verb, const std::string& rightEntity) { + return "yes"; } diff --git a/src/lib/obelisk_wrapper.cpp b/src/lib/obelisk_wrapper.cpp index 625609b..2498e90 100644 --- a/src/lib/obelisk_wrapper.cpp +++ b/src/lib/obelisk_wrapper.cpp @@ -5,9 +5,9 @@ extern "C" { - CObelisk* create_obelisk() + CObelisk* create_obelisk(const char* filename) { - obelisk::Obelisk* obelisk = new obelisk::Obelisk(); + obelisk::Obelisk* obelisk = new obelisk::Obelisk(filename); return reinterpret_cast(obelisk); } @@ -26,6 +26,18 @@ extern "C" return obelisk->getLibVersion(); } + double call_obelisk_query(CObelisk* p_obelisk, + const char* left_entity, + const char* verb, + const char* right_entity) + { + obelisk::Obelisk* obelisk + = reinterpret_cast(p_obelisk); + return obelisk->query(std::string(left_entity), + std::string(verb), + std::string(right_entity)); + } + void destroy_obelisk(CObelisk* p_obelisk) { obelisk::Obelisk* obelisk diff --git a/src/lib/obelisk_wrapper.h b/src/lib/obelisk_wrapper.h index c697816..732a31f 100644 --- a/src/lib/obelisk_wrapper.h +++ b/src/lib/obelisk_wrapper.h @@ -11,9 +11,10 @@ extern "C" /** * @brief Create a obelisk object. * + * @param[in] filename The name of the obelisk KnowledgeBase file to use. * @return CObelisk* Returns the obelisk object. */ - CObelisk *create_obelisk(); + CObelisk *create_obelisk(const char *filename); /** * @brief Calls the obelisk method getVersion. @@ -32,6 +33,20 @@ extern "C" */ int call_obelisk_getLibVersion(CObelisk *p_obelisk); + /** + * @brief Calls the obelisk method query. + * + * @param[in] p_obelisk The obelisk object pointer. + * @param[in] left_entity The left entity. + * @param[in] verb The verb. + * @param[in] right_entity The right entity. + * @return double Returns whether or not the Fact is true. + */ + double call_obelisk_query(CObelisk *p_obelisk, + const char *left_entity, + const char *verb, + const char *right_entity); + /** * @brief Delete a obelisk object. * diff --git a/src/parser.cpp b/src/parser.cpp index 907fa6b..952cdc0 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -806,9 +806,9 @@ void obelisk::Parser::handleRule(std::unique_ptr& kb) insertFact(kb, rule.getReason()); // The rule is true, so the fact must be true to. - if (rule.getReason().getIsTrue()) + if (rule.getReason().getIsTrue() > 0) { - rule.getFact().setIsTrue(true); + rule.getFact().setIsTrue(1.0); } insertEntity(kb, rule.getFact().getLeftEntity()); @@ -957,7 +957,7 @@ void obelisk::Parser::insertFact(std::unique_ptr& kb, { if (updateIsTrue) { - fact.setIsTrue(true); + fact.setIsTrue(1.0); kb->updateIsTrue(fact); } }