From 3a2312174344929951bd65799f5aeb235e4ad6b3 Mon Sep 17 00:00:00 2001 From: Chris Cromer Date: Thu, 23 Feb 2023 01:07:44 -0300 Subject: [PATCH] add query for suggested actions --- src/lib/include/obelisk.h | 2 +- src/lib/include/obelisk_c.h | 15 +++++++++ src/lib/knowledge_base.cpp | 6 ++++ src/lib/knowledge_base.h | 16 +++++++++ src/lib/models/fact.cpp | 66 +++++++++++++++++++++++++++++++++++++ src/lib/models/fact.h | 11 +++++++ src/lib/obelisk.c | 8 +++++ src/lib/obelisk.cpp | 13 ++++++-- src/lib/obelisk_wrapper.cpp | 14 ++++++++ src/lib/obelisk_wrapper.h | 17 +++++++++- 10 files changed, 164 insertions(+), 4 deletions(-) diff --git a/src/lib/include/obelisk.h b/src/lib/include/obelisk.h index b078614..1e434bc 100644 --- a/src/lib/include/obelisk.h +++ b/src/lib/include/obelisk.h @@ -73,7 +73,7 @@ namespace obelisk * @param[in] rightEntity The right entity. * @return std::string Returns the suggested action. */ - std::string query_action(const std::string& leftEntity, + std::string queryAction(const std::string& leftEntity, const std::string& verb, const std::string& rightEntity); }; diff --git a/src/lib/include/obelisk_c.h b/src/lib/include/obelisk_c.h index fa5ab83..d1f0294 100644 --- a/src/lib/include/obelisk_c.h +++ b/src/lib/include/obelisk_c.h @@ -50,6 +50,21 @@ extern "C" const char* verb, const char* right_entity); + /** + * @brief Query the obelisk KnowledgeBase to get a suggested Action to do. + * + * @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 char* Returns the Action to do or an empty string if there is no + * action. + */ + extern char* obelisk_query_action(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 ec345df..36e250e 100644 --- a/src/lib/knowledge_base.cpp +++ b/src/lib/knowledge_base.cpp @@ -264,6 +264,12 @@ void obelisk::KnowledgeBase::queryFact(obelisk::Fact& fact) fact.selectByName(dbConnection_); } +void obelisk::KnowledgeBase::querySuggestAction(obelisk::Fact& fact, + obelisk::Action& action) +{ + fact.selectActionByFact(dbConnection_, action); +} + 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 24ae8bf..4930033 100644 --- a/src/lib/knowledge_base.h +++ b/src/lib/knowledge_base.h @@ -200,8 +200,24 @@ namespace obelisk */ void updateIsTrue(obelisk::Fact& fact); + /** + * @brief Query the KnowledgeBase to see if a Fact is true or false. + * + * @param[in] fact The Fact to check. + */ void queryFact(obelisk::Fact& fact); + /** + * @brief Query the KnowledgeBase to get a suggested action based + * on a Fact. + * If a SuggestAction doesn't exist, it will return an empty Action. + * + * @param[in] fact The Fact to search for. + * @param[out] action The Action that is suggested to take. + */ + void querySuggestAction(obelisk::Fact& fact, + obelisk::Action& action); + /** * @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 5bfc1ca..874e0cd 100644 --- a/src/lib/models/fact.cpp +++ b/src/lib/models/fact.cpp @@ -276,6 +276,72 @@ void obelisk::Fact::selectByName(sqlite3* dbConnection) } } +void obelisk::Fact::selectActionByFact(sqlite3* dbConnection, + obelisk::Action& action) +{ + if (dbConnection == nullptr) + { + throw obelisk::DatabaseException("database isn't open"); + } + + sqlite3_stmt* ppStmt = nullptr; + + auto result = sqlite3_prepare_v2(dbConnection, + "SELECT CASE f.is_true WHEN 0 THEN (SELECT name FROM action WHERE id = fa.id) WHEN 1 THEN (SELECT name from action WHERE id = ta.id) END action FROM suggest_action LEFT JOIN action ta ON ta.id = suggest_action.true_action LEFT JOIN action fa ON fa.id = suggest_action.false_action LEFT JOIN fact f ON f.id = suggest_action.fact WHERE (f.id = ?)", + -1, + &ppStmt, + nullptr); + if (result != SQLITE_OK) + { + throw obelisk::DatabaseException(sqlite3_errmsg(dbConnection)); + } + + result = sqlite3_bind_int(ppStmt, 1, getId()); + 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 : + action.setName((char*) sqlite3_column_text(ppStmt, 0)); + 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) diff --git a/src/lib/models/fact.h b/src/lib/models/fact.h index f920ef4..21810b2 100644 --- a/src/lib/models/fact.h +++ b/src/lib/models/fact.h @@ -1,6 +1,7 @@ #ifndef OBELISK_MODELS_FACT_H #define OBELISK_MODELS_FACT_H +#include "models/action.h" #include "models/entity.h" #include "models/fact.h" #include "models/verb.h" @@ -216,6 +217,16 @@ namespace obelisk */ void selectByName(sqlite3* dbConnection); + /** + * @brief Select an Action from the KnowledgeBase using the provided + * Fact. + * + * @param[in] dbConnection The database connection to use. + * @param[out] action The Action to take based on the provided fact. + */ + void selectActionByFact(sqlite3* dbConnection, + obelisk::Action& action); + /** * @brief Insert the Fact into the KnowledgeBase. * diff --git a/src/lib/obelisk.c b/src/lib/obelisk.c index 9de3ded..3d41055 100644 --- a/src/lib/obelisk.c +++ b/src/lib/obelisk.c @@ -31,3 +31,11 @@ double obelisk_query(CObelisk* obelisk, { return call_obelisk_query(obelisk, left_entity, verb, right_entity); } + +char* obelisk_query_action(CObelisk* obelisk, + const char* left_entity, + const char* verb, + const char* right_entity) +{ + return call_obelisk_queryAction(obelisk, left_entity, verb, right_entity); +} diff --git a/src/lib/obelisk.cpp b/src/lib/obelisk.cpp index 289e22d..e2bb414 100644 --- a/src/lib/obelisk.cpp +++ b/src/lib/obelisk.cpp @@ -30,9 +30,18 @@ double obelisk::Obelisk::query(const std::string& leftEntity, return fact.getIsTrue(); } -std::string obelisk::Obelisk::query_action(const std::string& leftEntity, +std::string obelisk::Obelisk::queryAction(const std::string& leftEntity, const std::string& verb, const std::string& rightEntity) { - return "yes"; + obelisk::Fact fact = obelisk::Fact(obelisk::Entity(leftEntity), + obelisk::Entity(rightEntity), + obelisk::Verb(verb)); + + kb_->queryFact(fact); + + obelisk::Action action; + kb_->querySuggestAction(fact, action); + + return action.getName(); } diff --git a/src/lib/obelisk_wrapper.cpp b/src/lib/obelisk_wrapper.cpp index 2498e90..be9b13a 100644 --- a/src/lib/obelisk_wrapper.cpp +++ b/src/lib/obelisk_wrapper.cpp @@ -38,6 +38,20 @@ extern "C" std::string(right_entity)); } + char* call_obelisk_queryAction(CObelisk* p_obelisk, + const char* left_entity, + const char* verb, + const char* right_entity) + { + obelisk::Obelisk* obelisk + = reinterpret_cast(p_obelisk); + auto temp = obelisk->queryAction(std::string(left_entity), + std::string(verb), + std::string(right_entity)); + auto action = strdup(temp.c_str()); + return action; + } + void destroy_obelisk(CObelisk* p_obelisk) { obelisk::Obelisk* obelisk diff --git a/src/lib/obelisk_wrapper.h b/src/lib/obelisk_wrapper.h index 732a31f..b8c4b6d 100644 --- a/src/lib/obelisk_wrapper.h +++ b/src/lib/obelisk_wrapper.h @@ -20,7 +20,7 @@ extern "C" * @brief Calls the obelisk method getVersion. * * @param[in] p_obelisk The obelisk object pointer. - * @return const char* Returns the version. This must be freed by the + * @return char* Returns the version. This must be freed by the * caller. */ char *call_obelisk_getVersion(CObelisk *p_obelisk); @@ -47,6 +47,21 @@ extern "C" const char *verb, const char *right_entity); + /** + * @brief Calls the obelisk method queryAction. + * + * @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 char* Returns the sugggested action to take or an empty string if + * no action is found. This must be freed by the caller. + */ + char *call_obelisk_queryAction(CObelisk *p_obelisk, + const char *left_entity, + const char *verb, + const char *right_entity); + /** * @brief Delete a obelisk object. *