basic criterion and rules querying

This commit is contained in:
Green Sky 2022-08-15 01:28:02 +02:00
parent c0db6e3c30
commit 63a7fc3114
2 changed files with 163 additions and 0 deletions

View File

@ -1,2 +1,4 @@
cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
add_executable(main1 main1.cpp)

View File

@ -1,5 +1,166 @@
// this is a naive-ish implementation
// this is not pure naive, since it implements the less-branch Criterion compare variant discussed in the valve talk
#include <string>
#include <map>
#include <set>
#include <functional>
#include <limits>
#include <cassert>
// context aka, kv-dict
// criterion, predicate that returns true or false based on state and context(query)
// equal: value == min == max
// smaller: value == max -e; min == -inf
// greater: value == min +e; max == +inf
struct Criterion {
std::string key;
float min, max;
bool compare(const float x) const {
return x >= min && x <= max;
}
bool operator<(const Criterion& other) const {
return key < other.key && min < other.min && max < other.max;
}
};
// rule, list of criterions (obv &&)
struct Rules {
std::set<Criterion> crits;
};
// query, ...?
struct Query {
// sorted?
std::map<std::string, float> dict;
Query& add(const std::string& key, float value) {
dict[key] = value;
return *this;
}
Query& add(const std::string& key, const std::string& value) {
// lol
dict[key] = std::hash<std::string>{}(value);
return *this;
}
bool match_criterion(const Criterion& crit) const {
return dict.count(crit.key) && crit.compare(dict.at(crit.key));
}
bool match_rules(const Rules& rules) const {
for (const auto& crit : rules.crits) {
if (!match_criterion(crit)) {
return false;
}
}
return true;
}
};
// response -> action (list?)
struct Response {
Rules rules;
std::function<void(void)> f;
};
// special keys (usually bucketalbe):
// - concept: onHit, onIdle, onResponse, onObject?
// - "who": which char talked. gonna name this differently
struct ResponseDB {
};
int main(void) {
std::map<float, std::string> reverse_string_map;
reverse_string_map[std::hash<std::string>{}("who")] = "who";
// crit test
Criterion hp_not_critical {
"hp",
// have at least 15% of max hp
0.15f,
std::numeric_limits<float>::infinity()
};
assert(hp_not_critical.compare(0.0f) == false);
assert(hp_not_critical.compare(0.15f) == true);
assert(hp_not_critical.compare(0.15f - std::numeric_limits<float>::epsilon()) == false);
assert(hp_not_critical.compare(1.0f) == true);
Criterion is_hero {
"who",
// tmp
0.f, 0.f
};
// key "who" is value "hero"
is_hero.min = std::hash<std::string>{}("hero");
is_hero.max = std::hash<std::string>{}("hero");
assert(is_hero.compare(std::hash<std::string>{}("hero")) == true);
assert(is_hero.compare(std::hash<std::string>{}("enemy")) == false);
assert(is_hero.compare(std::hash<std::string>{}("ally")) == false);
Criterion on_idle {
"concept",
// tmp
0.f, 0.f
};
// key "concept" is value "idle"
on_idle.min = std::hash<std::string>{}("idle");
on_idle.max = std::hash<std::string>{}("idle");
assert(on_idle.compare(std::hash<std::string>{}("idle")) == true);
assert(on_idle.compare(std::hash<std::string>{}("hero")) == false);
assert(on_idle.compare(std::hash<std::string>{}("hit")) == false);
Rules rules_hero_idle_chatter {{
on_idle, is_hero, hp_not_critical
}};
// query test
Query q1{};
q1
.add("concept", "idle")
.add("who", "hero")
.add("hp", 0.843122f)
.add("ally_near", 1.f)
.add("enemy_near", 0.f)
.add("in_danger", 0.f)
;
Query q2{};
q2
.add("concept", "hit")
.add("who", "enemy")
.add("hp", 0.12333f)
.add("ally_near", 0.f)
.add("enemy_near", 1.f)
.add("in_danger", 1.f)
;
// add junk to q2
for (int i = 0; i < 10000; i++) {
q2.add(std::to_string(i) + "asdf", (i - 155) * 12399.3249f);
}
assert(q1.match_criterion(hp_not_critical) == true);
assert(q1.match_criterion(is_hero) == true);
assert(q2.match_criterion(hp_not_critical) == false);
assert(q2.match_criterion(is_hero) == false);
assert(q1.match_rules(rules_hero_idle_chatter) == true);
assert(q2.match_rules(rules_hero_idle_chatter) == false);
return 0;
}